@usesocial/cli 0.1.0 → 0.1.2

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 ADDED
@@ -0,0 +1,9 @@
1
+ # @usesocial/cli
2
+
3
+ ## 0.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`158bf58`](https://github.com/usesocial/monorepo/commit/158bf5804d47112fa2ed941fd7e78174a53b3947) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Release the promoted account lifecycle, schema, and publishing pipeline updates.
8
+
9
+ Future release entries are managed by Changesets.
package/README.md CHANGED
@@ -1,8 +1,15 @@
1
- # @usesocial/cli
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://usesocial.dev/app-icon-dark.svg" />
4
+ <img alt="social" height="84" src="https://usesocial.dev/app-icon.svg" width="84" />
5
+ </picture>
6
+ </p>
2
7
 
3
- **Give your agent access to social networks.** One install, one login, and your
4
- agent can read, search, and graph LinkedIn and X — and post through your own
5
- account when you let it from any shell, any runtime.
8
+ <h1 align="center">@usesocial/cli</h1>
9
+
10
+ **Agent-run distribution.** One install, one login, and your agent can run
11
+ distribution work across X and LinkedIn — outreach, posting, audience insights,
12
+ and the follow-up loops between them — from any shell.
6
13
 
7
14
  `social` is built for people who live in a terminal with an agent open and are on
8
15
  the hook for their own distribution. The work you keep meaning to do — see who
@@ -15,21 +22,19 @@ Published as `@usesocial/cli` on npm; the binary is `social`.
15
22
  ## Install
16
23
 
17
24
  ```sh
18
- brew install usesocial/tap/social
19
- # or
20
- bun install -g @usesocial/cli@latest
21
- # or
22
- npm install -g @usesocial/cli
25
+ curl -fsSL https://usesocial.dev/install.sh | bash
26
+ # or install only the CLI with Homebrew
27
+ brew install usesocial/tap/cli
23
28
  ```
24
29
 
25
30
  ## Quickstart
26
31
 
27
32
  ```sh
28
- social login # device sign-in, choose scope, set up billing
29
- social linkedin connect # connect a LinkedIn account
30
- social linkedin users me --pretty
31
- social x connect # connect an X account
32
- social x users me --pretty
33
+ social auth login # device sign-in, choose scope, set up billing
34
+ social accounts connect linkedin # connect a LinkedIn account
35
+ social linkedin whoami
36
+ social accounts connect x # connect an X account
37
+ social x whoami
33
38
  ```
34
39
 
35
40
  ## What you can hand your agent
@@ -47,10 +52,10 @@ A few of the things the command surface supports:
47
52
 
48
53
  ## Commands
49
54
 
50
- Every command supports `--json` and `--pretty` for machine- vs. human-readable
51
- output. Most accept filters like `--limit`, `--cursor`, `--from`, and `--to`. Pass
52
- `--help` on any subcommand for the full flag list, or run `social schema` for a
53
- structured dump of every command — handy as an agent manifest.
55
+ The main command surfaces print compact JSON by default. Most accept filters like
56
+ `--limit`, `--cursor`, `--from`, and `--to`. Pass `--help` on any subcommand for
57
+ the full flag list, or run `social schema` for a structured dump of every command
58
+ — handy as an agent manifest.
54
59
 
55
60
  Commands marked **✎ write** mutate your account and require an explicit write
