@animaapp/cli 0.5.1 → 0.7.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/README.md CHANGED
@@ -5,7 +5,7 @@ build, host, publish, and share apps. This CLI is how an agent *uses* AgentGrid
5
5
  from a shell.
6
6
 
7
7
  **What it does.** Connect as a scoped agent identity, then work with **artifacts**
8
- (playgrounds — each one a real git repo): create them from your own code or from a
8
+ (each one a real git repo): create them from your own code or from a
9
9
  prompt/URL/Figma design, edit them over git, publish them to a live URL, and list
10
10
  your team's artifacts to resume recent work. Every command runs an AgentGrid MCP
11
11
  tool for you.
@@ -13,7 +13,8 @@ tool for you.
13
13
  **How it works.** Built for **agents**: any AI tool that can run a shell command
14
14
  can use it — no MCP server to configure, no plugins, just `npx`. Under the hood
15
15
  each command talks to AgentGrid over MCP (`api.agentgrid.io`), and your access is a
16
- **scoped, revocable, ~7-day identity** your human approved. If your runtime speaks
16
+ **scoped, revocable identity** your human approved, renewed for you as it
17
+ expires. If your runtime speaks
17
18
  MCP natively, `login` once then `mcp-config` to skip the CLI and call the tools
18
19
  directly.
19
20
 
@@ -34,8 +35,11 @@ npx @animaapp/cli@latest create -t p2c -p "SaaS dashboard with sidebar and analy
34
35
  ## Connecting an agent
35
36
 
36
37
  Every command runs as a **scoped agent identity**: it acts only within the
37
- workspaces and capabilities a human approved, your team can see and **revoke** it
38
- at any time, and it expires after ~7 days. You get that identity one of two ways.
38
+ workspaces and capabilities a human approved, and your team can see and
39
+ **revoke** it at any time. The CLI renews it in the background; after a few
40
+ months the consent reaches its renewal limit and a human approves again. You get
41
+ that identity one of four ways. Door 3 is the usual one — you lead with
42
+ something to show, and it needs neither a token nor an account on their side.
39
43
 
40
44
  ### 1. Device login — `anima login`
41
45
 
@@ -86,6 +90,56 @@ export FIGMA_TOKEN=<token> # only for codegen / f2c
86
90
 
87
91
  Resolution priority: `ANIMA_API_TOKEN` env var → stored credentials file → error.
88
92
 
93
+ ### 3. Create first, hand off later — anonymous artifacts
94
+
95
+ This is the flow where **you** lead: no token, and a human who needs no
96
+ AgentGrid account until the moment they claim. Two commands:
97
+
98
+ ```bash
99
+ # 1. Create it. Prints claimUrl — send your human that link.
100
+ anima create --anonymous -t import --from ./my-project \
101
+ --client-name "Claude Code" --json
102
+
103
+ # 2. Wait for them to claim it, then store the credentials that grants.
104
+ anima login --handoff --json
105
+ ```
106
+
107
+ `create --anonymous` needs no credential at all. It returns a `claimUrl` for
108
+ your human, and a **`handoffToken`** for you. The token has two uses:
109
+
110
+ ```bash
111
+ anima login --handoff <token> # log in, once they claim it
112
+ anima create --anonymous --handoff <token> --from … # another artifact, same claim
113
+ ```
114
+
115
+ The CLI stores the token, so both commands default to your last one and you can
116
+ leave `<token>` off. Keep it yourself if this machine's config will not outlive
117
+ the process — it is delivered exactly once and can never be re-fetched. Lose it
118
+ and your human can still claim the artifact, but you can never be granted access
119
+ to it.
120
+
121
+ Once a claim window closes unclaimed, the next `create --anonymous` just starts
122
+ a fresh one.
123
+
124
+ **Send `clientName` — say what product you are** (`"Claude Code"`, `"Cursor"`,
125
+ …), the same name you would pass to `login --client-name`. The human sees it on
126
+ the claim page and it becomes the agent name they approve; without it they are
127
+ asked to invent a name for an artifact they did not create. Display-only, never
128
+ verified, ≤120 characters.
129
+
130
+ `login --handoff` blocks until the claim lands. Background it if you have other
131
+ work, and check the state whenever you like:
132
+
133
+ ```bash
134
+ anima login --handoff --json > anima-login.json &
135
+ anima auth --status --json # pendingHandoff.state: awaiting_claim | expired
136
+ ```
137
+
138
+ Anonymous artifacts are read-only and expire in 24h if nobody claims them. The
139
+ handoff token does **not** claim anything — the human never needs it, and never
140
+ gets it. A claim without agent access grants no token, and `login --handoff`
141
+ says so rather than polling forever.
142
+
89
143
  ### Which do I use?
