---
name: x-bookmark-capture-sync
description: Fetch saved X bookmarks on a schedule, dedupe them locally, and create raw capture issues in GitHub Issues for later processing by a person or agent.
---

# X Bookmark Capture Sync

Use this skill when a user wants to turn their own X bookmarks into GitHub inbox items, run a daily bookmark capture cron job, backfill a bookmark backlog, or inspect the cost and setup for X API bookmark reads.

## Workflow

1. Confirm the user has an X API app with OAuth 2.0 enabled and a GitHub token that can create issues in the target repo.
2. Configure these environment variables:
   - `X_CLIENT_ID`
   - `X_REDIRECT_URI`
   - Optional for confidential X OAuth apps: `X_CLIENT_SECRET`
   - `GITHUB_TOKEN`
   - Optional: `GITHUB_REPOSITORY` (defaults to `buildleansaas/obsidian-vault`)
   - Optional: `GITHUB_ISSUE_LABELS` (defaults to `inbox,agent-ready`; missing configured labels are skipped and the script falls back to `x-inbox` or `inbox` if needed)
   - Optional: `BOOKMARK_SYNC_STATE_PATH`
   - Optional: `GITHUB_ISSUE_CAP` (defaults to `200`; set `0` only if you intentionally want to disable the cost guard)
3. Ask for the X OAuth scopes `tweet.read users.read bookmark.read offline.access`.
4. Run `node scripts/bookmark-capture-sync.mjs auth-url` and open the returned URL.
5. Run `node scripts/bookmark-capture-sync.mjs exchange --code <code> --state <state>` with the callback code and state.
6. Run `node scripts/bookmark-capture-sync.mjs sync --dry-run` to preview planned GitHub issues.
7. Run `node scripts/bookmark-capture-sync.mjs sync --stop-after-seen` daily from cron.
   - Use `--page-size 25` or another smaller value when the daily job should cap returned bookmarks below 100.
8. For the first backlog clear, run `node scripts/bookmark-capture-sync.mjs backfill --pages all`.

## Behavior

- Checks GitHub inbox capacity before making any X API bookmark/user calls: if open issues matching the configured inbox labels in `GITHUB_REPOSITORY` are at or above `GITHUB_ISSUE_CAP` (default `200`), exits without spending X credits.
- Reads the authenticated user's bookmarks from `GET /2/users/:id/bookmarks`.
- Requests up to 100 bookmarks per page.
- Creates or reuses one GitHub issue per new bookmark in `buildleansaas/obsidian-vault` by default.
- Labels every captured issue with existing repo labels, defaulting to `inbox` + `agent-ready` for `buildleansaas/obsidian-vault`; missing configured labels are skipped instead of auto-creating taxonomy.
- Creates missing GitHub labels when the token has permission.
- Dedupes by tweet ID in local state and by source URL search in GitHub if state is missing.
- Stores OAuth token data, processed tweet IDs, and GitHub issue metadata in local JSON state.
- Supports `--dry-run`, `--pages all|<n>`, and `--stop-after-seen`.
- Supports `--page-size <1-100>` to control maximum returned bookmarks per page.
- Does not delete X bookmarks in v1.

## Cron Example

```cron
15 8 * * * cd /path/to/bookmark-capture-sync && /usr/bin/env node scripts/bookmark-capture-sync.mjs sync --stop-after-seen >> sync.log 2>&1
```

## Cost Notes

X currently prices owned bookmark reads as owned read resources. For a personal workflow, expect roughly 500 returned bookmarks to cost about $0.50, and a daily first page of up to 100 bookmarks to cost up to about $0.10 per day. Always check the X Developer Console before relying on these numbers.

## Follow-up skill

Keep this skill deterministic. Use a separate Hermes/Codex heartbeat skill to score and triage the raw GitHub inbox issues after capture.
