@anna-ai/cli

中文文档
0.1.64发布于 2026/11/06MITTypeScriptES Module近 30 天下载 2151

Anna App developer CLI: scaffold, validate, harness (Phase 2 MVP: init + validate).

原始使用文档
文档目录17 节
  1. Install
  2. Commands
  3. anna-app init <dir> [--slug <slug>] [--template minimal] [-…
  4. anna-app validate [--manifest manifest.json] [--bundle bund…
  5. anna-app dev [--manifest …] [--bundle …] [--port 5180] [--m…
  6. anna-app doctor [--matrix-nexus-root <path>]
  7. anna-app fixture verify <file.jsonl>
  8. anna-app fixture summarize <file.jsonl>
  9. anna-app fixture replay <file.jsonl> [--manifest …]
  10. Programmatic harness (vitest)
  11. Pytest plugin ( anna-executa-test )
  12. Schema bundle
  13. Browser SDK
  14. Persistent storage (APS)
  15. Roadmap
  16. Pinned versions
  17. Tests

@anna-ai/cli

Anna App developer CLI — scaffold, validate, run a local dev harness, drive fixture-based regression tests, and program against the harness from vitest/pytest. Phases 2–9 (MVP) are done.

Install

End-user install (after first npm publish):

npm i -g @anna-ai/cli
anna-app --help

The dev and fixture replay commands transparently fetch the pinned Python runtime via uvx (no matrix-nexus checkout required). Install uv once:

curl -LsSf https://astral.sh/uv/install.sh | sh

Local dev (this repo):

pnpm install
pnpm build
node dist/cli.js --help

Commands

anna-app init <dir> [--slug <slug>] [--template minimal] [--force]

Scaffolds a new Anna App project (manifest + bundle + a stdio plugin template). __TOOL_ID__ becomes tool-dev-<slug>.

anna-app init my-app --slug my-app
cd my-app
anna-app validate

anna-app validate [--manifest manifest.json] [--bundle bundle] [--strict]

Layered fail-fast checks: legacy normalization (a schema 1–3 manifest is folded to schema 4 and its retired fields — permissions, host_capabilities, the ui.host_api method lists — are reported as a warning) → JSON Schema → ui static → cross-file tool_id linter (with Levenshtein-1 typo detection) → browser-feature usage vs ui.browser_permissions (warning: e.g. getUserMedia without "microphone" is denied by the Dashboard's Permissions-Policy — forum #395) → --strict allowed_tools literals vs ui.host_api.agent.tools.

There is no method-level Host API allow-list: installing an App is the user's consent, and every anna.<ns>.<method> is available to an installed App. A manifest only declares the three capabilities that involve a second principal:

declarationmeaning
ui.host_api.credentials: ["google"]third-party accounts the App may read via credentials.*
ui.host_api.agent.tools: ["fs_read_file"]host-kit tools (fs_* / exec_* / browser_*) a sandbox agent session may use; ["*"] = all
storage.scopes: {"user": "rw"}cross-App data (user / tool / another App's app bucket); the App's own app scope needs no declaration

anna-app dev [--manifest …] [--bundle …] [--port 5180] [--matrix-nexus-root <path>] [--executa <spec>…]

Boots the local harness:

  • Spawns the Python anna-app-bridge (production dispatcher reused via WindowStoreProtocol).
  • Serves a mock dashboard at http://localhost:<port>/.
  • Auto-discovers <manifest-dir>/executas/<name>/ plugins (Python / Node.js / Go / pre-built binary) and registers them in the in-process ExecutaPool. See "Multi-language executas" below.
  • Hot-reloads the bundle on disk changes (use --no-watch to disable).
  • Mocks the realtime voice session (anna.audio.session, SDK ≥ 0.21.0) in the dashboard page: ASR via the browser's SpeechRecognition (Chrome), the LLM turn via the local agent.session, TTS via speechSynthesis (no tts_audio frames — the app's player stays idle). Events / setContext / say / barge-in / end() follow the production protocol.
  • Applies the same Permissions-Policy gates as production: the iframe allow attribute and the bundle Permissions-Policy header both come from the runtime (ui.browser_permissions ∪ implied audio: ["session"] ⇒ microphone ∪ frame-src ⇒ playback). An app that records without declaring "microphone" fails locally exactly like it fails on the Dashboard — validate tells you why.
  • Mirrors the host theme / locale (SDK ≥ 0.24.0): the iframe URL carries ?theme=&themeMode=&lang= and the titlebar ☀/🌙 and EN/中 buttons broadcast theme.changed / locale.changed events, so anna.onThemeChange() / anna.onLocaleChange() can be exercised without a production host.
  • Forwards agent.session.run args verbatim to the nexus account, so the optional per-run maxTokens (dispatcher ≥ 0.30.0 / SDK ≥ 0.26.0) and the additive run_meta.max_output_tokens / task_complete.{stop_reason,truncated} frames behave exactly as in production.

Multi-language executas

Each subdirectory of <manifest-dir>/executas/ is launched according to the first sentinel that matches:

#SentinelTypeDefault launch
0executa.json(any)command field, else type-specific default below
1pyproject.tomlpythonuv run --project <dir> <tool_id>
2package.jsonnodenode <bin[tool_id] | bin | main | module>
3go.mod (alone)gorequires executa.json declaring type: "go"
4bin/<dirname> execbinaryruns the executable directly

executa.json (recommended for clarity, required for Go and pre-built binary tools):

{
  "tool_id": "tool-yourhandle-foo-abcd1234",
  "type":    "python" | "node" | "go" | "binary",
  "command": ["…"],          // optional; full override of type defaults
  "enabled": true             // optional; default true. Set false to skip
                              // (useful when shipping multiple language
                              // flavours of the same tool_id).
}

The --executa <spec> flag (repeatable) registers an out-of-tree executa, or fully overrides auto-discovery for the run. Spec syntax:

# Auto-detect from the dir (same rules as in-tree discovery):
anna-app dev --executa dir=./vendor/external-tool

# Force type when there's no executa.json:
anna-app dev --executa dir=./executas/foo,type=go

# Fully explicit:
anna-app dev --executa dir=./executas/foo,tool_id=tool-h-foo-12345678,command="node plugin.js"

For the full discovery / executa.json reference, see anna-executa-examples/docs/multi-language-anna-apps.md.

Two runtime modes (auto-selected):

ModeWhenCommand
uvx (default)No matrix-nexus checkout nearbyuvx --from anna-app-runtime-local@<pinned> anna-app-bridge
nexus-source--matrix-nexus-root set, $ANNA_NEXUS_ROOT set, or running from inside a checkoutuv run --project <root> python -m anna_app_runtime_local.bridge

The pinned wheel version is exported as PINNED_RUNTIME_VERSION from src/harness/bridge.ts — bump in lock-step with packages/VERSIONS.md in matrix-nexus.

anna-app doctor [--matrix-nexus-root <path>]

Environment sanity check: uv on PATH, uvx cache state for the pinned runtime, optional matrix-nexus checkout, dev signing key permissions. Exit 0 if all required checks pass.

anna-app fixture verify <file.jsonl>

Strict syntactic + semantic validation of a recorded fixture (envelope ordering, response⇄request pairing).

anna-app fixture summarize <file.jsonl>

Pretty stats: counts per (ns, method), error breakdown, event totals.

anna-app fixture replay <file.jsonl> [--manifest …]

Dry-run replay (MVP): re-executes the recorded request sequence against a fresh LocalDispatcherSession and diffs each response. Live executa re-invocation is deferred to a future minor.

Programmatic harness (vitest)

import { mountBundle } from "@anna-ai/cli/test";

const h = await mountBundle({
  manifest: "./examples/hello/manifest.json",
  bundle:   "./examples/hello/bundle",
});
await h.call("storage", "set", { key: "k", value: 1 });
const events = h.drainEvents();
await h.close();

See src/test/index.ts for the full surface. Calls are checked against the manifest's capability declarations exactly like production (tools.invoke → declared executas, non-self storage scopes → storage.scopes, credentials.* → ui.host_api.credentials); there is no method-level ACL.

Pytest plugin (anna-executa-test)

For executa authors. Lives in matrix-nexus at packages/anna-executa-test/. Provides executa_session / executa_invoke fixtures — see that package's README.

Schema bundle

@anna-ai/app-schema is a regular npm dependency. Set ANNA_APP_SCHEMA_DIR to point at a local checkout (e.g. matrix-nexus/packages/anna-app-schema/) to iterate on the protocol without publishing.

Browser SDK

End-user app bundles load AnnaAppRuntime from /static/anna-apps/_sdk/<version>/index.js. Both the matrix-nexus production server and this CLI's harness serve that URL from the public npm package @anna-ai/app-runtime, which is declared as a normal dependency. No vendored copy, no sync step.

Persistent storage (APS)

Anna 1.2+ exposes a per-user JSON-RPC storage surface under the storage/* namespace. Every installed Executa receives a storage_token for its own tool scope — install is consent, nothing to grant. To also touch the user-wide user scope:

  1. Declare it in the plugin's describe manifest — structured "storage": {"scopes": {"user": "rw"}} (or the legacy host_capabilities: ["aps.scope.user.read", "aps.scope.user.write"] strings; aps.kv / aps.files only ever meant the self scope).
  2. Negotiate client_capabilities.storage = {} during initialize.

anna-app executa dev --storage real mints tokens with exactly these scopes (tool + declared), mirroring the platform minter.

See the protocol & best-practice guide at anna-executa-examples/docs/persistent-storage.md for wire format, error codes, and a worked OCR-cache example. The local dev harness mocks APS by default so end-to-end tests do not need network access.

Roadmap

PhaseStatusScope
2 — init + validate✅ MVPSchema/ACL checks
3 — dev harness✅ MVPStdio bridge, dashboard, hot-reload
4 — @anna-ai/cli/test✅ MVPProgrammatic mountBundle
5 — anna-executa-test (pytest)✅ MVPPlugin shipped from matrix-nexus
6 — fixture {verify,summarize,replay}✅ MVP (dry-run replay)Live re-invoke deferred
7 — Publish & distribution✅ doneuvx default + full [email protected] extraction; end-users no longer need a matrix-nexus checkout
8 — manifest.dev block + init template + 4 docs✅ doneSee matrix-nexus/docs/developers/apps/: local-dev.md, testing-bundle.md, testing-plugin.md, recording-replay.md
9 — Reference example upgraded✅ doneanna-executa-examples/examples/anna-app-focus-flow ships tests/{bundle,plugin}/, fixtures, and .github/workflows/anna-app.yml

Pinned versions

  • PINNED_RUNTIME_VERSION = "0.2.0a1" (src/harness/bridge.ts)
  • See matrix-nexus/packages/VERSIONS.md for the full toolchain matrix.

Tests

pnpm test

版本与发布记录

@anna-ai/cli 共发布 46 个版本,首次发布于 2026/04/30;过去 12 个月发布了 46 个版本。

版本发布日期距今
0.1.64latest2026/11/061 天前
0.1.632026/10/308 天前
0.1.612026/10/2315 天前
0.1.602026/10/2117 天前
0.1.592026/10/1622 天前
0.1.582026/10/0929 天前

关于 @anna-ai/cli 的常见问题

@anna-ai/cli 是什么?

Anna App developer CLI: scaffold, validate, harness (Phase 2 MVP: init + validate).

如何安装 @anna-ai/cli?

在项目目录运行 npm install @anna-ai/cli,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 anna-app,可以用 npx anna-app 直接运行。

@anna-ai/cli 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@anna-ai/cli 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@anna-ai/cli 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@anna-ai/cli 可以商用吗?

@anna-ai/cli 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@anna-ai/cli 的下载量有多少?

根据 npm 官方下载统计,@anna-ai/cli 在 2026/10/06 – 2026/11/04 这 30 天内被下载 2,151 次,日均约 72 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@anna-ai/cli 还在维护吗?

最新版本 0.1.64 发布于 2026/11/06(1 天前);至今共发布 46 个版本,其中过去 12 个月发布了 46 个;首次发布于 2026/04/30。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。