90
144
 
91
145
  | Situation | How to connect |
@@ -94,6 +148,8 @@ Resolution priority: `ANIMA_API_TOKEN` env var → stored credentials file → e
94
148
  | Interactive agent, human nearby | `anima login` — show the URL + code, human approves on any device |
95
149
  | Headless agent, human reachable | `anima login --json` — relay the `verification_required` event, polling finishes automatically |
96
150
  | Fully headless / CI, no human | set `ANIMA_API_TOKEN` — no login step |
151
+ | You want to lead: share something first, no account needed on their side | `anima create --anonymous …` → send `claimUrl` → `anima login --handoff` |
152
+ | Your human led: they sent you an invite link to join | `anima login --invite <url-or-code>` — one exchange, no approval step |
97
153
 
98
154
  ---
99
155
 
@@ -115,6 +171,9 @@ npx @animaapp/cli@latest publish <sessionId>
115
171
  # ...or start empty and push over git
116
172
  npx @animaapp/cli@latest create -t empty --framework react --name "My project"
117
173
  npx @animaapp/cli@latest get-git-token <sessionId> # then: git clone <url>, add code, git push
174
+
175
+ # ...or create an independent copy of an existing artifact
176
+ npx @animaapp/cli@latest duplicate <artifactUrl-or-sessionId> --name "My copy"
118
177
  ```
119
178
 
120
179
  ---
@@ -129,49 +188,60 @@ npx @animaapp/cli@latest login --client-name "My CI Agent" # label on the cons
129
188
  npx @animaapp/cli@latest login --no-open # don't auto-open the browser
130
189
  npx @animaapp/cli@latest login --print-mcp-config # also emit an MCP server config
131
190
  npx @animaapp/cli@latest login --invite <url-or-code> # redeem a pre-approved invite — no approval step
191
+ npx @animaapp/cli@latest login --handoff # wait for a claim on your anonymous artifact
192
+ npx @animaapp/cli@latest login --handoff <token> # ...or name the token explicitly
132
193
  ```
133
194
 
134
195
  | Option | Description | Default |
135
196
  |--------|-------------|---------|
197
+ | `--handoff [token]` | Log in with the handoff token from an anonymous create. Waits until a human claims the artifact, then stores the credentials their claim grants — same store as every other door. Defaults to your last one. Blocks; background it with `&` and watch `auth --status`. Stops with a clear message if the window closes unclaimed, or if the human claimed without granting agent access | — |
136
198
  | `--invite <url-or-code>` | Redeem an invite link (`…/invite/<code>.md`) or bare code. The human already approved when minting the invite, so there is no verification step — one call and you're connected. The invite URL's origin is persisted as the `api-url`, so follow-up commands target the right server with no flags | — |
137
199
  | `--client-name <name>` | How the CLI appears on the consent screen | `AgentGrid CLI` |
138
200
  | `--no-open` | Don't try to open the verification page in a browser | — |
139
201
  | `--print-mcp-config` | One-shot: after this fresh login, also print the MCP server config. If you are already logged in, use `mcp-config` instead — this flag always starts a new login | off |
140
202
 
141
- ### `mcp-config` — print your MCP server config (no new login)
203
+ ### `mcp-config` — print your MCP server config
142
204
 
143
205
  ```bash
144
206
  npx @animaapp/cli@latest mcp-config
145
207
  ```
146
208
 
