@usesocial/cli 0.8.0 → 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,205 @@
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
+
3
203
  ## 0.8.0
4
204
 
5
205
  ### Minor Changes
package/README.md CHANGED
@@ -94,10 +94,12 @@ that local mirror; it is free, instant, and read-only. Named read commands call
94
94
  the live network and cost credits; `x tweets <target>` and
95
95
  `linkedin posts <target>` require a target. Writes act.
96
96
 
97
+ `sync` output is always `{ data, meta }`: bare `sync` lists collections under
98
+ `.data[]`, while collection summaries and `--reset` results live under `.data`.
97
99
  `sync <collection> --since 2026-05-04` (ISO date or datetime) pulls only newer
98
100
  items where the bare `sync` listing shows `supportsSince: true` — cheaper than a
99
- full re-pull. `sync <collection> --reset` clears a collection's local
100
- rows and sync state so the next sync rebuilds it.
101
+ full re-pull. `sync <collection> --reset` clears a collection's local rows and
102
+ sync state so the next sync rebuilds it.
101
103
  `sync <collection> --timeout 900` opts into a wall-clock wait budget, in seconds,
102
104
  for rate-limit handling. LinkedIn sync may sleep and retry while the next wait
103
105
  fits the budget; X keeps its current no-new-retry behavior.
@@ -202,8 +204,9 @@ profile lookup is needed.
202
204
 
203
205
  - Everything speaks JSON: success on stdout, structured errors on stderr.
204
206
  - Platform reads return one envelope: lists use `.items[]`, single resources use
205
- `.data`, metadata lives under `.meta`. `social account` service commands return
206
- 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 } }`.
207
210
  - Schema-backed planning: `social schema --list` is the compact runnable index.
208
211
  - Local SQL is the free surface for your own synced data.
209
212
 
@@ -268,7 +271,7 @@ social linkedin profile @username -H "Cache-Control: max-age=60"
268
271
  ```
269
272
 
270
273
  The local mirror is separate: run `sync` when you want newer local data, then
271
- 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:
272
275
 
273
276
  ```sh
274
277
  social x sql "SELECT sender_username, text FROM x_messages ORDER BY created_at DESC LIMIT 5" \