@usesocial/cli 0.7.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,222 @@
1
1
  # @usesocial/cli
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`90cd296`](https://github.com/usesocial/monorepo/commit/90cd2967a18a271337c54414466c5d89e66649d2) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - `social account logs` auto-paginates and aggregates for spend audits.
8
+
9
+ - `--limit` above the server's 100-row page cap now follows `.meta.cursor`
10
+ across pages transparently and returns one merged envelope.
11
+ - `--sum-by <fields>` (comma-separated from `platform`, `path`, `method`,
12
+ `day`, `cacheStatus`) aggregates the selected window into
13
+ `{ …key, calls, credits, errors }` rows sorted by credits descending —
14
+ a one-command answer to "what did my agent spend this week, on what".
15
+ - `createdAt` is always an ISO string, and the declared contract stays
16
+ JSON-Schema-serializable (`social schema --leaves` works).
17
+
18
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`b8cddb4`](https://github.com/usesocial/monorepo/commit/b8cddb4d4c5c290a2add9498ce94c906427a12e5) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Error output and diagnostics are now debuggable end-to-end.
19
+
20
+ - API error JSON printed to stderr now includes a top-level `code` (stable
21
+ snake_case API error code) and `requestId` — quote the request id when
22
+ reporting a bug and we can trace the exact server-side call.
23
+ - Rate-limited commands surface `retryCount` and `retryBudgetExhausted` on the
24
+ error payload alongside the existing `retryAfterSeconds`.
25
+ - Diagnostic telemetry (opt-out unchanged: `DO_NOT_TRACK=1` /
26
+ `SOCIAL_DO_NOT_TRACK=1`) now records every command failure — not just API
27
+ 5xx — with a privacy-safe fingerprint (error class + status + stable code)
28
+ instead of raw messages. The first-run privacy promise is unchanged: no
29
+ arguments, stdin, response bodies, handles, or content ever leave the
30
+ machine.
31
+ - Crashes, unhandled rejections, and Ctrl-C now flush diagnostics before
32
+ exiting (signals exit `130`/`143`); a closed stdout pipe (`head`, `jq -e`)
33
+ exits `0` quietly instead of crashing.
34
+
35
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`e3fb8a2`](https://github.com/usesocial/monorepo/commit/e3fb8a2d09301494d95115f8409862d392d78fcb) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Schema contracts now declare advisory hazards instead of confirmation gates:
36
+ `confirmation.{required,recommended}` is replaced by `hazard { kind:
37
+ spends_credits | destructive | outbound_write, confirm: "advisory" }` on
38
+ mutating commands (billing portal and connect declare nothing). Non-TTY
39
+ `account login` and `account connect` become pollable state machines that
40
+ advance one step per call — `pending_approval { verificationURL, expiresAt }`
41
+ through `logged_in` / `connected` — with the in-flight device code persisted
42
+ between calls. New get-started skill reference walks agents through
43
+ login → connect → cost-estimated first sync.
44
+
45
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`84797f6`](https://github.com/usesocial/monorepo/commit/84797f67c496cef4f5e26b740550166dacba3876) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - `social linkedin message <target>` now accepts `--media <path>` (repeatable) to
46
+ attach files to a new or existing conversation. The caption (piped on stdin)
47
+ becomes optional when media is present, and the combined attachments must stay
48
+ under 20 MB. Media types are detected from file content (magic bytes) and render
49
+ natively.
50
+
51
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`f9c9916`](https://github.com/usesocial/monorepo/commit/f9c9916e67699ab1640b621205bb0ba498b061d5) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - `social linkedin post` now attaches media and supports quoting and posting as a
52
+ company. Pipe the caption on stdin as before, or omit it entirely when attaching
53
+ media or quoting.
54
+
55
+ - `--media <path>` (repeatable) attaches local files inline (base64). The media
56
+ type is detected from the file's content (magic bytes). LinkedIn allows
57
+ multiple images, OR a single non-image file (video, PDF, document).
58
+ - `--quote <post>` quotes/reposts an existing post — a LinkedIn post URL,
59
+ `post_id:<id>`, or URN. With caption text it's a quote post; with empty text
60
+ it's a bare repost.
61
+ - `--as <company>` publishes on behalf of a company you admin — a numeric
62
+ company id, or a company URL/vanity that is resolved to its id.
63
+
64
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`b89c2f9`](https://github.com/usesocial/monorepo/commit/b89c2f96d1acc4dfe21b796a9332732fa60681b4) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Own-data live reads now require a target; your own data is the local mirror.
65
+
66
+ `social x tweets`, `x followers`, `x following`, `x liked`, `x mentions`, and
67
+ `linkedin connections` invoked without a target no longer fall back to a
68
+ metered self-read. Each fails with a teaching error naming the free local
69
+ path instead — e.g. `social x sync tweets` then
70
+ `social x sql "SELECT text, like_count, impression_count FROM x_tweets ORDER BY created_at DESC LIMIT 25"`.
71
+ Live reads are for someone else's graph; `sync` + `sql` is the own-data
72
+ surface. A literal `@me`/`@self` target still resolves to that real X
73
+ username but emits a note pointing at the sync+sql path.
74
+
75
+ Bare `social x sync` / `social linkedin sync` listings now include
76
+ `totalRows` (current local table count) beside `objectCount` (last run's
77
+ fetched count), so a caught-up sync no longer reads as an empty mirror.
78
+
79
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`90cd296`](https://github.com/usesocial/monorepo/commit/90cd2967a18a271337c54414466c5d89e66649d2) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Cursor-based syncs are resumable after rate limits and aborts.
80
+
81
+ Sync progress (page cursor and phase, including LinkedIn messages' two-phase
82
+ conversations→messages walk) is persisted after every stored page. When a
83
+ sync dies mid-run — most commonly a LinkedIn `/chats` 429 — the rate-limit
84
+ JSON now reports `syncResume.cursorPersisted: true` with `behavior: "resume"`,
85
+ and re-running the printed `retryCommand` continues from the saved cursor
86
+ instead of restarting and re-billing already-fetched pages. Resume only
87
+ applies to the same collection, account, and `--since` window; `--reset`
88
+ clears saved cursors; a clean completion replaces them with the normal
89
+ checkpoint.
90
+
91
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`90cd296`](https://github.com/usesocial/monorepo/commit/90cd2967a18a271337c54414466c5d89e66649d2) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Successful writes now update the local SQL mirror immediately.
92
+
93
+ - `social x message` inserts the sent DM into `x_messages` using the send
94
+ response (and upserts the recipient profile, so `counterpart_username`
95
+ resolves even for conversations where the other side has never replied).
96
+ - `social linkedin requests cancel` / `accept` remove the pending row from
97
+ `li_requests`; `requests send` inserts the new sent row.
98
+ - `social x bookmark` / `unbookmark` add and remove `x_bookmarks` rows.
99
+ - `social linkedin message` inserts into `li_messages` once that collection
100
+ has been synced.
101
+
102
+ Your own write is queryable via `sql` the moment the command succeeds — no
103
+ re-sync, and no `--reset` (which re-bills a collection's full history) just
104
+ to verify a send. Write-through only applies to collections that have been
105
+ synced at least once, and a mirror write failure never breaks a successful
106
+ command: it degrades to a stderr warning.
107
+
108
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`4824400`](https://github.com/usesocial/monorepo/commit/4824400ebcabb56f27f616418b0e62bc382c8fae) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Posting now updates the local SQL mirror immediately, like messages and
109
+ bookmarks already do.
110
+
111
+ - `social x post` inserts the created post into `x_tweets` from the send
112
+ response; `social x delete` removes the row.
113
+ - `social linkedin post` inserts into `li_posts` when the response carries a
114
+ usable post id (`post_id` or `id`); without one the mirror write is skipped
115
+ silently.
116
+
117
+ Rows are sparse until the next sync enriches them from upstream (engagement
118
+ counters arrive then). Same semantics as the existing write-throughs: only
119
+ applies once the collection has been synced at least once, and a mirror
120
+ failure degrades to a stderr warning without breaking the command.
121
+
122
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`b89c2f9`](https://github.com/usesocial/monorepo/commit/b89c2f96d1acc4dfe21b796a9332732fa60681b4) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - `liked` and `mentions` are now syncable X collections with local mirror twins.
123
+
124
+ - `social x sync liked` populates `x_liked`; `social x sync mentions`
125
+ populates `x_mentions`. Both are tweet-shaped (text, url, created_at, all
126
+ public metrics, author columns) and query free via `social x sql`.
127
+ - `mentions` supports `--since <ISO date>` for cheap incremental pulls;
128
+ `liked` does not (the upstream API has no time filter — re-syncs walk from
129
+ the newest like to the local checkpoint).
130
+ - Sync requests carry the full live-read field presets, so mirror rows land
131
+ with `created_at` and metrics populated from the first pull.
132
+ - `social x like <post>` inserts the post into `x_liked` immediately on
133
+ success and `unlike` removes it — no re-sync needed to see your own action,
134
+ once the collection has been synced at least once.
135
+
136
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`a902314`](https://github.com/usesocial/monorepo/commit/a9023144ca92f9cc87dd753239b572e6d0f3bfda) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - `social x post` now attaches media and creates native polls. Pipe the caption
137
+ on stdin as before, or omit it entirely when attaching media — text is optional
138
+ once media is present.
139
+
140
+ - `--media <path>` (repeatable) uploads local image/gif/video files via X's
141
+ chunked upload, then attaches them. X combinatorics apply: up to 4 images, OR
142
+ 1 gif, OR 1 video — no mixing.
143
+ - `--media-id <id>` (repeatable) attaches an already-uploaded media id, skipping
144
+ upload (useful for retries).
145
+ - `--poll-option <text>` (repeatable, 2–4) with `--poll-duration <minutes>`
146
+ (5–10080) creates a native poll. Mutually exclusive with media.
147
+ - `--reply-settings <following|mentionedUsers|subscribers|verified>` limits who
148
+ can reply.
149
+ - `--timeout <seconds>` sets the wait budget for video/gif processing
150
+ (default 300).
151
+ - `--reply-to <post>`, `--account <selector>`, and the `--body <JSON>` escape
152
+ hatch for long-tail post fields (media title/description, `tagged_user_ids`,
153
+ `quote_tweet_id`, `made_with_ai`, community, geo, nullcast) are restored for
154
+ `post`.
155
+
156
+ Uploading media is free; each finalized file costs a flat 15 credits at the
157
+ finalize step, independent of file size, on top of the normal post-create
158
+ credits.
159
+
160
+ Posting media requires the `media.write` OAuth scope. Existing connected X
161
+ accounts must run `social account reconnect x <account>` to gain it — OAuth
162
+ scope upgrades are not retroactive.
163
+
164
+ ### Patch Changes
165
+
166
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`90cd296`](https://github.com/usesocial/monorepo/commit/90cd2967a18a271337c54414466c5d89e66649d2) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - `social linkedin message <person>` starts new conversations again.
167
+
168
+ Person-target sends (profile URL, `@username`, `profile_id:<id>`, URN) were
169
+ rejected upstream after the provider's v2 migration. New chats now follow the
170
+ v2 inbox contract — the CLI resolves the person, discovers the LinkedIn
171
+ classic inbox, and starts the chat there. The command's contract models both
172
+ response shapes: `MessageSent` for existing-chat sends (`chat_id:<id>`),
173
+ `ChatStarted` (with the new `chat_id`) for first messages.
174
+
175
+ - [#35](https://github.com/usesocial/monorepo/pull/35) [`0dacb7f`](https://github.com/usesocial/monorepo/commit/0dacb7fadb59067787e167e8a3ae84fcde673fe7) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Internal: the profile write-through primitives (`upsertProfiles`,
176
+ `lookupProfiles`, `ProfileRow`) moved from `@usesocial/api/proxy` to
177
+ `@usesocial/db/profiles`; the proxy re-exports them unchanged. No CLI-visible
178
+ behavior change.
179
+
180
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`5a2e56e`](https://github.com/usesocial/monorepo/commit/5a2e56e7fbd4b27edc11990192639aa9404f19b1) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Report local SQLite cache auto-migrations in JSON output instead of stderr banners.
181
+ Breaking: all `social x sync...` and `social linkedin sync...` outputs now return
182
+ `{ data, meta }`; previous bare sync arrays and summary/reset objects now live
183
+ under `.data`, and migration details appear under `.meta.cache.migration` only
184
+ when a cache migration runs.
185
+
186
+ - [#34](https://github.com/usesocial/monorepo/pull/34) [`90cd296`](https://github.com/usesocial/monorepo/commit/90cd2967a18a271337c54414466c5d89e66649d2) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - X syncs request full field presets, and incremental message refreshes are
187
+ ~10x cheaper.
188
+
189
+ - `social x sync tweets` / `bookmarks` / `followers` / `following` now send
190
+ the same field presets as live reads, so mirror rows land with `created_at`
191
+ and `public_metrics` populated — previously the upstream returned minimal
192
+ objects and the documented own-content audit recipe (`like_count`,
193
+ `impression_count`, …) silently came back all-NULL. Mirrors synced before
194
+ this fix need one `--reset` re-pull to heal (metered).
195
+ - Sync summaries gain an additive `warnings[]`; a `fieldCompleteness` warning
196
+ fires if a page arrives missing expected fields, so silent starvation
197
+ cannot recur.
198
+ - Checkpointed `x sync messages` refreshes request small pages instead of
199
+ full 100-event pages, cutting a caught-up refresh from ~1,470 to ~150
200
+ credits. `stoppedReason: "checkpoint"` now carries a note explaining it
201
+ means "caught up: no new events since the last sync checkpoint".
202
+
203
+ ## 0.8.0
204
+
205
+ ### Minor Changes
206
+
207
+ - [#33](https://github.com/usesocial/monorepo/pull/33) [`abb6401`](https://github.com/usesocial/monorepo/commit/abb64017354f4607a25d321f115d5063ad3d4117) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Remove `social account config cache mode`; configure live-read proxy caching with `social account config cache ttl` only.
208
+
209
+ - [#33](https://github.com/usesocial/monorepo/pull/33) [`2c315ba`](https://github.com/usesocial/monorepo/commit/2c315ba6ba0f8279b9bad05928450d5666476627) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Add sync `--timeout` rate-limit wait budgets and resumable rate-limit abort guidance.
210
+
211
+ - [#33](https://github.com/usesocial/monorepo/pull/33) [`76d03f2`](https://github.com/usesocial/monorepo/commit/76d03f21d6e2e2214f85338c8cb13c4eae2a96c3) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Rebuild the local SQL mirror as curated views and slim the schema surfaces.
212
+
213
+ - Every cache table is now a view over a `<name>_raw` physical table. Views drop `raw`/`synced_at` (a `SELECT *` row is ~5× smaller) and normalize names across platforms: `username`/`name`/`avatar_url` everywhere, `created_at` (was `timestamp`), `conversation_id` (was `chat_id`/`dm_conversation_id`), `last_message_at`, `is_mentioned`, `*_distance`. Upstream JSON stays queryable in the `_raw` twins via `json_extract(raw, '$.field')`. Existing caches migrate automatically.
214
+ - Promoted raw fields: `li_requests.message` (invitation note text) and `x_profiles.receives_your_dm`.
215
+ - `li_posts` is a curated ~29-column view; the quoted-post/permissions long tail lives in `li_posts_raw`.
216
+ - Bare `social <platform> sql` now prints compact schema metadata — column lists, row counts, `synced_at`, `query_ready`, indexed columns, join hints, and enum values — instead of raw `CREATE TABLE` statements (~35% smaller).
217
+ - `social schema` output is leaner: the redundant `params` field is gone (use `args`/`flags`/`inputSchema`), `schemaVersion` prints once at the root, and empty `subCommands` are omitted (`--leaves` is ~26% smaller).
218
+ - `sql` contract examples are projected queries on `x_followers`, `x_following`, and `li_connections`.
219
+
3
220
  ## 0.7.1
4
221
 
5
222
  ### Patch Changes
package/README.md CHANGED
@@ -25,6 +25,12 @@ Published as `@usesocial/cli` on npm; the binary is `social`.
25
25
  curl -fsSL https://usesocial.dev/install.sh | bash
26
26
  ```
27
27
 
28
+ Or with Homebrew:
29
+
30
+ ```sh
31
+ brew install usesocial/tap/cli
32
+ ```
33
+
28
34
  ## Quickstart
29
35
 
30
36
  ```sh
@@ -56,7 +62,7 @@ marked **local** update local CLI state or the local mirror.
56
62
 
57
63
  ### Targets
58
64
 
59
- Targets accept handles, profile/post/conversation/company URLs, LinkedIn URNs,
65
+ Targets accept usernames, profile/post/conversation/company URLs, LinkedIn URNs,
60
66
  or typed IDs such as `profile_id:<id>`, `post_id:<id>`, `chat_id:<id>`,
61
67
  `conversation_id:<id>`, `company_id:<id>`, and `request_id:<id>`. Bare IDs are
62
68
  not accepted.
@@ -69,25 +75,48 @@ freeform text from stdin. There is no text positional:
69
75
  ```sh
70
76
  echo "gm" | social x post
71
77
  social linkedin post < draft.md
72
- social linkedin requests send @handle < note.txt
78
+ social linkedin requests send @username < note.txt
73
79
  ```
74
80
 
75
81
  Pipe a JSON object for advanced payload fields.
76
82
 
77
- ## Your data is local
83
+ ### Pagination
84
+
85
+ Live list reads take `--limit`. X lists and LinkedIn `posts`/`connections`
86
+ continue with `--cursor` from `.meta.cursor`; LinkedIn `search`, `comments`,
87
+ `reactions`, and `jobs` continue with `--offset`. `sql` does not paginate —
88
+ use SQL `LIMIT` and `ORDER BY`.
89
+
90
+ ### Your data is local
78
91
 
79
92
  `sync` pulls your own data down; it is explicit and costs credits. `sql` queries
80
93
  that local mirror; it is free, instant, and read-only. Named read commands call
81
94
  the live network and cost credits; `x tweets <target>` and
82
95
  `linkedin posts <target>` require a target. Writes act.
83
96
 
97
+ `sync` output is always `{ data, meta }`: bare `sync` lists collections under
98
+ `.data[]`, while collection summaries and `--reset` results live under `.data`.
99
+ `sync <collection> --since 2026-05-04` (ISO date or datetime) pulls only newer
100
+ items where the bare `sync` listing shows `supportsSince: true` — cheaper than a
101
+ full re-pull. `sync <collection> --reset` clears a collection's local rows and
102
+ sync state so the next sync rebuilds it.
103
+ `sync <collection> --timeout 900` opts into a wall-clock wait budget, in seconds,
104
+ for rate-limit handling. LinkedIn sync may sleep and retry while the next wait
105
+ fits the budget; X keeps its current no-new-retry behavior.
106
+
107
+ Rate-limit JSON includes `retryAfterSeconds`, `resumeAt`, `retryCommand`,
108
+ `hint`, and `syncResume`. When `syncResume.cursorPersisted` is true, already
109
+ synced pages are saved and the listed `retryCommand` resumes from the saved
110
+ cursor. For parent/child message syncs, the hint says when an exact cursor
111
+ resume is not safe and the re-run may re-fetch unfinished pages.
112
+
84
113
  ```sh
85
114
  social x sync messages
86
- social x sql "SELECT sender_handle, text, datetime(created_at/1000,'unixepoch') AS at FROM x_messages ORDER BY created_at DESC LIMIT 20" \
115
+ social x sql "SELECT sender_username, text, datetime(created_at/1000,'unixepoch') AS at FROM x_messages ORDER BY created_at DESC LIMIT 20" \
87
116
  | jq '.items[]'
88
117
  ```
89
118
 
90
- The X inbox query gets `sender_handle` from the `x_messages` view; no extra
119
+ The X inbox query gets `sender_username` from the `x_messages` view; no extra
91
120
  profile lookup is needed.
92
121
 
93
122
  ### Top level
@@ -117,26 +146,25 @@ profile lookup is needed.
117
146
  | `billing portal` | Open the hosted billing portal and print its URL. | |
118
147
  | `usage` | Aggregate proxy calls and credits. | |
119
148
  | `logs` | Recent proxy calls. | |
120
- | `config cache mode` | Read or set the live-read proxy cache mode. | |
121
- | `config cache ttl` | Set a live-read proxy cache TTL in seconds. | |
149
+ | `config cache ttl` | Read or set the live-read proxy cache TTL in seconds. | |
122
150
 
123
151
  ### `social linkedin`
124
152
 
125
153
  | Command | Description | |
126
154
  | --- | --- | --- |
127
155
  | `profile [target]` | Fetch a profile; omit target for your own account. | |
128
- | `posts <target>` | Live posts for a person or company; target required. Supports `--limit` and `--cursor` from `.meta.cursor`. | |
129
- | `comments <target>` | List a post's comments; supports `--limit` and `--offset`. | |
130
- | `reactions <target>` | List a post's reactions; supports `--limit` and `--offset`. | |
131
- | `connections [target]` | Live connection graph read; omit target for your own account. Supports `--limit` and `--cursor` from `.meta.cursor`. Costs credits. | |
156
+ | `posts <target>` | Live posts for a person or company; target required. | |
157
+ | `comments <target>` | List a post's comments. | |
158
+ | `reactions <target>` | List a post's reactions. | |
159
+ | `connections [target]` | Live connection graph read; omit target for your own account. Costs credits. | |
132
160
  | `company <target>` | Fetch a company profile. | |
133
- | `jobs <target>` | List a company's job postings; supports `--limit` and `--offset`. | |
134
- | `search people\|posts\|jobs\|companies <keywords>` | Search LinkedIn; live offset-paginated reads. | |
161
+ | `jobs <target>` | List a company's job postings. | |
162
+ | `search people\|posts\|jobs\|companies <keywords>` | Search LinkedIn. | |
135
163
  | `sync [collection]` | Pull your own `connections`, `posts`, `messages`, or `requests` into the local mirror; costs credits. | local |
136
- | `sql [query]` | Query your synced local mirror with read-only SQL - free; bare `sql` prints the schema. | |
164
+ | `sql [query]` | Query your synced local mirror with read-only SQL - free; bare `sql` prints compact schema metadata. | |
137
165
  | `post` | Create a post (body from stdin). | write |
138
166
  | `comment <target>` | Comment on a post (body from stdin). | write |
139
- | `react <target>` | React to a post or comment; use `--type` for non-like reactions. | write |
167
+ | `react <target>` | React to a post; use `--type` for non-like reactions. | write |
140
168
  | `requests send <target>` | Send a connection request (optional note from stdin). | write |
141
169
  | `requests accept request_id:<id>` | Accept a received connection request. | write |
142
170
  | `requests cancel request_id:<id>` | Cancel a sent request or refuse a received connection request. | write |
@@ -163,7 +191,7 @@ profile lookup is needed.
163
191
  | `likers <target>` | List users who liked a post. | |
164
192
  | `reposters <target>` | List users who reposted a post. | |
165
193
  | `sync [collection]` | Pull your own `tweets`, `followers`, `following`, `bookmarks`, or `messages` into the local mirror; costs credits. | local |
166
- | `sql [query]` | Query your synced local mirror with read-only SQL - free; bare `sql` prints the schema. | |
194
+ | `sql [query]` | Query your synced local mirror with read-only SQL - free; bare `sql` prints compact schema metadata. | |
167
195
  | `post` | Create a post (body from stdin). | write |
168
196
  | `message <recipients>` | Send a DM (body from stdin). | write |
169
197
  | `like <target>` / `unlike <target>` | Like or unlike a post. | write |
@@ -176,15 +204,16 @@ profile lookup is needed.
176
204
 
177
205
  - Everything speaks JSON: success on stdout, structured errors on stderr.
178
206
  - Platform reads return one envelope: lists use `.items[]`, single resources use
179
- `.data`, metadata lives under `.meta`. `social account` service commands return
180
- bare JSON; `account logs` returns `{ items, meta: { cursor } }`.
207
+ `.data`, metadata lives under `.meta`. Sync commands use `{ data, meta }`.
208
+ `social account` service commands return bare JSON; `account logs` returns
209
+ `{ items, meta: { cursor } }`.
181
210
  - Schema-backed planning: `social schema --list` is the compact runnable index.
182
211
  - Local SQL is the free surface for your own synced data.
183
212
 
184
213
  ```sh
185
214
  # SQL insight: synced contacts you have never messaged.
186
215
  # Run `social linkedin sync connections` and `social linkedin sync messages` first.
187
- social linkedin sql "SELECT c.user_display_name, c.user_public_identifier, c.user_profile_url FROM li_connections c LEFT JOIN li_messages m ON m.sender_id = c.user_id WHERE m.id IS NULL ORDER BY c.created_at DESC LIMIT 100" \
216
+ social linkedin sql "SELECT c.user_name, c.user_username, c.user_profile_url FROM li_connections c LEFT JOIN li_messages m ON m.sender_id = c.user_id WHERE m.id IS NULL ORDER BY c.created_at DESC LIMIT 100" \
188
217
  | jq '.items[]'
189
218
 
190
219
  # Live fan-out: review recent posts, fan out to reactions, rank warm contacts.
@@ -192,8 +221,8 @@ social linkedin posts profile_id:<profile-id> --limit 25 > /tmp/recent-posts.jso
192
221
  jq -r '.items[].id' /tmp/recent-posts.json \
193
222
  | xargs -I{} social linkedin reactions post_id:{} --limit 100 --offset 0 \
194
223
  | jq -s '[ .[] | .items[] ]
195
- | group_by(.actor.id // .reactor.id // .profile_id)
196
- | map({person: (.[0].actor // .[0].reactor), signals: length})
224
+ | group_by(.sender.id)
225
+ | map({person: .[0].sender, signals: length})
197
226
  | sort_by(-.signals) | .[0:15]'
198
227
  ```
199
228
 
@@ -206,7 +235,7 @@ jq -r '.items[].id' /tmp/recent-posts.json \
206
235
  | `3` | Not found | Check the resource ID or pick a different item. |
207
236
  | `4` | Auth or scope error | Run `social account login`, or log out and choose the needed scope. |
208
237
  | `5` | API, proxy, or unexpected error | Retry later or surface the server error. |
209
- | `7` | Rate limited | Back off, using `retryAfterSeconds` when present. |
238
+ | `7` | Rate limited | Back off, using `retryAfterSeconds`, `resumeAt`, and `retryCommand` when present. |
210
239
 
211
240
  ## Auth
212
241
 
@@ -230,26 +259,22 @@ The proxy cache applies to live reads only. Cache hits are free; fresh upstream
230
259
  reads are metered. Configure the default:
231
260
 
232
261
  ```sh
233
- social account config cache mode
234
- social account config cache mode live
235
- social account config cache mode analytical
236
- social account config cache mode historical
237
262
  social account config cache ttl 3600
238
263
  ```
239
264
 
240
265
  Override one live read when the command lists `--header`:
241
266
 
242
267
  ```sh
243
- social linkedin profile @handle -H "Cache-Control: no-cache"
244
- social linkedin profile @handle -H "Cache-Control: no-store"
245
- social linkedin profile @handle -H "Cache-Control: max-age=60"
268
+ social linkedin profile @username -H "Cache-Control: no-cache"
269
+ social linkedin profile @username -H "Cache-Control: no-store"
270
+ social linkedin profile @username -H "Cache-Control: max-age=60"
246
271
  ```
247
272
 
248
273
  The local mirror is separate: run `sync` when you want newer local data, then
249
- query it with `sql`. SQL reads show local freshness in `meta.cache.tables`:
274
+ query it with `sql`. SQL reads show local freshness in `meta.cache.tables` and auto-upgrades in `meta.cache.migration` when a migration runs:
250
275
 
251
276
  ```sh
252
- social x sql "SELECT sender_handle, text FROM x_messages ORDER BY created_at DESC LIMIT 5" \
277
+ social x sql "SELECT sender_username, text FROM x_messages ORDER BY created_at DESC LIMIT 5" \
253
278
  | jq '{cost: .meta.cost, cache: .meta.cache}'
254
279
  social x timeline --limit 20 | jq '{cost: .meta.cost, cursor: .meta.cursor, cache: .meta.cache}'
255
280
  ```
@@ -263,8 +288,8 @@ Agents should watch `.meta.cost` during high-fanout loops, use
263
288
  ```sh
264
289
  # LinkedIn local mirror.
265
290
  social linkedin sync messages
266
- social linkedin sql "SELECT sender_display_name, text, datetime(timestamp/1000,'unixepoch') AS at FROM li_messages ORDER BY timestamp DESC LIMIT 20"
267
- social linkedin sql "SELECT user_display_name, user_public_identifier FROM li_requests WHERE type='received' ORDER BY created_at DESC LIMIT 25"
291
+ social linkedin sql "SELECT sender_name, text, datetime(created_at/1000,'unixepoch') AS at FROM li_messages ORDER BY created_at DESC LIMIT 20"
292
+ social linkedin sql "SELECT user_name, user_username FROM li_requests WHERE type='received' ORDER BY created_at DESC LIMIT 25"
268
293
 
269
294
  # LinkedIn live reads.
270
295
  social linkedin profile
@@ -275,7 +300,7 @@ social linkedin reactions post_id:<post-id> --limit 100 --offset 0
275
300
 
276
301
  # X local mirror.
277
302
  social x sync messages
278
- social x sql "SELECT sender_handle, text FROM x_messages ORDER BY created_at DESC LIMIT 20"
303
+ social x sql "SELECT sender_username, text FROM x_messages ORDER BY created_at DESC LIMIT 20"
279
304
  social x sql "SELECT text, url FROM x_bookmarks ORDER BY created_at DESC LIMIT 50"
280
305
  social x sql "SELECT username, name, followers_count FROM x_followers ORDER BY followers_count DESC LIMIT 100"
281
306