147
- Prints a ready-to-paste remote MCP server entry (points at `/v1/mcp` with a
148
- bearer header) **from your stored credentials** — no network call, no device
149
- flow. Errors with "run `anima login`" if you are not logged in or the token
150
- expired. `--json` wraps it as `{ success, mcpConfig, expiresAt }`.
209
+ Prints a ready-to-paste remote MCP server entry pointing at `/v1/mcp`. It
210
+ contains **no credential** and needs none: your MCP client authorizes itself
211
+ against the server and holds a credential it can renew on its own. No network
212
+ call, no device flow. `--json` wraps it as `{ success, mcpConfig }`.
151
213
 
152
- **MCP-capable agents:** `login` once, then `mcp-config`. Configure the printed
153
- entry and use native MCP tools directly — no CLI in the loop. The token is
154
- scoped and expires in ~7 days; on auth errors run `login` again, then
155
- `mcp-config` again. The token is never printed by plain `login --json` — only
156
- by `mcp-config` and `--print-mcp-config`.
214
+ **MCP-capable agents:** run `mcp-config`, add the entry to your client, and
215
+ authorize when it prompts. No CLI in the loop after that. Your client needs to
216
+ support OAuth for remote MCP servers (`.well-known` discovery); if it cannot,
217
+ use the CLI commands instead.
157
218
 
158
- ### `create` — a playground for your code, or AI-generated
219
+ ### `create` — an artifact for your code, or AI-generated
159
220
 
160
221
  ```bash
161
222
  npx @animaapp/cli@latest create -t import --from ./my-project # import YOUR code (instant)
223
+ npx @animaapp/cli@latest create -t import --from ./notes --artifact-type markdown # a readable document
162
224
  npx @animaapp/cli@latest create -t empty --framework react --name "My project" # empty repo you push to (instant)
163
225
  npx @animaapp/cli@latest create -t p2c -p "Analytics dashboard with a sidebar"
164
226
  npx @animaapp/cli@latest create -t l2c -u https://stripe.com
165
227
  npx @animaapp/cli@latest create -t f2c --file-key <key> --nodes 42:15
228
+ npx @animaapp/cli@latest create -t import --from ./my-project --anonymous # no account — hand off later
166
229
  ```
167
230
 
168
231
  `-t import` is the one-step upload path: your folder (or .zip) becomes the
169
- playground's first commit — small text-only projects are sent inline, larger
232
+ artifact's first commit — small text-only projects are sent inline, larger
170
233
  or binary ones are zipped and uploaded via a presigned URL automatically.
171
234
  `-t empty` creates an empty repository instead: follow with `git clone` of the
172
235
  returned URL, add your code, and `git push`. Then `publish <sessionId>` for a
173
236
  live URL. The other types are AI generation (3–7 min).
174
237
 
238
+ `--artifact-type` is a separate question from `-t`: `-t` is how the repository
239
+ starts, `--artifact-type` is what the artifact IS, and it decides how a human
240
+ sees it. `app` is a running web page and needs an `index.html`; `markdown` is a
241
+ readable document and needs `.md` files. Omit it and the server infers one:
242
+ markdown when your files are `.md`/`.mdx` with no HTML, otherwise app. Getting it wrong is the common mistake — `.md` files
243
+ uploaded as an app produce an artifact with nothing to render.
244
+
175
245
  | Option | Values | Default |
176
246
  |--------|--------|---------|
177
247
  | `-t, --type` | `import` (your code, with `--from`), `empty` (repo to push to), `p2c` (prompt), `l2c` (URL), `f2c` (Figma) | _required_ |
@@ -182,7 +252,11 @@ live URL. The other types are AI generation (3–7 min).
182
252
  | `--file-key` | Figma file key or URL | _(f2c)_ |
183
253
  | `--nodes` | Figma node IDs, comma-separated | _(f2c)_ |
184
254
  | `--figma-token` | Figma PAT (or `FIGMA_TOKEN` env) | _(f2c)_ |
185
- | `--framework` | `react`, `html` | `react` |
255
+ | `--artifact-type` | `app` (web page, needs an `index.html`), `markdown` (document, needs `.md` files) | _inferred from your files_ |
256
+ | `--anonymous` | Create with no account (`-t import` only). Returns `claimUrl` for your human and a `handoffToken` for you | off |
257
+ | `--handoff <token>` | Add this artifact to an existing claim (`--anonymous` only), so one link covers them all | _your last one_ |
258
+ | `--client-name` | Who to credit as the creator on the claim page (`--anonymous` only) | `AgentGrid CLI` |
259
+ | `--framework` | `react`, `html` — apps only | `react` |
186
260
  | `--styling` | `tailwind`, `css`, `plain_css`, `css_modules`, `inline_styles`¹ | `tailwind` |