56
61
  scope (see [Account safety](#account-safety)).
@@ -59,13 +64,29 @@ scope (see [Account safety](#account-safety)).
59
64
 
60
65
  | Command | Description |
61
66
  |---|---|
62
- | `social login` | Device sign-in, scope selection, billing, optional agent-skill install. |
63
- | `social logout` | Revoke the session and clear the saved token. |
67
+ | `social config` | Read or configure local CLI settings. |
68
+ | `social auth login` | Device sign-in, scope selection, and billing. |
69
+ | `social auth logout` | Revoke the session and clear the saved token. |
70
+ | `social accounts <…>` | Connect, reconnect, disconnect, and list accounts. |
64
71
  | `social schema` | Print the full command tree as JSON — a manifest for agents. |
65
72
  | `social usage` | Recent calls or an aggregate billing/usage summary. |
66
73
  | `social linkedin <…>` | LinkedIn operations (below). |
67
74
  | `social x <…>` | X operations (below). |
68
75
 
76
+ ### `social accounts`
77
+
78
+ | Command | Description | |
79
+ |---|---|---|
80
+ | `connect linkedin` | Connect a LinkedIn account through hosted auth. | ✎ write |
81
+ | `connect x` | Connect an X account through OAuth. | ✎ write |
82
+ | `reconnect linkedin <account>` | Re-auth an existing LinkedIn account. | ✎ write |
83
+ | `reconnect x <account>` | Re-auth an existing X account. | ✎ write |
84
+ | `disconnect linkedin <account>` | Disconnect a LinkedIn account. | ✎ write |
85
+ | `disconnect x <account>` | Disconnect an X account. | ✎ write |
86
+ | `list [linkedin\|x\|all]` | List accounts. Defaults to all platforms. | |
87
+
88
+ `accounts list` returns `{ accounts: [...] }` as compact JSON.
89
+
69
90
  ### `social linkedin`
70
91
 
71
92
  | Command | Description | |
@@ -81,12 +102,16 @@ scope (see [Account safety](#account-safety)).
81
102
  | `posts react` | React to a post or comment. | ✎ write |
82
103
  | `search people` | Search for people. | |
83
104
  | `search posts` | Search for posts. | |
105
+ | `inbox list` | List LinkedIn inbox conversations. | |
106
+ | `inbox get` | Fetch an inbox conversation. | |
107
+ | `inbox messages` | List messages in a chat. | |
108
+ | `inbox send` | Send a message in a chat. | ✎ write |
84
109
  | `users get` | Fetch a profile. | |
85
110
  | `users connections` | List a user's connections. | |
86
111
  | `users posts` | List a user's or company's posts. | |
87
- | `users me` | Show the connected LinkedIn profile. | |
112
+ | `whoami` | Show the connected LinkedIn profile. | |
113
+ | `users me` | Same profile read as `whoami`. | |
88
114
  | `users invite` | Send a connection invite. | ✎ write |
89
- | `connect` · `reconnect` · `disconnect` · `list` | Account lifecycle and listing. | |
90
115
 
91
116
  ### `social x`
92
117
 
@@ -101,58 +126,94 @@ scope (see [Account safety](#account-safety)).
101
126
  | `tweets repost` · `unrepost` | Repost or undo a repost. | ✎ write |
102
127
  | `tweets delete` | Delete a post. | ✎ write |
103
128
  | `users tweets` | List a user's recent posts. | |
104
- | `users me` | Show the authenticated X profile. | |
129
+ | `users followers` | List a user's followers. | |
130
+ | `users following` | List accounts a user follows. | |
131
+ | `whoami` | Show the authenticated X profile. | |
132
+ | `users me` | Same profile read as `whoami`. | |
105
133
  | `users follow` · `unfollow` | Follow or unfollow a user. | ✎ write |
106
134
  | `bookmarks list` | List your saved bookmarks. | |
107
135
  | `bookmarks add` · `remove` | Add or remove a bookmark. | ✎ write |
108
- | `connect` · `reconnect` · `disconnect` · `list` | Account lifecycle and listing. | |
136
+ | `dms list` | List recent DM events. | |
137
+ | `dms messages` | List DM events for a conversation. | |
138
+ | `dms with` | List one-to-one DM events with a user. | |
139
+ | `dms get` | Fetch a DM event. | |
140
+ | `dms start` | Start a DM conversation. | ✎ write |
141
+ | `dms send` | Send a DM to a participant or conversation. | ✎ write |
109
142
 
110
143
  ## Built for agents
111
144
 
112
- - **Everything speaks JSON.** Pass `--json` and pipe through `jq`, `fzf`, or your
113
- agent's planner — anything that reads stdin. Structured errors and predictable
114
- exit codes mean an agent can branch on what happened.
115
- - **The same flags across networks.** `--limit`, `--cursor`, `--json`,
116
- `--pretty`. Learn the surface once; reuse it on LinkedIn and X.
145
+ - **Everything speaks JSON.** Pipe output through `jq`, `fzf`, or your agent's
146
+ planner — anything that reads stdin. Structured errors and predictable exit
147
+ codes mean an agent can branch on what happened.
148
+ - **The same flags across networks.** `--limit`, `--cursor`, `--account`, and
149
+ `--no-cache` behave consistently on LinkedIn and X.
117
150
  - **A skill you drop straight in.** Install the public skill repo with
118
151
  `npx skills add usesocial/skill`; Claude, Codex, or any other supported agent
119
- then knows the commands. `social login` can install it for you.
152
+ then knows the commands.
120
153
 
121
154
  ```sh
122
155
  # Find hiring posts, fan out to reaction graphs, rank warm contacts — one pipe.
123
- social linkedin search posts "AI infra hiring" --limit 10 --json \
156
+ social linkedin search posts "AI infra hiring" \
124
157
  | jq -r '.posts[].urn' \
125
- | xargs -I{} social linkedin posts reactions {} --json \
158
+ | xargs -I{} social linkedin posts reactions {} \
126
159
  | jq -s '[.[].reactions[] | {actor, type}]
127
160
  | group_by(.actor.id)
128
161
  | map({actor: .[0].actor, signals: length})
129
162
  | sort_by(-.signals) | .[0:15]'
130
163
  ```
131
164
 
165
+ ## Exit codes
166
+
167
+ | Code | Meaning | Agent action |
168
+ |---:|---|---|
169
+ | `0` | Success | Continue. |
170
+ | `2` | Usage or validation error | Fix the command, flags, IDs, JSON body, or local input. |
171
+ | `3` | Not found | Check the resource ID or pick a different item. |
172
+ | `4` | Auth or scope error | Run `social auth login`, or re-login with the needed scope. |
173
+ | `5` | API or unexpected error | Retry later or surface the server error. |
174
+ | `7` | Rate limited | Back off; JSON errors may include `retryAfterSeconds`. |
175
+
132
176
  ## Auth
133
177
 
134
- `social login` runs a device-authorization flow:
178
+ `social auth login` runs a device-authorization flow:
135
179
 
136
- 1. Shows you a verification code and opens the approval page in your browser
137
- (or prints the URL if there's no TTY, or you pass `--no-open`).
138
- 2. Waits until you approve the session in the browser.
139
- 3. Stores the returned token in your OS keyring, falling back to
180
+ 1. Asks what access to grant the agent. Read and Write are both selected by
181
+ default; pass `--scope read` to grant read-only access.
182
+ 2. Shows you a verification code and approval URL, then tries to open that URL
183
+ in your browser.
184
+ 3. Waits until you approve the session in the browser.
185
+ 4. Stores the returned token in your OS keyring, falling back to
140
186
  `~/.social/credentials.json` (mode `0600`) when no keyring is available.
187
+ Non-production `SOCIAL_API_URL` values use an API-specific credential
188
+ namespace so staging tests do not overwrite the production session.
141
189
 
142
- `social logout` revokes the session and removes the stored token from both places.
190
+ `social auth logout` revokes the session and removes the stored token from both places.
191
+ `social auth login` requires an interactive terminal and is not supported from CI,
192
+ background jobs, or agent-mediated setup flows.
143
193
 
144
- For non-interactive use (CI, agents), pass the details up front:
194
+ ## Cache config
195
+
196
+ Allowlisted GET requests use a local proxy cache. The CLI sends
197
+ `Cache-Control: max-age=<seconds>` on API requests from your local config:
145
198
 
146
199
  ```sh
147
- social login --email you@example.com --scope read,write --accept-pricing --json
200
+ social config cache mode # read the current cache mode and TTL
201
+ social config cache mode live # 15 minutes, default
202
+ social config cache mode analytical # 24 hours
203
+ social config cache mode historical # 1 week
204
+ social config cache ttl 3600 # custom TTL in seconds
148
205
  ```
149
206
 
207
+ Setting `ttl` switches the mode to `custom`. Config is stored at
208
+ `~/.social/config.json` with mode `0600`. Use command-level `--no-cache` when you
209
+ need to bypass cached reads and refresh the stored response.
210
+
150
211
  ## Account safety
151
212
 
152
213
  Built so your accounts outlive your prototype.
153
214
 
154
- - **Read scope by default.** Writes need an explicit upgrade you can revoke. A
155
- read-only session can't post, react, or invite.
215
+ - **Read/write scope by default.** Pass `--scope read` when you want a
216
+ read-only session that can't post, react, or invite.
156
217
  - **A write never fires twice.** Rate-limit and server errors surface verbatim and
157
218
  writes are never retried — so a post or invite can't double-send.
158
219
  - **A residential IP per account.** Each connected account runs over a dedicated
@@ -162,24 +223,27 @@ Built so your accounts outlive your prototype.
162
223
 
163
224
  ```sh
164
225
  # LinkedIn
165
- social linkedin search people "founder ai" --limit 10 --pretty
166
- social linkedin users me --json
226
+ social linkedin search people "founder ai"
227
+ social linkedin whoami
167
228
 
168
229
  # X
169
- social x search recent "from:elonmusk" --pretty
170
- social x bookmarks list --limit 50 --json
230
+ social x search recent "from:elonmusk"
231
+ social x bookmarks list <my-x-user-id> --limit 50
232
+ social x users followers <x-user-id> --limit 100
233
+ social x users following <x-user-id> --limit 100
234
+ social x dms list --limit 50
171
235
 
172
236
  # Usage / billing
173
- social usage --summary --platform linkedin --pretty
237
+ social usage --summary --platform linkedin
174
238
  social usage --limit 20 --from 2026-05-01T00:00:00Z
175
239
 
176
240
  # Agent manifest
177
- social schema --pretty
241
+ social schema
178
242
  ```
179
243
 
180
244
  ## Links
181
245
 
182
- - Pricing and limits: <https://socialcli.dev/pricing>
183
- - Terms: <https://socialcli.dev/terms> · Privacy: <https://socialcli.dev/privacy>
246
+ - Pricing and limits: <https://usesocial.dev/pricing>
247
+ - Terms: <https://usesocial.dev/terms> · Privacy: <https://usesocial.dev/privacy>
184
248
 
185
- Built by founders with the same distribution problem.
249
+ Built by founders who needed their agents to keep distribution moving.
package/dist/index.d.mts CHANGED
@@ -1 +1,98 @@
1
- export { };
1
+ //#region ../../node_modules/.bun/citty@0.2.2/node_modules/citty/dist/index.d.mts
2
+ //#region src/types.d.ts
3
+ type ArgType = "boolean" | "string" | "enum" | "positional" | undefined;
4
+ type _ArgDef<T extends ArgType, VT extends boolean | number | string> = {
5
+ type?: T;
6
+ description?: string;
7
+ valueHint?: string;
8
+ alias?: string | string[];
9
+ default?: VT;
10
+ required?: boolean;
11
+ options?: string[];
12
+ };
13
+ type BooleanArgDef = Omit<_ArgDef<"boolean", boolean>, "options"> & {
14
+ negativeDescription?: string;
15
+ };
16
+ type StringArgDef = Omit<_ArgDef<"string", string>, "options">;
17
+ type EnumArgDef = _ArgDef<"enum", string>;
18
+ type PositionalArgDef = Omit<_ArgDef<"positional", string>, "alias" | "options">;
19
+ type ArgDef = BooleanArgDef | StringArgDef | PositionalArgDef | EnumArgDef;
20
+ type ArgsDef = Record<string, ArgDef>;
21
+ type ResolveParsedArgType<T extends ArgDef, VT> = T extends {
22
+ default?: any;
23
+ required?: boolean;
24
+ } ? T["default"] extends NonNullable<VT> ? VT : T["required"] extends true ? VT : VT | undefined : VT | undefined;
25
+ type ParsedPositionalArg<T extends ArgDef> = T extends {
26
+ type: "positional";
27
+ } ? ResolveParsedArgType<T, string> : never;
28
+ type ParsedStringArg<T extends ArgDef> = T extends {
29
+ type: "string";
30
+ } ? ResolveParsedArgType<T, string> : never;
31
+ type ParsedBooleanArg<T extends ArgDef> = T extends {
32
+ type: "boolean";
33
+ } ? ResolveParsedArgType<T, boolean> : never;
34
+ type ParsedEnumArg<T extends ArgDef> = T extends {
35
+ type: "enum";
36
+ options: infer U;
37
+ } ? U extends Array<any> ? ResolveParsedArgType<T, U[number]> : never : never;
38
+ type RawArgs = {
39
+ _: string[];
40
+ };
41
+ type ParsedArg<T extends ArgDef> = T["type"] extends "positional" ? ParsedPositionalArg<T> : T["type"] extends "boolean" ? ParsedBooleanArg<T> : T["type"] extends "string" ? ParsedStringArg<T> : T["type"] extends "enum" ? ParsedEnumArg<T> : never;
42
+ type ParsedArgs<T extends ArgsDef = ArgsDef> = RawArgs & { [K in keyof T]: ParsedArg<T[K]> } & { [K in keyof T as T[K] extends {
43
+ alias: string;
44
+ } ? T[K]["alias"] : never]: ParsedArg<T[K]> } & { [K in keyof T as T[K] extends {
45
+ alias: string[];
46
+ } ? T[K]["alias"][number] : never]: ParsedArg<T[K]> } & Record<string, string | number | boolean | string[]>;
47
+ interface CommandMeta {
48
+ name?: string;
49
+ version?: string;
50
+ description?: string;
51
+ hidden?: boolean;
52
+ alias?: string | string[];
53
+ }
54
+ type SubCommandsDef = Record<string, Resolvable<CommandDef<any>>>;
55
+ type CommandDef<T extends ArgsDef = ArgsDef> = {
56
+ meta?: Resolvable<CommandMeta>;
57
+ args?: Resolvable<T>;
58
+ default?: Resolvable<string>;
59
+ subCommands?: Resolvable<SubCommandsDef>;
60
+ plugins?: Resolvable<CittyPlugin>[];
61
+ setup?: (context: CommandContext<T>) => any | Promise<any>;
62
+ cleanup?: (context: CommandContext<T>) => any | Promise<any>;
63
+ run?: (context: CommandContext<T>) => any | Promise<any>;
64
+ };
65
+ type CommandContext<T extends ArgsDef = ArgsDef> = {
66
+ rawArgs: string[];
67
+ args: ParsedArgs<T>;
68
+ cmd: CommandDef<T>;
69
+ subCommand?: CommandDef<T>;
70
+ data?: any;
71
+ };
72
+ type CittyPlugin = {
73
+ name: string;
74
+ setup?(context: CommandContext<any>): void | Promise<void>;
75
+ cleanup?(context: CommandContext<any>): void | Promise<void>;
76
+ };
77
+ type Resolvable<T> = T | Promise<T> | (() => T) | (() => Promise<T>); //#endregion
78
+ //#region src/command.d.ts
79
+ //#endregion
80
+ //#region src/index.d.ts
81
+ type MutableCommand = CommandDef<any> & {
82
+ args?: any;
83
+ meta?: any;
84
+ subCommands?: any;
85
+ };
86
+ /**
87
+ * Resolves the chain of matched command NAMES for analytics, e.g.
88
+ * `social x tweets get <id>` → `["x", "tweets", "get"]`. Mirrors the
89
+ * `commandForUsage` walk but collects names.
90
+ *
91
+ * PRIVACY: only tokens that resolve to a real subcommand are appended. The first
92
+ * arg that does not resolve (a positional value: tweet ID, handle, query text,
93
+ * flag value) breaks the walk and is NEVER captured. Never returns rawArgs or
94
+ * flag values.
95
+ */
96
+ declare const resolveCommandPath: (command: MutableCommand, rawArgs: string[]) => Promise<string[]>;
97
+ //#endregion
98
+ export { resolveCommandPath };