@animaapp/cli 0.4.1 → 0.5.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 +23 -10
- package/dist/index.js +147 -68
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
# @animaapp/cli
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
The command-line for **AgentGrid** — a governed hub (by Anima) where AI agents
|
|
4
|
+
build, host, publish, and share apps. This CLI is how an agent *uses* AgentGrid
|
|
5
|
+
from a shell.
|
|
6
|
+
|
|
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
|
|
9
|
+
prompt/URL/Figma design, edit them over git, publish them to a live URL, and list
|
|
10
|
+
your team's artifacts to resume recent work. Every command runs an AgentGrid MCP
|
|
11
|
+
tool for you.
|
|
12
|
+
|
|
13
|
+
**How it works.** Built for **agents**: any AI tool that can run a shell command
|
|
14
|
+
can use it — no MCP server to configure, no plugins, just `npx`. Under the hood
|
|
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
|
|
17
|
+
MCP natively, `login` once then `mcp-config` to skip the CLI and call the tools
|
|
18
|
+
directly.
|
|
19
|
+
|
|
20
|
+
> Package name is `@animaapp/cli` (AgentGrid is by Anima); the API lives at
|
|
21
|
+
> `api.agentgrid.io`.
|
|
9
22
|
|
|
10
23
|
```bash
|
|
11
24
|
npx @animaapp/cli login
|
|
@@ -121,7 +134,7 @@ npx @animaapp/cli login --invite <url-or-code> # redeem a pre-approved i
|
|
|
121
134
|
| Option | Description | Default |
|
|
122
135
|
|--------|-------------|---------|
|
|
123
136
|
| `--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 | — |
|
|
124
|
-
| `--client-name <name>` | How the CLI appears on the consent screen | `
|
|
137
|
+
| `--client-name <name>` | How the CLI appears on the consent screen | `AgentGrid CLI` |
|
|
125
138
|
| `--no-open` | Don't try to open the verification page in a browser | — |
|
|
126
139
|
| `--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 |
|
|
127
140
|
|
|
@@ -259,7 +272,7 @@ secret, and re-mint rather than store it.
|
|
|
259
272
|
npx @animaapp/cli logout
|
|
260
273
|
```
|
|
261
274
|
|
|
262
|
-
A full local reset: clears **all** stored credentials (
|
|
275
|
+
A full local reset: clears **all** stored credentials (AgentGrid token, Figma
|
|
263
276
|
token, agent metadata) **and the CLI config** (including an `api-url` persisted
|
|
264
277
|
by `login --invite`) — the machine ends up pristine, as if the CLI was never
|
|
265
278
|
used. This only forgets the token locally — to actually disable an agent,
|
|
@@ -280,7 +293,7 @@ npx @animaapp/cli config unset api-url
|
|
|
280
293
|
```
|
|
281
294
|
|
|
282
295
|
The API URL resolves in this order: **`--api-url` flag → `ANIMA_API_URL` env →
|
|
283
|
-
`config.json` → default (`https://
|
|
296
|
+
`config.json` → default (`https://api.agentgrid.io`).**
|
|
284
297
|
|
|
285
298
|
### `auth` — inspect or manage credentials
|
|
286
299
|
|
|
@@ -301,7 +314,7 @@ Available on the network commands (`login`, `create`, `codegen`, `publish`,
|
|
|
301
314
|
|------|-------------|---------|
|
|
302
315
|
| `--json` | Emit a single JSON object to stdout (for agents) | off (pretty in a TTY) |
|
|
303
316
|
| `--verbose` | Stream progress to stderr in JSON mode¹ | off |
|
|
304
|
-
| `--api-url <url>` | API base URL (point at local/staging)³ | `https://
|
|
317
|
+
| `--api-url <url>` | API base URL (point at local/staging)³ | `https://api.agentgrid.io` |
|
|
305
318
|
| `--log-file <path>` | Append a JSON debug log of each step to a file | off |
|
|
306
319
|
| `--timeout <ms>` | Request timeout² | `600000` (10 min) |
|
|
307
320
|
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command13 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/create.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -271,7 +271,7 @@ function connectionError(err) {
|
|
|
271
271
|
const message = err instanceof Error ? err.message : String(err);
|
|
272
272
|
return new CliError(
|
|
273
273
|
"CONNECTION_ERROR",
|
|
274
|
-
`Could not reach the
|
|
274
|
+
`Could not reach the AgentGrid MCP endpoint: ${message}`,
|
|
275
275
|
1
|
|
276
276
|
);
|
|
277
277
|
}
|
|
@@ -370,7 +370,7 @@ function printSessionResult(result) {
|
|
|
370
370
|
printSuccess("Playground created successfully!");
|
|
371
371
|
printKeyValue("Session ID", result.sessionId);
|
|
372
372
|
if (result.playgroundUrl) {
|
|
373
|
-
printKeyValue("
|
|
373
|
+
printKeyValue("Your playground", chalk.cyan.underline(result.playgroundUrl));
|
|
374
374
|
}
|
|
375
375
|
if (result.tokenUsage) {
|
|
376
376
|
printKeyValue("Token usage", result.tokenUsage.toLocaleString());
|
|
@@ -514,13 +514,32 @@ function collectProjectSource(fromPath) {
|
|
|
514
514
|
return { kind: "files", files, fileCount: paths.length };
|
|
515
515
|
}
|
|
516
516
|
|
|
517
|
+
// src/utils/playgroundUrl.ts
|
|
518
|
+
var PLAYGROUND_BASE = "https://dev.animaapp.com/chat";
|
|
519
|
+
function parsePlaygroundUrl(input) {
|
|
520
|
+
if (!input.includes("/")) {
|
|
521
|
+
return input;
|
|
522
|
+
}
|
|
523
|
+
try {
|
|
524
|
+
const url = new URL(input);
|
|
525
|
+
const parts = url.pathname.split("/").filter(Boolean);
|
|
526
|
+
const markerIndex = parts.findIndex((p) => p === "chat" || p === "artifacts");
|
|
527
|
+
if (markerIndex !== -1 && markerIndex + 1 < parts.length) {
|
|
528
|
+
return parts[markerIndex + 1];
|
|
529
|
+
}
|
|
530
|
+
return parts[parts.length - 1];
|
|
531
|
+
} catch {
|
|
532
|
+
return input;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
517
536
|
// src/config/store.ts
|
|
518
537
|
import fs3 from "fs";
|
|
519
538
|
import path3 from "path";
|
|
520
539
|
import os2 from "os";
|
|
521
540
|
var CONFIG_DIR2 = path3.join(os2.homedir(), ".config", "anima");
|
|
522
541
|
var CONFIG_FILE = path3.join(CONFIG_DIR2, "config.json");
|
|
523
|
-
var DEFAULT_API_URL = "https://
|
|
542
|
+
var DEFAULT_API_URL = "https://api.agentgrid.io";
|
|
524
543
|
var CONFIG_KEYS = {
|
|
525
544
|
"api-url": "apiUrl"
|
|
526
545
|
};
|
|
@@ -570,12 +589,11 @@ function resolveApiUrl(flagValue) {
|
|
|
570
589
|
}
|
|
571
590
|
|
|
572
591
|
// src/commands/create.ts
|
|
573
|
-
var PLAYGROUND_BASE = "https://dev.animaapp.com/chat";
|
|
574
592
|
var createCommand = new Command("create").description(
|
|
575
|
-
"Create a playground
|
|
593
|
+
"Create a playground from your own code: empty for code you'll push (instant) or import your existing code (instant). Also supports AI generation: p2c/l2c/f2c (3-7 min)."
|
|
576
594
|
).requiredOption(
|
|
577
595
|
"-t, --type <type>",
|
|
578
|
-
"
|
|
596
|
+
"empty (empty repo you push to), import (create FROM your code \u2014 use --from), or AI-generated: p2c, l2c, f2c"
|
|
579
597
|
).option("-p, --prompt <prompt>", "Text prompt (p2c)").option("-u, --url <url>", "Website URL (l2c)").option("--file-key <key>", "Figma file key or URL (f2c)").option("--nodes <nodes>", "Figma node IDs, comma-separated (f2c)").option("--figma-token <token>", "Figma personal access token (f2c)").option(
|
|
580
598
|
"--framework <fw>",
|
|
581
599
|
"html | react \u2014 the only supported frameworks. REQUIRED for empty (declare react if you will push React code); detected from package.json for import"
|
|
@@ -690,8 +708,8 @@ ${result.nextSteps}` : message, result);
|
|
|
690
708
|
}
|
|
691
709
|
});
|
|
692
710
|
function validateCreateOptions(type, opts) {
|
|
693
|
-
if (!["
|
|
694
|
-
throw validationError(`Invalid type "${type}". Must be
|
|
711
|
+
if (!["empty", "import", "p2c", "l2c", "f2c"].includes(type)) {
|
|
712
|
+
throw validationError(`Invalid type "${type}". Must be empty, import, p2c, l2c, or f2c.`);
|
|
695
713
|
}
|
|
696
714
|
if (type === "p2c" && !opts.prompt) {
|
|
697
715
|
throw validationError("--prompt is required for p2c type");
|
|
@@ -764,9 +782,86 @@ function buildCreateArgs(type, opts) {
|
|
|
764
782
|
return args;
|
|
765
783
|
}
|
|
766
784
|
|
|
767
|
-
// src/commands/
|
|
785
|
+
// src/commands/list.ts
|
|
768
786
|
import { Command as Command2 } from "commander";
|
|
769
|
-
|
|
787
|
+
import chalk3 from "chalk";
|
|
788
|
+
var listCommand = new Command2("list").aliases(["ls", "artifacts"]).description(
|
|
789
|
+
"List your team's artifacts (most-recently-updated first) so you can resume existing work."
|
|
790
|
+
).option("--json", "Output as JSON").option("--api-url <url>", "API base URL (overrides config / ANIMA_API_URL)").option("--log-file <path>", "Append a JSON debug log of each step to this file").action(async (opts) => {
|
|
791
|
+
const mode = detectOutputMode(opts);
|
|
792
|
+
initLogger(opts.logFile);
|
|
793
|
+
try {
|
|
794
|
+
const auth = resolveAuth();
|
|
795
|
+
const result = await withMcp(
|
|
796
|
+
{ apiBaseUrl: resolveApiUrl(opts.apiUrl), token: auth.token, teamId: auth.teamId },
|
|
797
|
+
(client) => client.callTool("workspace-list_artifacts", {})
|
|
798
|
+
);
|
|
799
|
+
if (!result.success) {
|
|
800
|
+
const message = result.reason || result.error || "Could not list artifacts";
|
|
801
|
+
throw apiError(message, result);
|
|
802
|
+
}
|
|
803
|
+
const artifacts = result.artifacts ?? [];
|
|
804
|
+
logEvent("artifacts_listed", { count: artifacts.length, truncated: result.truncated ?? false });
|
|
805
|
+
if (mode === "pretty") {
|
|
806
|
+
if (artifacts.length === 0) {
|
|
807
|
+
console.log();
|
|
808
|
+
console.log(
|
|
809
|
+
" No artifacts yet \u2014 create one with `create -t empty` or `create -t import`."
|
|
810
|
+
);
|
|
811
|
+
console.log();
|
|
812
|
+
} else {
|
|
813
|
+
console.log();
|
|
814
|
+
for (const a of artifacts) {
|
|
815
|
+
console.log(` ${chalk3.bold(a.name)} ${chalk3.gray(`(${a.type})`)}`);
|
|
816
|
+
if (a.sessionId) {
|
|
817
|
+
console.log(` ${chalk3.gray("session:")} ${a.sessionId}`);
|
|
818
|
+
}
|
|
819
|
+
console.log(` ${chalk3.gray("updated:")} ${formatUpdatedAt(a.updatedAt)}`);
|
|
820
|
+
if (a.sessionId) {
|
|
821
|
+
console.log(
|
|
822
|
+
` ${chalk3.cyan.underline(`${PLAYGROUND_BASE}/${a.sessionId}`)}`
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
console.log();
|
|
826
|
+
}
|
|
827
|
+
if (result.truncated) {
|
|
828
|
+
console.log(
|
|
829
|
+
chalk3.yellow(" The list was capped \u2014 some artifacts are not shown.")
|
|
830
|
+
);
|
|
831
|
+
console.log();
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
} else {
|
|
835
|
+
outputResult(mode, {
|
|
836
|
+
success: true,
|
|
837
|
+
workspaceId: result.workspaceId,
|
|
838
|
+
artifacts,
|
|
839
|
+
truncated: result.truncated ?? false
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
} catch (err) {
|
|
843
|
+
if (err instanceof CliError) {
|
|
844
|
+
if (mode === "pretty") {
|
|
845
|
+
console.error(err.message);
|
|
846
|
+
} else {
|
|
847
|
+
outputError(mode, { code: err.code, message: err.message });
|
|
848
|
+
}
|
|
849
|
+
process.exit(err.exitCode);
|
|
850
|
+
}
|
|
851
|
+
throw err;
|
|
852
|
+
}
|
|
853
|
+
});
|
|
854
|
+
function formatUpdatedAt(iso) {
|
|
855
|
+
const then = new Date(iso).getTime();
|
|
856
|
+
if (Number.isNaN(then)) return iso;
|
|
857
|
+
const seconds = Math.max(0, Math.round((Date.now() - then) / 1e3));
|
|
858
|
+
const relative2 = seconds < 60 ? "just now" : seconds < 3600 ? `${Math.floor(seconds / 60)}m ago` : seconds < 86400 ? `${Math.floor(seconds / 3600)}h ago` : `${Math.floor(seconds / 86400)}d ago`;
|
|
859
|
+
return `${relative2} (${iso})`;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// src/commands/publish.ts
|
|
863
|
+
import { Command as Command3 } from "commander";
|
|
864
|
+
var publishCommand = new Command3("publish").description("Deploy playground to live URL or npm package (1-3 min)").argument("<sessionId>", "Session ID from create command").option("--mode <mode>", "webapp | designSystem", "webapp").option("--package-name <name>", "NPM package name (designSystem mode)").option("--package-version <version>", "NPM package version (designSystem mode)").option("--json", "Output as JSON").option("--verbose", "Show progress on stderr").option("--api-url <url>", "API base URL (overrides config / ANIMA_API_URL)").option("--log-file <path>", "Append a JSON debug log of each step to this file").action(async (sessionId, opts) => {
|
|
770
865
|
const mode = detectOutputMode(opts);
|
|
771
866
|
initLogger(opts.logFile);
|
|
772
867
|
const progress = new ProgressReporter(mode, opts.verbose);
|
|
@@ -836,7 +931,7 @@ var publishCommand = new Command2("publish").description("Deploy playground to l
|
|
|
836
931
|
});
|
|
837
932
|
|
|
838
933
|
// src/commands/codegen.ts
|
|
839
|
-
import { Command as
|
|
934
|
+
import { Command as Command4 } from "commander";
|
|
840
935
|
|
|
841
936
|
// src/utils/files.ts
|
|
842
937
|
import fs4 from "fs";
|
|
@@ -864,7 +959,7 @@ function writeFilesToDisk(files, outputDir) {
|
|
|
864
959
|
}
|
|
865
960
|
|
|
866
961
|
// src/commands/codegen.ts
|
|
867
|
-
var codegenCommand = new
|
|
962
|
+
var codegenCommand = new Command4("codegen").description("Convert Figma design to code files (no playground)").requiredOption("--file-key <key>", "Figma file key or URL").option("--nodes <nodes>", "Figma node IDs, comma-separated").option("--figma-token <token>", "Figma personal access token (or set FIGMA_TOKEN env var)").option("-o, --output <dir>", "Output directory", "./generated").option("--framework <fw>", "react | html", "react").option("--styling <style>", "tailwind | plain_css", "tailwind").option("--language <lang>", "typescript | javascript").option("--ui-library <lib>", "mui | antd | shadcn | clean_react").option("--json", "Output as JSON").option("--timeout <ms>", "Timeout in milliseconds", "600000").option("--verbose", "Show progress on stderr").option("--api-url <url>", "API base URL (overrides config / ANIMA_API_URL)").option("--log-file <path>", "Append a JSON debug log of each step to this file").action(async (opts) => {
|
|
868
963
|
const mode = detectOutputMode(opts);
|
|
869
964
|
initLogger(opts.logFile);
|
|
870
965
|
const progress = new ProgressReporter(mode, opts.verbose);
|
|
@@ -936,26 +1031,8 @@ var codegenCommand = new Command3("codegen").description("Convert Figma design t
|
|
|
936
1031
|
});
|
|
937
1032
|
|
|
938
1033
|
// src/commands/getGitToken.ts
|
|
939
|
-
import { Command as
|
|
940
|
-
import
|
|
941
|
-
|
|
942
|
-
// src/utils/playgroundUrl.ts
|
|
943
|
-
function parsePlaygroundUrl(input) {
|
|
944
|
-
if (!input.includes("/")) {
|
|
945
|
-
return input;
|
|
946
|
-
}
|
|
947
|
-
try {
|
|
948
|
-
const url = new URL(input);
|
|
949
|
-
const parts = url.pathname.split("/").filter(Boolean);
|
|
950
|
-
const chatIndex = parts.indexOf("chat");
|
|
951
|
-
if (chatIndex !== -1 && chatIndex + 1 < parts.length) {
|
|
952
|
-
return parts[chatIndex + 1];
|
|
953
|
-
}
|
|
954
|
-
return parts[parts.length - 1];
|
|
955
|
-
} catch {
|
|
956
|
-
return input;
|
|
957
|
-
}
|
|
958
|
-
}
|
|
1034
|
+
import { Command as Command5 } from "commander";
|
|
1035
|
+
import chalk4 from "chalk";
|
|
959
1036
|
|
|
960
1037
|
// src/utils/gitToken.ts
|
|
961
1038
|
function preview(payload) {
|
|
@@ -989,7 +1066,7 @@ function parseGitTokenResponse(payload) {
|
|
|
989
1066
|
}
|
|
990
1067
|
|
|
991
1068
|
// src/commands/getGitToken.ts
|
|
992
|
-
var getGitTokenCommand = new
|
|
1069
|
+
var getGitTokenCommand = new Command5("get-git-token").description("Mint a short-lived git remote URL for a playground (clone/push with git)").argument("<playgroundUrl>", "Playground URL or session ID").option("--json", "Output as JSON").option("--verbose", "Show progress on stderr").option("--api-url <url>", "API base URL (overrides config / ANIMA_API_URL)").option("--log-file <path>", "Append a JSON debug log of each step to this file").action(async (playgroundUrl, opts) => {
|
|
993
1070
|
const mode = detectOutputMode(opts);
|
|
994
1071
|
initLogger(opts.logFile);
|
|
995
1072
|
const progress = new ProgressReporter(mode, opts.verbose);
|
|
@@ -1006,7 +1083,7 @@ var getGitTokenCommand = new Command4("get-git-token").description("Mint a short
|
|
|
1006
1083
|
progress.succeed(`Git access granted (${grant.access === "rw" ? "read-write" : "read-only"})`);
|
|
1007
1084
|
if (mode === "pretty") {
|
|
1008
1085
|
console.log();
|
|
1009
|
-
console.log(` ${
|
|
1086
|
+
console.log(` ${chalk4.cyan(`git clone ${grant.gitRemoteUrl}`)}`);
|
|
1010
1087
|
console.log();
|
|
1011
1088
|
if (grant.access === "rw") {
|
|
1012
1089
|
console.log(" Commit and push to update the live playground.");
|
|
@@ -1016,7 +1093,7 @@ var getGitTokenCommand = new Command4("get-git-token").description("Mint a short
|
|
|
1016
1093
|
if (grant.expiresAt) {
|
|
1017
1094
|
console.log(
|
|
1018
1095
|
` The URL embeds a token that expires at ${grant.expiresAt} and cannot be renewed;
|
|
1019
|
-
re-run this command and ${
|
|
1096
|
+
re-run this command and ${chalk4.cyan("git remote set-url origin <new url>")} to keep pushing.`
|
|
1020
1097
|
);
|
|
1021
1098
|
}
|
|
1022
1099
|
console.log(" Treat the URL as a secret \u2014 it grants access to this playground.");
|
|
@@ -1045,16 +1122,16 @@ var getGitTokenCommand = new Command4("get-git-token").description("Mint a short
|
|
|
1045
1122
|
});
|
|
1046
1123
|
|
|
1047
1124
|
// src/commands/mcpConfig.ts
|
|
1048
|
-
import { Command as
|
|
1125
|
+
import { Command as Command7 } from "commander";
|
|
1049
1126
|
|
|
1050
1127
|
// src/commands/login.ts
|
|
1051
|
-
import { Command as
|
|
1052
|
-
import
|
|
1128
|
+
import { Command as Command6 } from "commander";
|
|
1129
|
+
import chalk5 from "chalk";
|
|
1053
1130
|
import open from "open";
|
|
1054
1131
|
|
|
1055
1132
|
// src/auth/device.ts
|
|
1056
1133
|
var DEVICE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
1057
|
-
var DEFAULT_CLIENT_NAME = "
|
|
1134
|
+
var DEFAULT_CLIENT_NAME = "AgentGrid CLI";
|
|
1058
1135
|
var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
1059
1136
|
function decodeJwtPayload(token) {
|
|
1060
1137
|
try {
|
|
@@ -1219,7 +1296,7 @@ async function loginWithInvite(options) {
|
|
|
1219
1296
|
}
|
|
1220
1297
|
|
|
1221
1298
|
// src/commands/login.ts
|
|
1222
|
-
var loginCommand = new
|
|
1299
|
+
var loginCommand = new Command6("login").description("Log in via the device flow, or redeem a pre-approved invite with --invite").option("--invite <url-or-code>", "Redeem an invite link (\u2026/invite/<code>.md) or bare code \u2014 no approval step").option("--client-name <name>", "How this CLI appears on the consent screen", "AgentGrid CLI").option("--no-open", "Do not try to open the verification page in a browser").option("--json", "Output as JSON").option("--api-url <url>", "API base URL (overrides config / ANIMA_API_URL)").option("--log-file <path>", "Append a JSON debug log of each step to this file").option(
|
|
1223
1300
|
"--print-mcp-config",
|
|
1224
1301
|
"After login, also print an MCP server config (includes the token) to paste into an MCP-capable agent"
|
|
1225
1302
|
).action(async (opts) => {
|
|
@@ -1282,9 +1359,9 @@ var loginCommand = new Command5("login").description("Log in via the device flow
|
|
|
1282
1359
|
console.log();
|
|
1283
1360
|
printInfo("To connect, open the verification page and enter this code:");
|
|
1284
1361
|
console.log();
|
|
1285
|
-
console.log(` ${
|
|
1362
|
+
console.log(` ${chalk5.cyan.underline(info.verificationUri)}`);
|
|
1286
1363
|
console.log();
|
|
1287
|
-
console.log(` ${
|
|
1364
|
+
console.log(` ${chalk5.bold.white(info.userCode)}`);
|
|
1288
1365
|
console.log();
|
|
1289
1366
|
printInfo(`Waiting for approval\u2026 (code expires in ${Math.round(info.expiresInSeconds / 60)} minutes)`);
|
|
1290
1367
|
} else {
|
|
@@ -1354,7 +1431,7 @@ function buildMcpConfig(apiUrl, token) {
|
|
|
1354
1431
|
}
|
|
1355
1432
|
|
|
1356
1433
|
// src/commands/mcpConfig.ts
|
|
1357
|
-
var mcpConfigCommand = new
|
|
1434
|
+
var mcpConfigCommand = new Command7("mcp-config").description("Print an MCP server config from your stored credentials (run `login` first)").option("--json", "Output as JSON").option("--api-url <url>", "API base URL (overrides config / ANIMA_API_URL)").action(async (opts) => {
|
|
1358
1435
|
const mode = detectOutputMode(opts);
|
|
1359
1436
|
try {
|
|
1360
1437
|
const auth = resolveAuth();
|
|
@@ -1391,10 +1468,10 @@ var mcpConfigCommand = new Command6("mcp-config").description("Print an MCP serv
|
|
|
1391
1468
|
});
|
|
1392
1469
|
|
|
1393
1470
|
// src/commands/auth.ts
|
|
1394
|
-
import { Command as
|
|
1395
|
-
import
|
|
1396
|
-
var DEFAULT_API_URL2 = "https://
|
|
1397
|
-
var authCommand = new
|
|
1471
|
+
import { Command as Command8 } from "commander";
|
|
1472
|
+
import chalk6 from "chalk";
|
|
1473
|
+
var DEFAULT_API_URL2 = "https://api.agentgrid.io";
|
|
1474
|
+
var authCommand = new Command8("auth").description("Manage authentication").option("--token <token>", "Store AgentGrid API token").option("--figma-token <token>", "Store Figma personal access token").option("--team-id <teamId>", "Team ID to associate with token").option("--status", "Show current auth status").option("--logout", "Clear stored credentials (alias for `anima logout`)").option("--json", "Output as JSON").option("--api-url <url>", "API base URL", DEFAULT_API_URL2).action(async (opts) => {
|
|
1398
1475
|
const mode = detectOutputMode(opts);
|
|
1399
1476
|
try {
|
|
1400
1477
|
if (opts.token || opts.figmaToken) {
|
|
@@ -1410,7 +1487,7 @@ var authCommand = new Command7("auth").description("Manage authentication").opti
|
|
|
1410
1487
|
if (mode === "pretty") {
|
|
1411
1488
|
printSuccess("Credentials saved to " + getCredentialsPath());
|
|
1412
1489
|
if (opts.token) {
|
|
1413
|
-
printKeyValue("
|
|
1490
|
+
printKeyValue("AgentGrid token", "saved");
|
|
1414
1491
|
if (toSave.teamId) printKeyValue("Team ID", toSave.teamId);
|
|
1415
1492
|
}
|
|
1416
1493
|
if (opts.figmaToken) {
|
|
@@ -1449,7 +1526,7 @@ var authCommand = new Command7("auth").description("Manage authentication").opti
|
|
|
1449
1526
|
if (mode === "pretty") {
|
|
1450
1527
|
printSuccess("Token configured");
|
|
1451
1528
|
printKeyValue("Source", sourceName);
|
|
1452
|
-
printKeyValue("
|
|
1529
|
+
printKeyValue("AgentGrid token", auth.token.slice(0, 12) + "..." + auth.token.slice(-4));
|
|
1453
1530
|
printKeyValue("Token type", auth.tokenType === "agent" ? "agent (scoped, revocable)" : "personal/API");
|
|
1454
1531
|
if (creds?.tokenType === "agent" && creds.expiresAt) printKeyValue("Expires", creds.expiresAt);
|
|
1455
1532
|
if (auth.teamId) printKeyValue("Team ID", auth.teamId);
|
|
@@ -1481,12 +1558,12 @@ var authCommand = new Command7("auth").description("Manage authentication").opti
|
|
|
1481
1558
|
if (mode === "pretty") {
|
|
1482
1559
|
console.log();
|
|
1483
1560
|
printInfo("Auth commands:");
|
|
1484
|
-
console.log(` ${
|
|
1485
|
-
console.log(` ${
|
|
1486
|
-
console.log(` ${
|
|
1487
|
-
console.log(` ${
|
|
1561
|
+
console.log(` ${chalk6.cyan("anima login")} Log in (device flow \u2014 approve on any browser)`);
|
|
1562
|
+
console.log(` ${chalk6.cyan("anima logout")} Clear all credentials`);
|
|
1563
|
+
console.log(` ${chalk6.cyan("anima auth --status")} Check auth status`);
|
|
1564
|
+
console.log(` ${chalk6.cyan("anima auth --figma-token <T>")} Save Figma token (needed for codegen/f2c)`);
|
|
1488
1565
|
console.log();
|
|
1489
|
-
console.log(` Figma token: ${
|
|
1566
|
+
console.log(` Figma token: ${chalk6.cyan.underline("https://www.figma.com")} > Settings > Personal access tokens`);
|
|
1490
1567
|
console.log();
|
|
1491
1568
|
} else {
|
|
1492
1569
|
outputResult(mode, {
|
|
@@ -1508,8 +1585,8 @@ var authCommand = new Command7("auth").description("Manage authentication").opti
|
|
|
1508
1585
|
});
|
|
1509
1586
|
|
|
1510
1587
|
// src/commands/logout.ts
|
|
1511
|
-
import { Command as
|
|
1512
|
-
var logoutCommand = new
|
|
1588
|
+
import { Command as Command9 } from "commander";
|
|
1589
|
+
var logoutCommand = new Command9("logout").description("Clear all stored credentials (AgentGrid + Figma tokens) from this machine").option("--json", "Output as JSON").action((opts) => {
|
|
1513
1590
|
const mode = detectOutputMode(opts);
|
|
1514
1591
|
const hadCredentials = clearStorage();
|
|
1515
1592
|
deleteConfig();
|
|
@@ -1525,8 +1602,8 @@ var logoutCommand = new Command8("logout").description("Clear all stored credent
|
|
|
1525
1602
|
});
|
|
1526
1603
|
|
|
1527
1604
|
// src/commands/unpublish.ts
|
|
1528
|
-
import { Command as
|
|
1529
|
-
var unpublishCommand = new
|
|
1605
|
+
import { Command as Command10 } from "commander";
|
|
1606
|
+
var unpublishCommand = new Command10("unpublish").description("Take a published playground offline (clears its live URL; code and playground stay intact)").argument("<sessionId>", "Session ID of the published playground").option("--json", "Output as JSON").option("--verbose", "Show progress on stderr").option("--api-url <url>", "API base URL (overrides config / ANIMA_API_URL)").option("--log-file <path>", "Append a JSON debug log of each step to this file").action(async (sessionId, opts) => {
|
|
1530
1607
|
const mode = detectOutputMode(opts);
|
|
1531
1608
|
initLogger(opts.logFile);
|
|
1532
1609
|
const progress = new ProgressReporter(mode, opts.verbose);
|
|
@@ -1561,8 +1638,8 @@ var unpublishCommand = new Command9("unpublish").description("Take a published p
|
|
|
1561
1638
|
});
|
|
1562
1639
|
|
|
1563
1640
|
// src/commands/update.ts
|
|
1564
|
-
import { Command as
|
|
1565
|
-
var updateCommand = new
|
|
1641
|
+
import { Command as Command11 } from "commander";
|
|
1642
|
+
var updateCommand = new Command11("update").description("Update a playground's metadata: display name and/or visibility (never touches code)").argument("<sessionId>", "Session ID of the playground").option("--name <name>", "New display name").option("--privacy <privacy>", "public (anyone with the link) | private (team only)").option("--json", "Output as JSON").option("--verbose", "Show progress on stderr").option("--api-url <url>", "API base URL (overrides config / ANIMA_API_URL)").option("--log-file <path>", "Append a JSON debug log of each step to this file").action(async (sessionId, opts) => {
|
|
1566
1643
|
const mode = detectOutputMode(opts);
|
|
1567
1644
|
initLogger(opts.logFile);
|
|
1568
1645
|
const progress = new ProgressReporter(mode, opts.verbose);
|
|
@@ -1607,8 +1684,8 @@ var updateCommand = new Command10("update").description("Update a playground's m
|
|
|
1607
1684
|
});
|
|
1608
1685
|
|
|
1609
1686
|
// src/commands/config.ts
|
|
1610
|
-
import { Command as
|
|
1611
|
-
var configCommand = new
|
|
1687
|
+
import { Command as Command12 } from "commander";
|
|
1688
|
+
var configCommand = new Command12("config").description(
|
|
1612
1689
|
`Store CLI preferences (keys: ${configKeys().join(", ")})`
|
|
1613
1690
|
);
|
|
1614
1691
|
configCommand.command("set <key> <value>").description("Set a config value").option("--json", "Output as JSON").action((key, value, opts) => {
|
|
@@ -1674,11 +1751,11 @@ function assertUrl(value) {
|
|
|
1674
1751
|
}
|
|
1675
1752
|
|
|
1676
1753
|
// src/index.ts
|
|
1677
|
-
var program = new
|
|
1678
|
-
`
|
|
1679
|
-
real git repository; each command runs an
|
|
1754
|
+
var program = new Command13().name("anima").description(
|
|
1755
|
+
`AgentGrid CLI \u2014 host, edit, and publish your work on AgentGrid. Every playground is a
|
|
1756
|
+
real git repository; each command runs an AgentGrid tool for you.
|
|
1680
1757
|
|
|
1681
|
-
THE MAIN FLOW (build something and put it on
|
|
1758
|
+
THE MAIN FLOW (build something and put it on AgentGrid):
|
|
1682
1759
|
1. npx @animaapp/cli login # once; a human approves
|
|
1683
1760
|
2. npx @animaapp/cli create -t import --from ./my-project # your code \u2192 a live playground
|
|
1684
1761
|
(or: create -t empty --framework html \u2014 an empty repo you push to)
|
|
@@ -1702,6 +1779,7 @@ TIMING (important for AI agents):
|
|
|
1702
1779
|
COMMANDS:
|
|
1703
1780
|
login Connect (device flow, or --invite to redeem an invite link)
|
|
1704
1781
|
logout Full local reset \u2014 clears credentials and CLI config
|
|
1782
|
+
list List your team's artifacts (most-recently-updated first) to resume work
|
|
1705
1783
|
create Make a playground: import your code, empty repo, or AI-generated (p2c/l2c/f2c)
|
|
1706
1784
|
get-git-token Fresh git access to an existing playground (or after token expiry)
|
|
1707
1785
|
update Rename a playground or set visibility public/private (metadata only)
|
|
@@ -1713,7 +1791,7 @@ COMMANDS:
|
|
|
1713
1791
|
auth Inspect or manage credentials (status / figma token)
|
|
1714
1792
|
|
|
1715
1793
|
EXAMPLES (headless flow):
|
|
1716
|
-
npx @animaapp/cli login --invite https://
|
|
1794
|
+
npx @animaapp/cli login --invite https://api.agentgrid.io/invite/<code>.md
|
|
1717
1795
|
npx @animaapp/cli create -t import --from ./my-project
|
|
1718
1796
|
npx @animaapp/cli create -t empty --framework react --name "My app"
|
|
1719
1797
|
npx @animaapp/cli get-git-token <sessionId>
|
|
@@ -1726,6 +1804,7 @@ OUTPUT: JSON to stdout when piped (for AI tools), pretty text in terminals.
|
|
|
1726
1804
|
).version(version, "-v, --version");
|
|
1727
1805
|
program.addCommand(loginCommand);
|
|
1728
1806
|
program.addCommand(logoutCommand);
|
|
1807
|
+
program.addCommand(listCommand);
|
|
1729
1808
|
program.addCommand(createCommand);
|
|
1730
1809
|
program.addCommand(publishCommand);
|
|
1731
1810
|
program.addCommand(unpublishCommand);
|