187
261
  | `--language` | `typescript`, `javascript` | `typescript` (react) |
188
262
  | `--ui-library` | `shadcn`, `mui`, `antd`, `clean_react` | _(none)_ |
@@ -191,7 +265,25 @@ live URL. The other types are AI generation (3–7 min).
191
265
  ¹ The valid styling / UI-library set depends on `--type`; the server validates and
192
266
  returns a clear error for unsupported combinations.
193
267
 
194
- ### `codegen` — Figma to local files (no playground)
268
+ ### `duplicate` — copy an existing artifact
269
+
270
+ ```bash
271
+ npx @animaapp/cli@latest duplicate <artifactUrl-or-sessionId>
272
+ npx @animaapp/cli@latest duplicate <artifactUrl-or-sessionId> --name "My copy"
273
+ ```
274
+
275
+ Creates a new, independent artifact in the current team's Default workspace.
276
+ It copies code, assets, and supported database content, but does **not** copy
277
+ chat or custom domains. The source must be readable and the destination
278
+ workspace must be writable. Without `--name`, the API names it
279
+ `<source name> (Copy)`.
280
+
281
+ The result includes the new and source session IDs, duplicate name,
282
+ `playgroundUrl`, `previewUrl`, and API-provided next steps. Duplication is not
283
+ idempotent: if a request times out or its response is lost, run `list` and check
284
+ recent artifacts before retrying.
285
+
286
+ ### `codegen` — Figma to local files (no artifact)
195
287
 
196
288
  ```bash
197
289
  npx @animaapp/cli@latest codegen --file-key <key-or-url> --nodes 42:15 -o ./components
@@ -210,30 +302,27 @@ npx @animaapp/cli@latest codegen --file-key <key-or-url> --nodes 42:15 -o ./comp
210
302
 
211
303
  ### `publish` — deploy a session to a public URL (1–3 min)
212
304
 
213
- Publishing makes the playground **public to the world**. Sharing usually
214
- doesn't need it — the playground is already visible at its `playgroundUrl`.
305
+ Publishing makes the app **public to the world**. Sharing usually
306
+ doesn't need it — the artifact is already visible at its `playgroundUrl`.
215
307
  **Agents:** only publish when the human explicitly asked for a public site;
216
- otherwise share the playground URL and offer publishing as a follow-up.
308
+ otherwise share that URL and offer publishing as a follow-up.
217
309
 
218
310
  ```bash
219
311
  npx @animaapp/cli@latest publish <sessionId>
220
- npx @animaapp/cli@latest publish <sessionId> --mode designSystem --package-name my-ds
221
312
  ```
222
313
 
223
- | Option | Values | Default |
224
- |--------|--------|---------|
225
- | `--mode` | `webapp`, `designSystem` | `webapp` |
226
- | `--package-name` | npm package name | _(designSystem)_ |
227
- | `--package-version` | npm package version | _(designSystem)_ |
314
+ Deploys the artifact's app to a live URL. Publishing as a design-system npm
315
+ package is an enterprise feature and is not reachable over MCP, so this CLI
316
+ does not offer it.
228
317
 
229
- ### `unpublish` — take a published playground offline
318
+ ### `unpublish` — take a published artifact offline
230
319
 
231
320
  ```bash
232
321
  npx @animaapp/cli@latest unpublish <sessionId>
233
322
  ```
234
323
 
235
324
  The inverse of `publish`: clears the live URL so the deployed site stops being
236
- reachable. The playground, its code, and its content are untouched; publishing
325
+ reachable. The artifact, its code, and its content are untouched; publishing
237
326
  again reuses the same subdomain.
238
327
 
239
328
  ### `update` — rename or change visibility (metadata only)
@@ -246,19 +335,19 @@ npx @animaapp/cli@latest update <sessionId> --privacy private # team only
246
335
 
247
336
  Never touches code or content — that's the git flow (`get-git-token`).
248
337
 
249
- ### `get-git-token` — read/edit a playground's code over git
338
+ ### `get-git-token` — read/edit an artifact's code over git
250
339
 
251
340
  ```bash
252
341
  npx @animaapp/cli@latest get-git-token https://dev.animaapp.com/chat/<sessionId>
253
342
  ```
254
343
 
255
- A playground **is** a git repository, and git is the only way to read or edit
344
+ An artifact **is** a git repository, and git is the only way to read or edit
256
345
  its code. This command mints a short-lived access token scoped to that one
257
- playground and prints a ready-to-use remote URL — you run git yourself:
346
+ artifact and prints a ready-to-use remote URL — you run git yourself:
258
347
 
259
348
  ```bash
260
349
  git clone <gitRemoteUrl> # read (and edit locally)
261
- git push # read-write access: updates the live playground
350
+ git push # read-write access: updates the live artifact
262
351
  git remote set-url origin <new url> # after expiry: re-run get-git-token, re-point the clone
263
352
  ```
264
353
 
@@ -272,11 +361,13 @@ secret, and re-mint rather than store it.
272
361
  npx @animaapp/cli@latest logout
273
362
  ```
274
363
 
275
- A full local reset: clears **all** stored credentials (AgentGrid token, Figma
276
- token, agent metadata) **and the CLI config** (including an `api-url` persisted
277
- by `login --invite`) — the machine ends up pristine, as if the CLI was never
278
- used. This only forgets the token locally — to actually disable an agent,
279
- revoke it from your team settings.
364
+ A full reset: revokes the agent credentials server-side, then clears **all**
365
+ stored credentials (AgentGrid token, Figma token, agent metadata) **and the CLI
366
+ config** (including an `api-url` persisted by `login --invite`) — the machine
367
+ ends up pristine, as if the CLI was never used. Because the revocation is
368
+ server-side, a copy of the token taken from this machine stops working too.
369
+ The agent identity itself remains on your team roster; revoke it there to retire
370
+ it for good.
280
371
 
281
372
  ### `config` — store CLI preferences
282
373
 
@@ -298,17 +389,21 @@ The API URL resolves in this order: **`--api-url` flag → `ANIMA_API_URL` env
298
389
  ### `auth` — inspect or manage credentials
299
390
 
300
391
  ```bash
301
- npx @animaapp/cli@latest auth --status # token type + expiry
392
+ npx @animaapp/cli@latest auth --status # token type + expiry, and any pending claim
302
393
  npx @animaapp/cli@latest auth --figma-token <T> # save a Figma token for codegen / f2c
303
394
  npx @animaapp/cli@latest auth --logout # alias for `anima logout`
304
395
  ```
305
396
 
397
+ `--status` also reports a handoff waiting to be claimed — including when you are
398
+ not connected yet, which is exactly when you want to ask. `pendingHandoff.state`
399
+ is `awaiting_claim` or `expired`, alongside the `claimUrl` to re-send.
400
+
306
401
  ---
307
402
 
308
403
  ## Global flags
309
404
 
310
- Available on the network commands (`login`, `create`, `codegen`, `publish`,
311
- `get-git-token`):
405
+ Available on the network commands (`login`, `create`, `duplicate`, `codegen`,
406
+ `publish`, `get-git-token`):
312
407
 
313
408
  | Flag | Description | Default |
314
409
  |------|-------------|---------|
@@ -318,7 +413,8 @@ Available on the network commands (`login`, `create`, `codegen`, `publish`,
318
413
  | `--log-file <path>` | Append a JSON debug log of each step to a file | off |
319
414
  | `--timeout <ms>` | Request timeout² | `600000` (10 min) |
320
415
 
321
- ¹ `--verbose` applies to `create` / `codegen` / `publish` / `get-git-token`.
416
+ ¹ `--verbose` applies to `create` / `duplicate` / `codegen` / `publish` /
417
+ `get-git-token`.
322
418
  ² `--timeout` applies to `create` / `codegen`. Don't lower it — generation takes
323
419
  minutes.
324
420
  ³ Falls back to `ANIMA_API_URL`, then `anima config set api-url`, then the