@zibby/cli 0.7.0 → 0.7.1

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.
Files changed (29) hide show
  1. package/dist/bin/zibby.js +19 -18
  2. package/dist/commands/init.js +6 -6
  3. package/dist/commands/workflows/generate.js +33 -33
  4. package/dist/package.json +2 -2
  5. package/dist/templates/zibby-workflow-claude/agents-md-block.md +23 -23
  6. package/dist/templates/zibby-workflow-claude/claude/agents/zibby-workflow-builder.md +24 -24
  7. package/dist/templates/zibby-workflow-claude/claude/commands/zibby-add-node.md +18 -18
  8. package/dist/templates/zibby-workflow-claude/claude/commands/zibby-debug.md +10 -10
  9. package/dist/templates/zibby-workflow-claude/claude/commands/zibby-delete.md +7 -7
  10. package/dist/templates/zibby-workflow-claude/claude/commands/zibby-deploy.md +26 -26
  11. package/dist/templates/zibby-workflow-claude/claude/commands/zibby-list.md +8 -8
  12. package/dist/templates/zibby-workflow-claude/claude/commands/zibby-static-ip.md +13 -13
  13. package/dist/templates/zibby-workflow-claude/claude/commands/zibby-tail.md +13 -13
  14. package/dist/templates/zibby-workflow-claude/claude/commands/zibby-trigger.md +16 -16
  15. package/dist/templates/zibby-workflow-claude/cursor/rules/zibby-workflows.mdc +19 -19
  16. package/dist/templates/zibby-workflow-claude/manifest.json +1 -1
  17. package/package.json +2 -2
  18. package/templates/zibby-workflow-claude/agents-md-block.md +23 -23
  19. package/templates/zibby-workflow-claude/claude/agents/zibby-workflow-builder.md +24 -24
  20. package/templates/zibby-workflow-claude/claude/commands/zibby-add-node.md +18 -18
  21. package/templates/zibby-workflow-claude/claude/commands/zibby-debug.md +10 -10
  22. package/templates/zibby-workflow-claude/claude/commands/zibby-delete.md +7 -7
  23. package/templates/zibby-workflow-claude/claude/commands/zibby-deploy.md +26 -26
  24. package/templates/zibby-workflow-claude/claude/commands/zibby-list.md +8 -8
  25. package/templates/zibby-workflow-claude/claude/commands/zibby-static-ip.md +13 -13
  26. package/templates/zibby-workflow-claude/claude/commands/zibby-tail.md +13 -13
  27. package/templates/zibby-workflow-claude/claude/commands/zibby-trigger.md +16 -16
  28. package/templates/zibby-workflow-claude/cursor/rules/zibby-workflows.mdc +19 -19
  29. package/templates/zibby-workflow-claude/manifest.json +1 -1
package/dist/bin/zibby.js CHANGED
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
- process.stdout.on("error",e=>{e.code}),process.stderr.on("error",e=>{e.code}),process.env.DOTENV_CONFIG_QUIET="true";import"@zibby/skills";import{Command as P}from"commander";import{initCommand as A}from"../commands/init.js";import{runCommand as _}from"../commands/run.js";import{videoCommand as S}from"../commands/video.js";import{uploadCommand as B}from"../commands/upload.js";import{ciSetupCommand as E}from"../commands/ci-setup.js";import{setupPlaywrightMcpCommand as Y,setupCiCommand as x,testWithVideoCommand as O}from"../commands/setup-scripts.js";import{readFileSync as R}from"fs";import{fileURLToPath as j}from"url";import{dirname as Z,join as T}from"path";import{bootstrapAgentEnv as z}from"../utils/agent-credentials.js";import{WARM_POOL_QUANTITY_OPTIONS as h,WARM_POOL_MAX_QUANTITY as k}from"../config/warmPool.js";const D=j(import.meta.url),U=Z(D),g=JSON.parse(R(T(U,"../package.json"),"utf-8"));function p(e,o){return o.push(e),o}function b(e){if(e===void 0||e===!0||e==="")return 1;const o=parseInt(e,10);if(!Number.isFinite(o)||!h.includes(o))throw new Error(`--warm must be one of [${h.join(", ")}] (got "${e}"). Omit the flag to disable warm pool.`);return o}const v=`zibby v${g.version}`,a=process.argv.slice(2),L=a.includes("-h")||a.includes("--help"),M=a.includes("-v")||a.includes("-V")||a.includes("--version");M&&(console.log(v),process.exit(0));const I=a[0],K=a[1],N=["logs","uninstall"],F=I==="workflow"&&K==="list";!N.includes(I)&&!F&&console.log(`${v}
3
- `),z(process.cwd());const W=a[0]==="chat",H=["--verbose","--agent","--stream","-s"],J=a.length>0&&a.every(e=>H.includes(e)||a[a.indexOf(e)-1]==="--agent"),q=a.length===0||W||J;if(q&&!L){const e={},o=a.indexOf("--agent");o!==-1&&a[o+1]&&(e.agent=a[o+1]),a.includes("--verbose")&&(e.verbose=!0),(a.includes("--stream")||a.includes("-s"))&&(e.stream=!0);const{chatCommand:t}=await import("../commands/chat.js");await t(e),process.exit(0)}const n=new P;n.name("zibby").description("Zibby \u2014 the cloud pipeline for Claude Code, Cursor, Codex, and Gemini. Compose them into structured workflows with schema-enforced handoff.").version(g.version,"-V, --version"),n.configureHelp({visibleCommands:()=>[]}),n.addHelpText("after",`
4
- Workflow (the platform):
5
- workflow new <name> Scaffold a new workflow at .zibby/workflows/<name>/
6
- workflow run <name> Run a workflow locally (one-shot, mirrors trigger flags)
7
- workflow list Show local + cloud workflows
8
- workflow deploy <name> Build bundle + upload to cloud
9
- workflow trigger <uuid> Trigger a deployed workflow remotely
10
- workflow logs <uuid> [-t] Fetch (or tail) execution logs
11
- workflow download <uuid> Pull a cloud workflow source locally
12
- workflow delete <uuid> Destroy a cloud workflow
13
- workflow start <name> Long-lived local dev server (Studio integration)
2
+ process.stdout.on("error",e=>{e.code}),process.stderr.on("error",e=>{e.code}),process.env.DOTENV_CONFIG_QUIET="true";import"@zibby/skills";import{Command as P}from"commander";import{initCommand as A}from"../commands/init.js";import{runCommand as _}from"../commands/run.js";import{videoCommand as S}from"../commands/video.js";import{uploadCommand as B}from"../commands/upload.js";import{ciSetupCommand as E}from"../commands/ci-setup.js";import{setupPlaywrightMcpCommand as Y,setupCiCommand as x,testWithVideoCommand as O}from"../commands/setup-scripts.js";import{readFileSync as R}from"fs";import{fileURLToPath as j}from"url";import{dirname as Z,join as T}from"path";import{bootstrapAgentEnv as z}from"../utils/agent-credentials.js";import{WARM_POOL_QUANTITY_OPTIONS as g,WARM_POOL_MAX_QUANTITY as k}from"../config/warmPool.js";const D=j(import.meta.url),U=Z(D),b=JSON.parse(R(T(U,"../package.json"),"utf-8"));function p(e,o){return o.push(e),o}function v(e){if(e===void 0||e===!0||e==="")return 1;const o=parseInt(e,10);if(!Number.isFinite(o)||!g.includes(o))throw new Error(`--warm must be one of [${g.join(", ")}] (got "${e}"). Omit the flag to disable warm pool.`);return o}const I=`zibby v${b.version}`,a=process.argv.slice(2),L=a.includes("-h")||a.includes("--help"),M=a.includes("-v")||a.includes("-V")||a.includes("--version");M&&(console.log(I),process.exit(0));const h=a[0],K=a[1],N=["logs","uninstall"],F=(h==="workflow"||h==="agent")&&K==="list";!N.includes(h)&&!F&&console.log(`${I}
3
+ `),z(process.cwd());const W=a[0]==="chat",H=["--verbose","--agent","--stream","-s"],J=a.length>0&&a.every(e=>H.includes(e)||a[a.indexOf(e)-1]==="--agent"),q=a.length===0||W||J;if(q&&!L){const e={},o=a.indexOf("--agent");o!==-1&&a[o+1]&&(e.agent=a[o+1]),a.includes("--verbose")&&(e.verbose=!0),(a.includes("--stream")||a.includes("-s"))&&(e.stream=!0);const{chatCommand:t}=await import("../commands/chat.js");await t(e),process.exit(0)}const n=new P;n.name("zibby").description("Zibby \u2014 the cloud pipeline for Claude Code, Cursor, Codex, and Gemini. Compose them into structured workflows with schema-enforced handoff.").version(b.version,"-V, --version"),n.configureHelp({visibleCommands:()=>[]}),n.addHelpText("after",`
4
+ Agent (the platform) (alias: workflow):
5
+ agent new <name> Scaffold a new agent at .zibby/workflows/<name>/
6
+ agent run <name> Run an agent locally (one-shot, mirrors trigger flags)
7
+ agent list Show local + cloud agents
8
+ agent deploy <name> Build bundle + upload to cloud
9
+ agent trigger <uuid> Trigger a deployed agent remotely
10
+ agent logs <uuid> [-t] Fetch (or tail) execution logs
11
+ agent download <uuid> Pull a cloud agent source locally
12
+ agent delete <uuid> Destroy a cloud agent
13
+ agent start <name> Long-lived local dev server (Studio integration)
14
14
 
15
- Built-in workflow recipes (vertical slices on top of the platform):
15
+ Built-in agent recipes (vertical slices on top of the platform):
16
16
  test <spec-path> Browser test workflow \u2014 agent drives the browser, generates Playwright + video
17
17
  video Organize / regenerate verification videos for a test
18
18
  analyze Analyze a Jira ticket against the codebase
@@ -35,14 +35,15 @@ Studio + advanced:
35
35
  g Generate scaffolds (alias for 'generate')
36
36
 
37
37
  Examples:
38
- $ zibby workflow new my-pipeline # scaffold a multi-agent CI/CD pipeline
39
- $ zibby workflow run my-pipeline -p ticket=BUG-123 # run it locally with input
40
- $ zibby workflow deploy my-pipeline # ship to cloud (returns UUID)
41
- $ zibby workflow trigger <uuid> -p ticket=BUG-123 # trigger remotely with same flags
38
+ $ zibby agent new my-pipeline # scaffold a multi-agent CI/CD pipeline
39
+ $ zibby agent run my-pipeline -p ticket=BUG-123 # run it locally with input
40
+ $ zibby agent deploy my-pipeline # ship to cloud (returns UUID)
41
+ $ zibby agent trigger <uuid> -p ticket=BUG-123 # trigger remotely with same flags
42
+ # (the 'workflow' noun still works: 'zibby workflow new ...' is an alias)
42
43
 
43
44
  $ zibby test "go to example.com, verify title is 'Example Domain'"
44
45
  # run the built-in browser-test recipe
45
46
 
46
47
  Docs: https://docs.zibby.app
47
48
  GitHub: https://github.com/ZibbyHQ/zibby-agent
48
- `),n.command("init").description("Initialize a Zibby project (config + credentials only \u2014 pass -t <name> to also scaffold a workflow template)").argument("[project-name]","Project name (optional, uses current directory if not provided)").option("--agent <type>","Agent to use (claude, cursor, codex, gemini)").option("--memory-backend <backend>","Memory backend to configure (dolt, mem0)","dolt").option("--infer","Smart memory: let the LLM distill/dedupe facts on store (mem0 only; costs tokens). Default off = embed-only, free.").option("-t, --template <name>","Workflow template to scaffold into .zibby/ (see `zibby template list`). Default: none \u2014 init only sets up config and credentials.").option("--skip-install","Skip npm install").option("--skip-memory","Skip test memory setup during initialization").option("-f, --force","Force reinitialize (overwrite existing config)").option("--headed","Run MCP browser in headed mode (visible browser)").option("--headless","Run MCP browser in headless mode (hidden browser)").option("--api-key <key>","Zibby API key for cloud sync").option("--cloud-sync","Enable cloud sync and install Zibby MCP").option("--agent-key <key>","Agent API key (non-interactive). For Claude this is the per-token API key").option("--agent-oauth-token <token>","Claude OAuth subscription token (non-interactive). Saves to ~/.zibby/config.json").action(A),n.command("test").description("Run a test specification").argument("[spec-path]","Path to test spec file or inline test description in quotes").option("--sources <ids>","Comma-separated test case IDs to fetch from cloud").option("--execution <id>","Execution ID containing the test cases (required with --sources)").option("--agent <type>","Agent to use (claude, cursor, codex, gemini) - overrides config").option("--workflow <name>","Workflow to use (e.g., QuickSmokeWorkflow, quick-smoke)").option("--headless","Run browser in headless mode").option("--node <name>","Run only a specific node (e.g., execute_live, generate_script)").option("--session <id>",'Use existing session (e.g., 1768974629717 or "last") - requires --node').option("--session-path <dir>","Use this session folder (absolute or relative to cwd); Studio pins artifacts here").option("--project <id>","Project ID (optional, auto-detected from ZIBBY_API_KEY)").option("--collection <id-or-name>","Collection ID or name (creates new if name doesn't exist)").option("--folder <path>","Folder path within collection (optional, requires --collection)").option("--sync","Force upload to cloud (overrides cloudSync: false)").option("--no-sync","Skip upload to cloud (overrides cloudSync: true)").option("--config <path>","Path to config file",".zibby.config.mjs").option("--auto-approve","Auto-approve MCP tools (for CI/CD)").option("-o, --open","Open test results in browser after completion").option("--verbose","Show info level logs").option("--debug","Show debug level logs (most verbose)").option("-m, --mem","Enable test memory (Dolt-backed knowledge from previous runs)").action((e,o)=>(o.debug?process.env.ZIBBY_DEBUG="true":o.verbose&&(process.env.ZIBBY_VERBOSE="true"),_(e,o))),n.command("implement").description("Implement a Jira ticket using AI agent (runs in ECS container)").action(async(...e)=>{const{implementCommand:o}=await import("../commands/implement.js");return o(...e)}),n.command("analyze").description("Analyze a Jira ticket against the codebase (runs in ECS container)").option("--workflow <path>","Path to a local workflow JSON file (e.g., .zibby/workflow-analysis.json)").action(async(...e)=>{const{analyzeCommand:o}=await import("../commands/analyze-graph.js");return o(...e)}),n.command("video").description("Organize test videos next to test files").action(S),n.command("upload <spec-path>").description("Upload existing test artifacts to Zibby Cloud").option("--project <id>","Project ID (REQUIRED - use flag or ZIBBY_PROJECT_ID env)").option("--collection <id-or-name>","Collection ID or name (creates new if name doesn't exist)").option("--folder <path>","Folder path within collection (optional)").option("--agent <type>","Agent used (for metadata)").action(B),n.command("login").description("Log in to Zibby (opens browser for authentication)").action(async()=>{const{loginCli:e}=await import("../auth/cli-login.js");await e(),process.exit(0)}),n.command("logout").description("Log out from Zibby (clears saved session)").action(async()=>{const{logoutCli:e}=await import("../auth/cli-login.js");e(),process.exit(0)}),n.command("status").description("Show current authentication status and token details").option("--json","Output in JSON format (for scripts)").action(async e=>{const{showLoginStatus:o}=await import("../auth/cli-login.js");await o(e),process.exit(0)}),n.command("list").description("List your projects and API tokens").action(async()=>{const{listProjectsCommand:e}=await import("../commands/list-projects.js");await e()}),n.command("ci-setup").description("Setup Cursor Agent for CI/CD (patch and configure)").option("--get-keys","Get MCP approval keys").option("--save","Save approval keys to project").action(E),n.command("setup-playwright").description("Setup official Playwright MCP (from cursor-agent-package)").option("--headed","Configure MCP in headed mode (visible browser)").option("--viewport-width <width>","Viewport width (default: 1280)","1280").option("--viewport-height <height>","Viewport height (default: 720)","720").action(e=>{const o={width:parseInt(e.viewportWidth,10)||1280,height:parseInt(e.viewportHeight,10)||720};return Y({...e,viewport:o})}),n.command("setup-ci-full").description("Complete CI/CD setup from scratch").action(x),n.command("test-video").description("Run Playwright tests with video recording").argument("[test-file]","Test file to run (default: tests/)").option("--headed","Run in headed mode (visible browser)").action(O),n.command("generate").description("Generate test specs from a ticket + codebase (local analysis using real AI agent)").option("-t, --ticket <key>","Jira ticket key (fetches automatically)").option("-i, --input <file>","Input file with ticket description/requirements").option("-d, --description <text>","Inline ticket description").option("--repo <path>","Path to the codebase (default: current directory)").option("--agent <type>","Agent to use (codex, claude, cursor, gemini)").option("--model <model>","Model override").option("-o, --output <dir>","Output directory for spec files (default: test-specs)").action(async e=>{const{generateCommand:o}=await import("../commands/generate.js");return o(e)}),n.command("studio").description("Launch Zibby Studio desktop (installs from CDN if needed). Uses this folder as the Zibby project.").option("-p, --port <port>","Port for the Studio API bridge (default: 3847)").option("--no-open","Start the API only; do not launch desktop app").option("--update","Force re-download of the latest Studio binary").action(async e=>{const{studioCommand:o}=await import("../commands/studio.js");return o(e)});const m=n.command("creds").description("Manage credentials Zibby has stored for your workspace (KMS-encrypted)");m.command("list").description("List credentials stored for your workspace (masked)").action(async()=>{const{listCmd:e}=await import("../commands/creds.js");await e(),process.exit(0)}),m.command("sync").description("Re-read ~/.zibby/credentials.env and upload any new tokens").action(async()=>{const{syncCmd:e}=await import("../commands/creds.js");await e(),process.exit(0)}),m.command("set <provider> <token>").description("Paste-token shortcut. e.g. zibby creds set claude sk-ant-oat01-... (auto-detects oauth vs api)").option("--type <kind>","Force credential kind: oauth | api (skips auto-detect)").action(async(e,o,t)=>{const{setCmd:s}=await import("../commands/creds.js");await s(e,o,t),process.exit(0)}),m.command("remove <type> <index>").description("Remove a stored credential. e.g. zibby creds remove oauth 0").action(async(e,o)=>{const{removeCmd:t}=await import("../commands/creds.js");await t(e,o),process.exit(0)});const G=n.command("g").description("Generate scaffolds");G.command("workflow [name]").description("Scaffold a new custom workflow in .zibby/workflows/<name>/ (auto-generates name if omitted)").option("-t, --template <name>","Scaffold from a template (see `zibby template list`). Future: also accepts npm package / git URL identifiers.").option("--skip-install","Skip running `npm install` in the new workflow folder").option("--skip-init-check","Skip the first-run init prompt that fires when ~/.zibby/config.json is missing (CI/scripted setups)").option("--agent-helpers [list]",'Install agent helpers (Claude Code / Cursor slash commands). List = comma-separated, e.g. "claude" or "claude,cursor". Bare flag defaults to claude.').option("--no-agent-helpers","Skip agent helpers even if .zibby.config.mjs says install").option("--agent <agent>","(legacy) Set up agent helpers: claude | cursor | codex | all | none. Prefer --agent-helpers.").option("--force-agents","Overwrite user-edited agent helper files (use with --agent-helpers)").action(async(e,o)=>{const{generateWorkflowCommand:t}=await import("../commands/workflows/generate.js");return t(e,o)}),n.command("start <workflow-name>").description("Start a local dev server for a custom workflow").option("-p, --port <port>","Port for the workflow server (default: 3848)").action(async(e,o)=>{const{startWorkflowCommand:t}=await import("../commands/workflows/start.js");return t(e,o)}),n.command("run <workflow-name>").description("Run a workflow locally \u2014 one-shot (alias of `zibby workflow run`)").option("-p, --param <key=value>","Input param (repeatable)",p,[]).option("--input <json>","Input as JSON string").option("--input-file <path>","Input as JSON file").action(async(e,o)=>{const{runLocalWorkflowCommand:t}=await import("../commands/workflows/run-local.js");return t(e,o)}),n.command("deploy [workflow-name]").description("Deploy a custom workflow to Zibby Cloud (interactive selection if workflow-name not provided)").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--dedicated-ip <action>","Manage dedicated egress IP addon: enable | status | disable | use | unuse").option("--env <path>","Path to a .env file to sync into per-workflow env vars after deploy (repeatable)",p,[]).option("--verbose","Show raw CodeBuild logs during the bundle build").option("--no-creds-check","Skip the project secrets sanity check (CI/CD when the secret is provisioned out-of-band)").option("--force","Deploy even if the source checksum matches the last deployed version (bypasses the unchanged check)").option("--warm [count]",`Enable warm-pool execution for this workflow (default 1, max ${k}). Skips ~60s Fargate cold-start by routing triggers to a per-account pool of always-on tasks. Pricing applies (paid feature).`,b).option("--ai-agent <agent>","Per-workflow AI agent override (claude | cursor | codex | gemini). Falls back to the project default when omitted.").action(async(e,o)=>{if(o.dedicatedIp){const{dedicatedEgressCommand:s}=await import("../commands/workflows/dedicated-egress.js");return s(o.dedicatedIp,o.project)}o.aiAgent&&!["claude","cursor","codex","gemini"].includes(o.aiAgent)&&(console.error(chalk.red(`Invalid --ai-agent: ${o.aiAgent}. Must be one of: claude, cursor, codex, gemini.`)),process.exit(1));const{deployWorkflowCommand:t}=await import("../commands/workflows/deploy.js");return t(e,o)}),n.command("trigger [uuid]").description("Trigger a deployed workflow by UUID (interactive selection if not provided). Get UUIDs from `zibby workflow list`.").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("-p, --param <key=value>","Input param (repeatable, e.g. -p url=https://x.com -p count=5)",p,[]).option("--input <json>",`Input as JSON string \u2014 overridden by --param (e.g. '{"key":"value"}')`).option("--input-file <path>","Input as JSON/YAML file \u2014 lowest precedence").option("--idempotency-key <key>","Idempotency key to prevent duplicate executions").option("-t, --follow","Stream logs in real-time after triggering (no need to run `logs -t` separately)").action(async(e,o)=>{const{triggerWorkflowCommand:t}=await import("../commands/workflows/trigger.js");return t(e,o)}),n.command("run-workflow").description("Run a deployed workflow from S3 sources (used by ECS containers)").action(async()=>{const{runWorkflowCommand:e}=await import("../commands/workflows/run.js");return e()});const C=n.command("template").description("Manage workflow templates in this project");C.command("list").description("List available workflow templates").action(async()=>{const{templateListCommand:e}=await import("../commands/template.js");return e()}),C.command("add",{hidden:!0}).argument("<name>","Template name (see `zibby template list`)").description("(deprecated \u2014 `zibby test` auto-installs the template) Copy a template into .zibby/, overwriting existing files").option("--skip-memory","Strip SKILLS.MEMORY from copied execute-live.mjs (browser-test only)").action(async(e,o)=>{const{templateAddCommand:t}=await import("../commands/template.js");return t(e,{enableMemory:!o.skipMemory})});const c=n.command("memory").description("Test memory database \u2014 version-controlled knowledge from runs");c.command("stats").description("Show memory database statistics").action(async()=>{const{memoryStatsCommand:e}=await import("../commands/memory.js");return e()}),c.command("init").description("Initialize the memory database (Dolt)").action(async()=>{const{memoryInitCommand:e}=await import("../commands/memory.js");return e()}),c.command("compact").description("Prune old data and run Dolt GC to reclaim storage").option("--max-runs <n>","Keep last N runs per spec (default: 50)",parseInt).option("--max-age <days>","Remove data older than N days (default: 90)",parseInt).action(async e=>{const{memoryCompactCommand:o}=await import("../commands/memory.js");return o(e)}),c.command("reset").description("Wipe the memory database").option("-f, --force","Confirm reset").action(async e=>{const{memoryResetCommand:o}=await import("../commands/memory.js");return o(e)}),c.command("cost").description("Show real LLM token usage from past runs (input/output/cache)").action(async()=>{const{memoryCostCommand:e}=await import("../commands/memory.js");return e()});const u=c.command("remote").description("Configure a remote so the team shares cross-spec memory");u.command("add").argument("<url>","Remote URL: aws://, gs://, https://, file:///").option("--name <name>","Remote name (default: origin)","origin").description("Point the local memory DB at a shared remote (S3/GCS/DoltHub/filesystem)").action(async(e,o)=>{const{memoryRemoteAddCommand:t}=await import("../commands/memory.js");return t(e,o)}),u.command("use").description("Switch to a managed remote backend. Currently: --hosted (Zibby-managed S3, signed-in users only).").option("--hosted","Use Zibby-managed S3 (allocates a tenant-scoped prefix per-project)").option("--project-id <id>","Override the projectId from .zibby.config.mjs").action(async e=>{e.hosted||(console.log("Pass --hosted. (Other backends will be added later.)"),process.exit(1));const{memoryRemoteUseHostedCommand:o}=await import("../commands/memory.js");return o(e)}),u.command("info").description("Show the configured memory remote (if any)").action(async()=>{const{memoryRemoteInfoCommand:e}=await import("../commands/memory.js");return e()}),u.command("remove").argument("[name]","Remote name (default: origin)").description("Remove a configured memory remote (memory becomes local-only)").action(async e=>{const{memoryRemoteRemoveCommand:o}=await import("../commands/memory.js");return o(e)}),c.command("pull").description("Pull latest team memory from the configured remote").action(async()=>{const{memoryPullCommand:e}=await import("../commands/memory.js");return e()}),c.command("push").description("Push local memory to the configured remote (auto-runs after passing tests)").action(async()=>{const{memoryPushCommand:e}=await import("../commands/memory.js");return e()});const V=n.command("agents").description("Manage Claude/Cursor/Codex helper files for working with Zibby workflows");V.command("add [agent]").description("Add agent helpers (claude | cursor | codex | all). Prompts if no agent given.").option("--force","Overwrite user-edited helper files").action(async(e,o)=>{const{runAgentHelpers:t,addAgent:s}=await import("../commands/workflows/agent-helpers.js");if(e){const d=["claude","cursor","codex","all","none"];d.includes(e)||(console.error(`Unknown agent "${e}". Valid: ${d.join(", ")}`),process.exit(1)),e==="none"?await t({forcedAgents:["none"],force:o.force===!0}):e==="all"?await t({forcedAgents:["claude","cursor","codex"],force:o.force===!0}):await s(e,{force:o.force===!0})}else await t({forcedAgents:void 0,force:o.force===!0,forcePrompt:!0})});const r=n.command("workflow").description("Manage workflow graphs \u2014 new, start, deploy, trigger, logs, list, download, delete");r.command("new [name]").description("Scaffold a new custom workflow (alias of `zibby g workflow`)").option("-t, --template <name>","Scaffold from a template (see `zibby template list`). Future: also accepts npm package / git URL identifiers.").option("--skip-install","Skip running `npm install` in the new workflow folder").option("--skip-init-check","Skip the first-run init prompt that fires when ~/.zibby/config.json is missing (CI/scripted setups)").option("--agent-helpers [list]",'Install agent helpers (Claude Code / Cursor slash commands). List = comma-separated, e.g. "claude" or "claude,cursor". Bare flag defaults to claude.').option("--no-agent-helpers","Skip agent helpers even if .zibby.config.mjs says install").option("--agent <agent>","(legacy) Set up agent helpers: claude | cursor | codex | all | none. Prefer --agent-helpers.").option("--force-agents","Overwrite user-edited agent helper files (use with --agent-helpers)").action(async(e,o)=>{const{generateWorkflowCommand:t}=await import("../commands/workflows/generate.js");return t(e,o)}),r.command("run <workflow-name>").description("Run a workflow locally \u2014 one-shot, same input flags as `workflow trigger`").option("-p, --param <key=value>","Input param (repeatable, e.g. -p url=https://x.com -p count=5)",p,[]).option("--input <json>",`Input as JSON string \u2014 overridden by --param (e.g. '{"key":"value"}')`).option("--input-file <path>","Input as JSON file \u2014 lowest precedence").action(async(e,o)=>{const{runLocalWorkflowCommand:t}=await import("../commands/workflows/run-local.js");return t(e,o)}),r.command("start <workflow-name>").description("Start a long-lived local dev server (Studio integration). Prefer `workflow run` for one-shots.").option("-p, --port <port>","Port for the workflow server (default: 3848)").action(async(e,o)=>{const{startWorkflowCommand:t}=await import("../commands/workflows/start.js");return t(e,o)}),r.command("deploy [workflow-name]").description("Deploy a workflow to Zibby Cloud (alias of `zibby deploy`)").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--env <path>","Path to a .env file to sync into per-workflow env vars after deploy (repeatable)",p,[]).option("--verbose","Show raw CodeBuild logs during the bundle build").option("--no-creds-check","Skip the project secrets sanity check (CI/CD when the secret is provisioned out-of-band)").option("--force","Deploy even if the source checksum matches the last deployed version (bypasses the unchanged check)").option("--warm [count]",`Enable warm-pool execution for this workflow (default 1, max ${k}). Skips ~60s Fargate cold-start by routing triggers to a per-account pool of always-on tasks. Pricing applies (paid feature).`,b).action(async(e,o)=>{const{deployWorkflowCommand:t}=await import("../commands/workflows/deploy.js");return t(e,o)}),r.command("trigger [uuid]").description("Trigger a deployed workflow by UUID (alias of `zibby trigger`)").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("-p, --param <key=value>","Input param (repeatable, e.g. -p url=https://x.com -p count=5)",p,[]).option("--input <json>",`Input as JSON string \u2014 overridden by --param (e.g. '{"key":"value"}')`).option("--input-file <path>","Input as JSON/YAML file \u2014 lowest precedence").option("--idempotency-key <key>","Idempotency key to prevent duplicate executions").option("-t, --follow","Stream logs in real-time after triggering (no need to run `logs -t` separately)").action(async(e,o)=>{const{triggerWorkflowCommand:t}=await import("../commands/workflows/trigger.js");return t(e,o)}),r.command("logs [jobId]").description("Tail logs from a workflow execution (alias of `zibby logs`)").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--workflow <name>","Workflow name (fetches the latest run)").option("--all","Show interleaved logs from all runs (requires --workflow)").option("-t, --follow","Stream logs in real-time (like Heroku logs -t)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--lines <n>","Max log lines per fetch (default: 500)").action(async(e,o)=>{const{logsCommand:t}=await import("../commands/workflows/logs.js");return t(e,o)}),r.command("download <uuid>").description("Download a deployed workflow back to local (edit it, then re-deploy with `zibby workflow deploy`)").option("--dest <path>","Destination directory (default: ./workflows/<name> when run inside a .zibby project)").option("--force","Overwrite without prompting; bypass uuid-mismatch guard").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{downloadWorkflowCommand:t}=await import("../commands/workflows/download.js");return t(e,o)}),r.command("list").description("List all workflows (local + remote if credentials available)").option("--local-only","Show only local workflows").option("--remote-only","Show only remote workflows (requires --project)").option("--project <id>","Project ID (optional, uses ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async e=>{if(e.remoteOnly){const{workflowListCommand:t}=await import("../commands/workflow.js");return t(e)}if(e.localOnly){const{listLocalWorkflowsCommand:t}=await import("../commands/workflows/list.js");return t(e)}const{listAllWorkflowsCommand:o}=await import("../commands/workflows/list.js");return o(e)}),r.command("validate <name>").description("Static-check a local workflow (.zibby/workflows/<name>/). Catches schema/topology/skill errors in ~30ms before you run anything.").option("--verbose","Print stack traces on graph.mjs import errors").action(async(e,o)=>{const{validateCommand:t}=await import("../commands/workflows/validate.js");return t(e,o)}),r.command("schedule <uuid> [action] [cron]").description(`Manage a workflow's cron schedule. Actions: get (default) | set <cron> | clear. Cron is Unix 5-field, e.g. "0 9 * * 1-5".`).option("--tz <iana>","IANA timezone for the schedule (default: UTC)").option("-p, --param <key=value>","Fixed input param for every scheduled run (repeatable)",p,[]).option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o,t,s)=>{const{scheduleCommand:d}=await import("../commands/workflows/schedule.js");return d(e,o,t,s)});const y=r.command("webhook").description("Configure a workflow's inbound webhook + auth (enable/disable, basic/ip/token, show)");y.command("enable <uuid>").description("Enable the workflow's inbound webhook (HTTP trigger)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("enable",e,void 0,o)}),y.command("disable <uuid>").description("Disable the workflow's inbound webhook (HTTP trigger)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("disable",e,void 0,o)}),y.command("show <uuid>").description("Show current webhook config (which auth methods are on, masked token, IP list, URL)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("show",e,void 0,o)});const w=y.command("auth").description("Configure webhook auth methods: basic | ip | token");w.command("basic <uuid>").description("Enable HTTP Basic auth (or --disable to turn it off). Password optional on update.").option("--username <u>","Basic auth username").option("--password <p>","Basic auth password (plaintext; backend hashes it; omit to keep existing)").option("--disable","Turn Basic auth off").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("auth","basic",e,o)}),w.command("ip <uuid>").description("Set the IP allowlist (or --disable to turn it off)").option("--allow <cidr,...>","Comma-separated IPs/CIDRs, e.g. 1.2.3.4,10.0.0.0/8").option("--disable","Turn the IP allowlist off").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("auth","ip",e,o)}),w.command("token <uuid>").description("Generate a bearer token (--generate) \u2014 printed ONCE \u2014 or --disable to turn it off").option("--generate","Mint a new token; printed once in plaintext").option("--disable","Turn token auth off").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("auth","token",e,o)}),r.command("delete <uuid>").description("Delete a deployed workflow by UUID").action(async e=>{const{deleteWorkflowCommand:o}=await import("../commands/workflows/delete.js");return o(e,{})});const f=r.command("env").description("Manage per-workflow encrypted env vars (set ANTHROPIC_API_KEY, DATABASE_URL, etc. per workflow)");f.command("list <uuid>").description("List env var key names for a workflow (values never returned)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{listEnvCommand:t}=await import("../commands/workflows/env.js");return t(e,o)}),f.command("set <uuid> <kv>").description("Set or update one env var: zibby workflow env set <uuid> KEY=value").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o,t)=>{const{setEnvCommand:s}=await import("../commands/workflows/env.js");return s(e,o,t)}),f.command("unset <uuid> <key>").description("Remove one env var from a workflow").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o,t)=>{const{unsetEnvCommand:s}=await import("../commands/workflows/env.js");return s(e,o,t)}),f.command("push <uuid>").description("Bulk-replace env from one or more .env files (later files override). Removes any keys not in the new map.").option("--file <path>","Path to a .env file (repeatable, e.g. --file .env --file .env.prod)",p,[]).option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{pushEnvCommand:t}=await import("../commands/workflows/env.js");return t(e,o)});const $=n.command("project").description("Manage Zibby projects");$.command("list").description("List all projects").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async e=>{const{projectListCommand:o}=await import("../commands/project.js");return o(e)});const Q=n.command("run-queue").description("Parallel capacity \u2014 on-disk wait queue (see parallel.waitWhenAtCapacity in .zibby.config.mjs)");Q.command("list").description("List CLI processes waiting for a run slot").option("--config <path>","Path to config file",".zibby.config.mjs").action(async e=>{const{runCapacityQueueListCommand:o}=await import("../commands/run-capacity-queue-cli.js");await o(e),process.exit(0)});const X=n.command("mcp").description("Manage the Zibby Remote MCP integration in your AI agent");X.command("install").description("Auto-configure Zibby MCP into your AI agent (Claude Code/Desktop, Cursor, Codex, Gemini)").option("--agent <name>","claude-code | claude-desktop | cursor | codex | gemini").option("--all","Install for every supported agent on this machine").option("--token <pat>","Use this PAT (zby_pat_\u2026) instead of minting one via session. Also reads ZIBBY_PAT env var.").option("--force","Overwrite the existing zibby block even if unchanged").action(async e=>{const{mcpInstallCommand:o}=await import("../commands/mcp.js");await o(e),process.exit(0)});const i=n.command("app").description("Manage Zibby Managed Apps \u2014 templates, deploy, list, status, destroy");i.command("templates").description("List the app catalog (n8n, grafana, gas-town, \u2026)").action(async e=>{const{appTemplatesCommand:o}=await import("../commands/app.js");return o(e)}),i.command("list").description("List deployed app instances (use --project to scope to one project)").option("--project <id>","Project ID \u2014 defaults to all instances under your account").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async e=>{const{appListCommand:o}=await import("../commands/app.js");return o(e)}),i.command("deploy [appType]").description('Deploy an app \u2014 either from the catalog (e.g. `zibby app deploy grafana --project <id>`) or a free-form install described by --goal (e.g. `zibby app deploy --goal "Install n8n at /n8n on port 5678, persist data in /data" --project <id>`). Pass exactly one of <appType> OR --goal. Catalog deploys are curated by Zibby; goal-based deploys are user-directed installs where you (not Zibby) choose what gets installed and accept the license terms of whatever you install.').option("--mode <name>",'Deploy mode \u2014 "cloud" (default, shared Fargate) or "solo" (dedicated t4g.* EC2 per app, cheaper + isolated). Solo deploys take --repo / --tier / --secret instead of <appType>; see `zibby app deploy --mode solo --help` for the solo flags.').option("--slug <name>","[solo] App slug \u2014 used to form the public hostname <slug>.solo.zibby.app. lowercase [a-z0-9-], 1-40 chars.").option("--repo <ownerRepo>",'[solo] GitHub source repo in "owner/name" form. Mutually exclusive with --tarball.').option("--ref <ref>","[solo] Git ref (branch, tag, sha) to clone. Defaults to the repo's default branch.").option("--tarball <s3Url>","[solo] s3:// URL of a tarball source. Mutually exclusive with --repo.").option("--framework <name>",'[solo] Framework hint \u2014 auto (default), rails, node, python, static, other. "auto" lets agent-ops detect from the source tree.').option("--tier <id>","[solo] Instance tier id: micro | small | medium | large. Run `zibby app deploy --mode solo` without --tier to see the live pricing table.").option("--region <id>","[solo] AWS region for the VM: ap-southeast-2 (Sydney, default) | us-east-1 | us-west-2 | eu-west-1 | ap-northeast-1 | auto (latency-probe + pick nearest). The Zibby control plane stays in Sydney; only your app's EC2 + storage move. Pricing is the same in every region. Omit the flag in interactive mode to pick from a list sorted by measured latency.").option("--secret <kv...>","[solo] Repeatable. Each is KEY=VALUEREF where VALUEREF points at your workspace-credentials (uploaded via `zibby creds set`). Plaintext is NOT accepted here. Example: --secret STRIPE_KEY=workspace:stripe-prod.").option("--db-persistence <kind>","[solo] Database persistence: sqlite-litestream | postgres-walg | none (default).").option("--files-persistence <kind>","[solo] Files persistence: activestorage-s3 | rclone-bisync | none (default).").option("--no-tail","[solo] Skip the post-fire status tail. Default tails until phase=running/failed (max 15 min). --yes implies --no-tail.").option("-y, --yes","Non-interactive mode \u2014 exit 1 on any missing inputs instead of prompting. Implies --no-tail.").option("--project <id>","Project ID (interactive prompt if not provided)").option("--goal <text>",'Free-form natural-language description of what to install (mutually exclusive with <appType>). The agent-ops bootstrap follows the description \u2014 e.g. "install n8n on port 5678 with sqlite persistence". You are responsible for the license terms of any software you install via this path.').option("--name <name>","Instance display name (defaults to appType, or first line of --goal)").option("--provider <name>",'Agent provider \u2014 "claude" (default) or "codex"').option("--arch <name>",`CPU architecture \u2014 "x86_64" or "arm64" (default = catalog's first listed arch; arm64 is ~20% greener at the same price)`).option("--model <name>","Claude model identifier to use for the agent-ops bootstrap (e.g. claude-sonnet-4-6, claude-opus-4-5, claude-haiku-4-5-20251001). Overrides the daemon's baked default. Use a stronger model (Opus) for complex installs; a cheaper one (Haiku) for trivial ones.").option("--anthropic-token <token>","SENSITIVE: Per-deploy Claude credential override. Replaces the workspace-stored token for THIS deploy only \u2014 never persisted. Must start with sk-ant-oat01- (OAuth subscription) or sk-ant-api03- (Anthropic API key). Env equivalent: ZIBBY_ANTHROPIC_TOKEN.").option("--max-turns <n>","Cap on Claude subprocess --max-turns (cfg.Agent.MaxToolCallsPerTask). Default 25; bump for heavy goal-mode installs (n8n, OpenHands) that exhaust the default before finishing. Range 1..200. Example: --max-turns 60.").option("--timeout-min <n>","Bootstrap-task wall-clock cap in minutes. Default 30; bump when npm install / docker pull / native compile dominates wall time (n8n ~500MB install often takes 25-40min). Range 1..120. Example: --timeout-min 45.").option("--auth-type <kind>",'Optional auth sidecar \u2014 "basic" (username + password), "token" (bearer header), or "none" (default, no auth). Adds a tiny Caddy container in front of the public URL that gates requests. Use this on apps with weak / no built-in auth (Grafana ships admin/admin; n8n ships with nothing).').option("--auth-user <name>","Username for --auth-type basic. Required for basic auth. Printable ASCII, no spaces (1-64 chars).").option("--auth-password <pass>","SENSITIVE: Password for --auth-type basic. 8-256 chars; bcrypt-hashed server-side, plaintext never persisted. Env equivalent: ZIBBY_APP_AUTH_PASSWORD.").option("--auth-token <tok>","Optional explicit bearer token for --auth-type token. 16-128 chars, base64url alphabet only ([A-Za-z0-9_-]). Omit to let the backend auto-generate a 32-byte token (returned ONCE in the deploy response \u2014 save it). Env equivalent: ZIBBY_APP_AUTH_TOKEN.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appDeployCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("status <instanceId>").description("Show one instance: status, resources, public URL").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appStatusCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("destroy <instanceId>").description("Stop + remove an app instance (interactive confirm unless --yes)").option("-y, --yes","Skip the confirmation prompt").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appDestroyCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("upgrade <instanceId>").description("Roll the agent-ops container image without destroying the instance (EFS data preserved)").option("--version <tag>","Pin to a specific agent-ops version (e.g. 0.1.16). Defaults to whatever AppsFleet base task def says.").option("-y, --yes","Skip the confirmation prompt").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appUpgradeCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("update-credential <instanceId>").description("Rotate the per-instance Claude credential to whatever's currently in your workspace-credentials. EFS preserved; task restarts ~30s.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appUpdateCredentialCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("set-auth <instanceId>").description("Enable, rotate, or disable the optional Caddy auth sidecar on a running instance. Use --auth-type basic / token / none, or --off to disable. PATCH semantics: omitted flags preserve current state, so e.g. `zibby app set-auth <id> --auth-password new` rotates JUST the password on a basic-auth instance.").option("--auth-type <kind>",'"basic" | "token" | "none". Omit to keep current type (e.g. just rotate the password).').option("--auth-user <name>","Username for basic auth. Required when switching TO basic; preserved on subsequent rotations.").option("--auth-password <pass>","SENSITIVE: Password for basic auth. 8-256 chars; bcrypt-hashed server-side. Env equivalent: ZIBBY_APP_AUTH_PASSWORD.").option("--auth-token <tok>","Optional bearer token for token auth. Omit to let the backend regenerate a fresh 32-byte token (returned ONCE \u2014 save it). Env equivalent: ZIBBY_APP_AUTH_TOKEN.").option("--off","Disable the auth sidecar entirely (alias for --auth-type none). Caddy container removed; public URL exposes the app port directly again.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appSetAuthCommand:t}=await import("../commands/app.js");return t(e,o)});const l=i.command("auth").description("Manage access control on a running app instance: credential auth (basic / token / none) and/or an IP allowlist. `auth show|basic|token|clear|ip <instanceId>`.");l.command("show <instanceId>").description("Show the current access-control gate (credential auth type + IP allowlist).").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appAuthShowCommand:t}=await import("../commands/app-auth.js");return t(e,o)}),l.command("basic <instanceId>").description("Enable / rotate HTTP basic auth (username + password). Adds a Caddy sidecar that gates the public URL. Task restarts ~1 min.").requiredOption("--user <name>","Username (1-64 printable ASCII, no spaces)").option("--password <pass>","SENSITIVE: password (8-256 chars). Env equivalent: ZIBBY_APP_AUTH_PASSWORD.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appAuthBasicCommand:t}=await import("../commands/app-auth.js");return t(e,o)}),l.command("token <instanceId>").description("Enable / rotate bearer-token auth. Omit --token to let the backend auto-generate one (printed ONCE \u2014 save it). Task restarts ~1 min.").option("--token <tok>","Optional explicit token (16-128 chars, base64url [A-Za-z0-9_-]). Omit to auto-generate. Env equivalent: ZIBBY_APP_AUTH_TOKEN.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appAuthTokenCommand:t}=await import("../commands/app-auth.js");return t(e,o)}),l.command("clear <instanceId>").description("Disable credential auth (authType none). The Caddy credential check is removed; any IP allowlist is left intact (clear it with `auth ip --clear-ip`).").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appAuthClearCommand:t}=await import("../commands/app-auth.js");return t(e,o)}),l.command("ip <instanceId>").description("Manage the IP allowlist (independent of credential auth). Only the listed source IPs/CIDRs may reach the app; all others get 403. SECURITY: enforced behind the ALB via X-Forwarded-For \u2014 verify it works on your instance before relying on it.").option("--allow <cidr...>","One or more IPs/CIDRs to allow (e.g. --allow 203.0.113.5/32 198.51.100.0/24). Replaces the current allowlist.").option("--clear-ip","Remove the IP allowlist entirely (all source IPs allowed again). Credential auth is left untouched.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appAuthIpCommand:t}=await import("../commands/app-auth.js");return t(e,o)}),i.command("logs <instanceId>").description("Show recent logs from an app instance (use -t to tail; polls every 3s)").option("-t, --follow","Tail mode \u2014 poll every 3s and print new lines as they arrive (Ctrl+C to stop)").option("--lines <n>","Max lines per fetch (default 200, max 5000)").option("--service <name>","For multi-container apps: limit logs to one service (e.g. `db`, `web`, `agent-ops`). Defaults to interleaved across all containers.").option("--json","Print raw JSON lines (one per line) instead of parsed summary").option("--verbose","Print the full line including JSON body (default: parsed `<time> <msg>` summary)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appLogsCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("run [cmd...]").description("Run a one-off command on a linked solo app (e.g. `zibby app run rails db:migrate`). Attaches your TTY via SSM \u2014 no AWS creds needed.").option("--app <slug>","App slug (defaults to the nearest .zibby/app.json)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appRunCommand:t}=await import("../commands/app-run.js");return t(e,o)}),i.command("console").description("Open the framework REPL on a linked solo app (rails console, python manage.py shell, node, iex -S mix)").option("--app <slug>","App slug (defaults to the nearest .zibby/app.json)").option("--framework <name>","Override the framework from the link file (rails | django | python | node | elixir)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async e=>{const{appConsoleCommand:o}=await import("../commands/app-run.js");return o(e)}),i.command("migrate").description("Run database migrations on a linked solo app (rails db:migrate / python manage.py migrate)").option("--app <slug>","App slug (defaults to the nearest .zibby/app.json)").option("--framework <name>","Override the framework from the link file").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async e=>{const{appMigrateCommand:o}=await import("../commands/app-run.js");return o(e)}),i.command("rollback [steps]").description("Roll back the last database migration(s) on a linked solo app (rails db:rollback STEP=<n>, default 1)").option("--app <slug>","App slug (defaults to the nearest .zibby/app.json)").option("--framework <name>","Override the framework from the link file").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appRollbackCommand:t}=await import("../commands/app-run.js");return t(e,o)}),i.command("link <slug>").description("Link the current directory to a solo app \u2014 writes .zibby/app.json (commit it so your team can `zibby app run` without --app)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appLinkCommand:t}=await import("../commands/app-run.js");return t(e,o)}),n.command("uninstall").description("Remove all Zibby data: global CLI, ~/.zibby, Cursor MCP config, Studio, and current project").option("--dry-run","Show what would be deleted without deleting").option("--deep","Also remove npx cache dirs containing zibby").action(async e=>{const{uninstallCommand:o}=await import("../commands/uninstall.js");await o(e),process.exit(0)}),n.parse();
49
+ `),n.command("init").description("Initialize a Zibby project (config + credentials only \u2014 pass -t <name> to also scaffold a workflow template)").argument("[project-name]","Project name (optional, uses current directory if not provided)").option("--agent <type>","Agent to use (claude, cursor, codex, gemini)").option("--memory-backend <backend>","Memory backend to configure (mem0, dolt). Default: mem0 (semantic vector memory; falls back to dolt if the embedding proxy is unavailable). Use dolt for self-contained structured memory.","mem0").option("--infer","Smart memory: let the LLM distill/dedupe facts on store (mem0 only; costs tokens). Default off = embed-only, free.").option("-t, --template <name>","Workflow template to scaffold into .zibby/ (see `zibby template list`). Default: none \u2014 init only sets up config and credentials.").option("--skip-install","Skip npm install").option("--skip-memory","Skip test memory setup during initialization").option("-f, --force","Force reinitialize (overwrite existing config)").option("--headed","Run MCP browser in headed mode (visible browser)").option("--headless","Run MCP browser in headless mode (hidden browser)").option("--api-key <key>","Zibby API key for cloud sync").option("--cloud-sync","Enable cloud sync and install Zibby MCP").option("--agent-key <key>","Agent API key (non-interactive). For Claude this is the per-token API key").option("--agent-oauth-token <token>","Claude OAuth subscription token (non-interactive). Saves to ~/.zibby/config.json").action(A),n.command("test").description("Run a test specification").argument("[spec-path]","Path to test spec file or inline test description in quotes").option("--sources <ids>","Comma-separated test case IDs to fetch from cloud").option("--execution <id>","Execution ID containing the test cases (required with --sources)").option("--agent <type>","Agent to use (claude, cursor, codex, gemini) - overrides config").option("--workflow <name>","Workflow to use (e.g., QuickSmokeWorkflow, quick-smoke)").option("--headless","Run browser in headless mode").option("--node <name>","Run only a specific node (e.g., execute_live, generate_script)").option("--session <id>",'Use existing session (e.g., 1768974629717 or "last") - requires --node').option("--session-path <dir>","Use this session folder (absolute or relative to cwd); Studio pins artifacts here").option("--project <id>","Project ID (optional, auto-detected from ZIBBY_API_KEY)").option("--collection <id-or-name>","Collection ID or name (creates new if name doesn't exist)").option("--folder <path>","Folder path within collection (optional, requires --collection)").option("--sync","Force upload to cloud (overrides cloudSync: false)").option("--no-sync","Skip upload to cloud (overrides cloudSync: true)").option("--config <path>","Path to config file",".zibby.config.mjs").option("--auto-approve","Auto-approve MCP tools (for CI/CD)").option("-o, --open","Open test results in browser after completion").option("--verbose","Show info level logs").option("--debug","Show debug level logs (most verbose)").option("-m, --mem","Enable test memory (Dolt-backed knowledge from previous runs)").action((e,o)=>(o.debug?process.env.ZIBBY_DEBUG="true":o.verbose&&(process.env.ZIBBY_VERBOSE="true"),_(e,o))),n.command("implement").description("Implement a Jira ticket using AI agent (runs in ECS container)").action(async(...e)=>{const{implementCommand:o}=await import("../commands/implement.js");return o(...e)}),n.command("analyze").description("Analyze a Jira ticket against the codebase (runs in ECS container)").option("--workflow <path>","Path to a local workflow JSON file (e.g., .zibby/workflow-analysis.json)").action(async(...e)=>{const{analyzeCommand:o}=await import("../commands/analyze-graph.js");return o(...e)}),n.command("video").description("Organize test videos next to test files").action(S),n.command("upload <spec-path>").description("Upload existing test artifacts to Zibby Cloud").option("--project <id>","Project ID (REQUIRED - use flag or ZIBBY_PROJECT_ID env)").option("--collection <id-or-name>","Collection ID or name (creates new if name doesn't exist)").option("--folder <path>","Folder path within collection (optional)").option("--agent <type>","Agent used (for metadata)").action(B),n.command("login").description("Log in to Zibby (opens browser for authentication)").action(async()=>{const{loginCli:e}=await import("../auth/cli-login.js");await e(),process.exit(0)}),n.command("logout").description("Log out from Zibby (clears saved session)").action(async()=>{const{logoutCli:e}=await import("../auth/cli-login.js");e(),process.exit(0)}),n.command("status").description("Show current authentication status and token details").option("--json","Output in JSON format (for scripts)").action(async e=>{const{showLoginStatus:o}=await import("../auth/cli-login.js");await o(e),process.exit(0)}),n.command("list").description("List your projects and API tokens").action(async()=>{const{listProjectsCommand:e}=await import("../commands/list-projects.js");await e()}),n.command("ci-setup").description("Setup Cursor Agent for CI/CD (patch and configure)").option("--get-keys","Get MCP approval keys").option("--save","Save approval keys to project").action(E),n.command("setup-playwright").description("Setup official Playwright MCP (from cursor-agent-package)").option("--headed","Configure MCP in headed mode (visible browser)").option("--viewport-width <width>","Viewport width (default: 1280)","1280").option("--viewport-height <height>","Viewport height (default: 720)","720").action(e=>{const o={width:parseInt(e.viewportWidth,10)||1280,height:parseInt(e.viewportHeight,10)||720};return Y({...e,viewport:o})}),n.command("setup-ci-full").description("Complete CI/CD setup from scratch").action(x),n.command("test-video").description("Run Playwright tests with video recording").argument("[test-file]","Test file to run (default: tests/)").option("--headed","Run in headed mode (visible browser)").action(O),n.command("generate").description("Generate test specs from a ticket + codebase (local analysis using real AI agent)").option("-t, --ticket <key>","Jira ticket key (fetches automatically)").option("-i, --input <file>","Input file with ticket description/requirements").option("-d, --description <text>","Inline ticket description").option("--repo <path>","Path to the codebase (default: current directory)").option("--agent <type>","Agent to use (codex, claude, cursor, gemini)").option("--model <model>","Model override").option("-o, --output <dir>","Output directory for spec files (default: test-specs)").action(async e=>{const{generateCommand:o}=await import("../commands/generate.js");return o(e)}),n.command("studio").description("Launch Zibby Studio desktop (installs from CDN if needed). Uses this folder as the Zibby project.").option("-p, --port <port>","Port for the Studio API bridge (default: 3847)").option("--no-open","Start the API only; do not launch desktop app").option("--update","Force re-download of the latest Studio binary").action(async e=>{const{studioCommand:o}=await import("../commands/studio.js");return o(e)});const m=n.command("creds").description("Manage credentials Zibby has stored for your workspace (KMS-encrypted)");m.command("list").description("List credentials stored for your workspace (masked)").action(async()=>{const{listCmd:e}=await import("../commands/creds.js");await e(),process.exit(0)}),m.command("sync").description("Re-read ~/.zibby/credentials.env and upload any new tokens").action(async()=>{const{syncCmd:e}=await import("../commands/creds.js");await e(),process.exit(0)}),m.command("set <provider> <token>").description("Paste-token shortcut. e.g. zibby creds set claude sk-ant-oat01-... (auto-detects oauth vs api)").option("--type <kind>","Force credential kind: oauth | api (skips auto-detect)").action(async(e,o,t)=>{const{setCmd:s}=await import("../commands/creds.js");await s(e,o,t),process.exit(0)}),m.command("remove <type> <index>").description("Remove a stored credential. e.g. zibby creds remove oauth 0").action(async(e,o)=>{const{removeCmd:t}=await import("../commands/creds.js");await t(e,o),process.exit(0)});const G=n.command("g").description("Generate scaffolds");G.command("workflow [name]").description("Scaffold a new custom workflow in .zibby/workflows/<name>/ (auto-generates name if omitted)").option("-t, --template <name>","Scaffold from a template (see `zibby template list`). Future: also accepts npm package / git URL identifiers.").option("--skip-install","Skip running `npm install` in the new workflow folder").option("--skip-init-check","Skip the first-run init prompt that fires when ~/.zibby/config.json is missing (CI/scripted setups)").option("--agent-helpers [list]",'Install agent helpers (Claude Code / Cursor slash commands). List = comma-separated, e.g. "claude" or "claude,cursor". Bare flag defaults to claude.').option("--no-agent-helpers","Skip agent helpers even if .zibby.config.mjs says install").option("--agent <agent>","(legacy) Set up agent helpers: claude | cursor | codex | all | none. Prefer --agent-helpers.").option("--force-agents","Overwrite user-edited agent helper files (use with --agent-helpers)").action(async(e,o)=>{const{generateWorkflowCommand:t}=await import("../commands/workflows/generate.js");return t(e,o)}),n.command("start <workflow-name>").description("Start a local dev server for a custom workflow").option("-p, --port <port>","Port for the workflow server (default: 3848)").action(async(e,o)=>{const{startWorkflowCommand:t}=await import("../commands/workflows/start.js");return t(e,o)}),n.command("run <workflow-name>").description("Run a workflow locally \u2014 one-shot (alias of `zibby workflow run`)").option("-p, --param <key=value>","Input param (repeatable)",p,[]).option("--input <json>","Input as JSON string").option("--input-file <path>","Input as JSON file").action(async(e,o)=>{const{runLocalWorkflowCommand:t}=await import("../commands/workflows/run-local.js");return t(e,o)}),n.command("deploy [workflow-name]").description("Deploy a custom workflow to Zibby Cloud (interactive selection if workflow-name not provided)").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--dedicated-ip <action>","Manage dedicated egress IP addon: enable | status | disable | use | unuse").option("--env <path>","Path to a .env file to sync into per-workflow env vars after deploy (repeatable)",p,[]).option("--verbose","Show raw CodeBuild logs during the bundle build").option("--no-creds-check","Skip the project secrets sanity check (CI/CD when the secret is provisioned out-of-band)").option("--force","Deploy even if the source checksum matches the last deployed version (bypasses the unchanged check)").option("--warm [count]",`Enable warm-pool execution for this workflow (default 1, max ${k}). Skips ~60s Fargate cold-start by routing triggers to a per-account pool of always-on tasks. Pricing applies (paid feature).`,v).option("--ai-agent <agent>","Per-workflow AI agent override (claude | cursor | codex | gemini). Falls back to the project default when omitted.").action(async(e,o)=>{if(o.dedicatedIp){const{dedicatedEgressCommand:s}=await import("../commands/workflows/dedicated-egress.js");return s(o.dedicatedIp,o.project)}o.aiAgent&&!["claude","cursor","codex","gemini"].includes(o.aiAgent)&&(console.error(chalk.red(`Invalid --ai-agent: ${o.aiAgent}. Must be one of: claude, cursor, codex, gemini.`)),process.exit(1));const{deployWorkflowCommand:t}=await import("../commands/workflows/deploy.js");return t(e,o)}),n.command("trigger [uuid]").description("Trigger a deployed workflow by UUID (interactive selection if not provided). Get UUIDs from `zibby workflow list`.").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("-p, --param <key=value>","Input param (repeatable, e.g. -p url=https://x.com -p count=5)",p,[]).option("--input <json>",`Input as JSON string \u2014 overridden by --param (e.g. '{"key":"value"}')`).option("--input-file <path>","Input as JSON/YAML file \u2014 lowest precedence").option("--idempotency-key <key>","Idempotency key to prevent duplicate executions").option("-t, --follow","Stream logs in real-time after triggering (no need to run `logs -t` separately)").action(async(e,o)=>{const{triggerWorkflowCommand:t}=await import("../commands/workflows/trigger.js");return t(e,o)}),n.command("run-workflow").description("Run a deployed workflow from S3 sources (used by ECS containers)").action(async()=>{const{runWorkflowCommand:e}=await import("../commands/workflows/run.js");return e()});const C=n.command("template").description("Manage workflow templates in this project");C.command("list").description("List available workflow templates").action(async()=>{const{templateListCommand:e}=await import("../commands/template.js");return e()}),C.command("add",{hidden:!0}).argument("<name>","Template name (see `zibby template list`)").description("(deprecated \u2014 `zibby test` auto-installs the template) Copy a template into .zibby/, overwriting existing files").option("--skip-memory","Strip SKILLS.MEMORY from copied execute-live.mjs (browser-test only)").action(async(e,o)=>{const{templateAddCommand:t}=await import("../commands/template.js");return t(e,{enableMemory:!o.skipMemory})});const c=n.command("memory").description("Test memory database \u2014 version-controlled knowledge from runs");c.command("stats").description("Show memory database statistics").action(async()=>{const{memoryStatsCommand:e}=await import("../commands/memory.js");return e()}),c.command("init").description("Initialize the memory database (Dolt)").action(async()=>{const{memoryInitCommand:e}=await import("../commands/memory.js");return e()}),c.command("compact").description("Prune old data and run Dolt GC to reclaim storage").option("--max-runs <n>","Keep last N runs per spec (default: 50)",parseInt).option("--max-age <days>","Remove data older than N days (default: 90)",parseInt).action(async e=>{const{memoryCompactCommand:o}=await import("../commands/memory.js");return o(e)}),c.command("reset").description("Wipe the memory database").option("-f, --force","Confirm reset").action(async e=>{const{memoryResetCommand:o}=await import("../commands/memory.js");return o(e)}),c.command("cost").description("Show real LLM token usage from past runs (input/output/cache)").action(async()=>{const{memoryCostCommand:e}=await import("../commands/memory.js");return e()});const u=c.command("remote").description("Configure a remote so the team shares cross-spec memory");u.command("add").argument("<url>","Remote URL: aws://, gs://, https://, file:///").option("--name <name>","Remote name (default: origin)","origin").description("Point the local memory DB at a shared remote (S3/GCS/DoltHub/filesystem)").action(async(e,o)=>{const{memoryRemoteAddCommand:t}=await import("../commands/memory.js");return t(e,o)}),u.command("use").description("Switch to a managed remote backend. Currently: --hosted (Zibby-managed S3, signed-in users only).").option("--hosted","Use Zibby-managed S3 (allocates a tenant-scoped prefix per-project)").option("--project-id <id>","Override the projectId from .zibby.config.mjs").action(async e=>{e.hosted||(console.log("Pass --hosted. (Other backends will be added later.)"),process.exit(1));const{memoryRemoteUseHostedCommand:o}=await import("../commands/memory.js");return o(e)}),u.command("info").description("Show the configured memory remote (if any)").action(async()=>{const{memoryRemoteInfoCommand:e}=await import("../commands/memory.js");return e()}),u.command("remove").argument("[name]","Remote name (default: origin)").description("Remove a configured memory remote (memory becomes local-only)").action(async e=>{const{memoryRemoteRemoveCommand:o}=await import("../commands/memory.js");return o(e)}),c.command("pull").description("Pull latest team memory from the configured remote").action(async()=>{const{memoryPullCommand:e}=await import("../commands/memory.js");return e()}),c.command("push").description("Push local memory to the configured remote (auto-runs after passing tests)").action(async()=>{const{memoryPushCommand:e}=await import("../commands/memory.js");return e()});const V=n.command("agents").description("Manage Claude/Cursor/Codex helper files for working with Zibby workflows");V.command("add [agent]").description("Add agent helpers (claude | cursor | codex | all). Prompts if no agent given.").option("--force","Overwrite user-edited helper files").action(async(e,o)=>{const{runAgentHelpers:t,addAgent:s}=await import("../commands/workflows/agent-helpers.js");if(e){const d=["claude","cursor","codex","all","none"];d.includes(e)||(console.error(`Unknown agent "${e}". Valid: ${d.join(", ")}`),process.exit(1)),e==="none"?await t({forcedAgents:["none"],force:o.force===!0}):e==="all"?await t({forcedAgents:["claude","cursor","codex"],force:o.force===!0}):await s(e,{force:o.force===!0})}else await t({forcedAgents:void 0,force:o.force===!0,forcePrompt:!0})});const r=n.command("workflow").alias("agent").description("Manage agents \u2014 new, start, deploy, trigger, logs, list, download, delete (alias: workflow)");r.command("new [name]").description("Scaffold a new custom workflow (alias of `zibby g workflow`)").option("-t, --template <name>","Scaffold from a template (see `zibby template list`). Future: also accepts npm package / git URL identifiers.").option("--skip-install","Skip running `npm install` in the new workflow folder").option("--skip-init-check","Skip the first-run init prompt that fires when ~/.zibby/config.json is missing (CI/scripted setups)").option("--agent-helpers [list]",'Install agent helpers (Claude Code / Cursor slash commands). List = comma-separated, e.g. "claude" or "claude,cursor". Bare flag defaults to claude.').option("--no-agent-helpers","Skip agent helpers even if .zibby.config.mjs says install").option("--agent <agent>","(legacy) Set up agent helpers: claude | cursor | codex | all | none. Prefer --agent-helpers.").option("--force-agents","Overwrite user-edited agent helper files (use with --agent-helpers)").action(async(e,o)=>{const{generateWorkflowCommand:t}=await import("../commands/workflows/generate.js");return t(e,o)}),r.command("run <workflow-name>").description("Run a workflow locally \u2014 one-shot, same input flags as `workflow trigger`").option("-p, --param <key=value>","Input param (repeatable, e.g. -p url=https://x.com -p count=5)",p,[]).option("--input <json>",`Input as JSON string \u2014 overridden by --param (e.g. '{"key":"value"}')`).option("--input-file <path>","Input as JSON file \u2014 lowest precedence").action(async(e,o)=>{const{runLocalWorkflowCommand:t}=await import("../commands/workflows/run-local.js");return t(e,o)}),r.command("start <workflow-name>").description("Start a long-lived local dev server (Studio integration). Prefer `workflow run` for one-shots.").option("-p, --port <port>","Port for the workflow server (default: 3848)").action(async(e,o)=>{const{startWorkflowCommand:t}=await import("../commands/workflows/start.js");return t(e,o)}),r.command("deploy [workflow-name]").description("Deploy a workflow to Zibby Cloud (alias of `zibby deploy`)").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--env <path>","Path to a .env file to sync into per-workflow env vars after deploy (repeatable)",p,[]).option("--verbose","Show raw CodeBuild logs during the bundle build").option("--no-creds-check","Skip the project secrets sanity check (CI/CD when the secret is provisioned out-of-band)").option("--force","Deploy even if the source checksum matches the last deployed version (bypasses the unchanged check)").option("--warm [count]",`Enable warm-pool execution for this workflow (default 1, max ${k}). Skips ~60s Fargate cold-start by routing triggers to a per-account pool of always-on tasks. Pricing applies (paid feature).`,v).action(async(e,o)=>{const{deployWorkflowCommand:t}=await import("../commands/workflows/deploy.js");return t(e,o)}),r.command("trigger [uuid]").description("Trigger a deployed workflow by UUID (alias of `zibby trigger`)").option("--project <id>","Project ID (interactive prompt if not provided, or ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("-p, --param <key=value>","Input param (repeatable, e.g. -p url=https://x.com -p count=5)",p,[]).option("--input <json>",`Input as JSON string \u2014 overridden by --param (e.g. '{"key":"value"}')`).option("--input-file <path>","Input as JSON/YAML file \u2014 lowest precedence").option("--idempotency-key <key>","Idempotency key to prevent duplicate executions").option("-t, --follow","Stream logs in real-time after triggering (no need to run `logs -t` separately)").action(async(e,o)=>{const{triggerWorkflowCommand:t}=await import("../commands/workflows/trigger.js");return t(e,o)}),r.command("logs [jobId]").description("Tail logs from a workflow execution (alias of `zibby logs`)").option("--project <id>","Project ID (or ZIBBY_PROJECT_ID env)").option("--workflow <name>","Workflow name (fetches the latest run)").option("--all","Show interleaved logs from all runs (requires --workflow)").option("-t, --follow","Stream logs in real-time (like Heroku logs -t)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").option("--lines <n>","Max log lines per fetch (default: 500)").action(async(e,o)=>{const{logsCommand:t}=await import("../commands/workflows/logs.js");return t(e,o)}),r.command("download <uuid>").description("Download a deployed workflow back to local (edit it, then re-deploy with `zibby workflow deploy`)").option("--dest <path>","Destination directory (default: ./workflows/<name> when run inside a .zibby project)").option("--force","Overwrite without prompting; bypass uuid-mismatch guard").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{downloadWorkflowCommand:t}=await import("../commands/workflows/download.js");return t(e,o)}),r.command("list").description("List all workflows (local + remote if credentials available)").option("--local-only","Show only local workflows").option("--remote-only","Show only remote workflows (requires --project)").option("--project <id>","Project ID (optional, uses ZIBBY_PROJECT_ID env)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async e=>{if(e.remoteOnly){const{workflowListCommand:t}=await import("../commands/workflow.js");return t(e)}if(e.localOnly){const{listLocalWorkflowsCommand:t}=await import("../commands/workflows/list.js");return t(e)}const{listAllWorkflowsCommand:o}=await import("../commands/workflows/list.js");return o(e)}),r.command("validate <name>").description("Static-check a local workflow (.zibby/workflows/<name>/). Catches schema/topology/skill errors in ~30ms before you run anything.").option("--verbose","Print stack traces on graph.mjs import errors").action(async(e,o)=>{const{validateCommand:t}=await import("../commands/workflows/validate.js");return t(e,o)}),r.command("schedule <uuid> [action] [cron]").description(`Manage a workflow's cron schedule. Actions: get (default) | set <cron> | clear. Cron is Unix 5-field, e.g. "0 9 * * 1-5".`).option("--tz <iana>","IANA timezone for the schedule (default: UTC)").option("-p, --param <key=value>","Fixed input param for every scheduled run (repeatable)",p,[]).option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o,t,s)=>{const{scheduleCommand:d}=await import("../commands/workflows/schedule.js");return d(e,o,t,s)});const y=r.command("webhook").description("Configure a workflow's inbound webhook + auth (enable/disable, basic/ip/token, show)");y.command("enable <uuid>").description("Enable the workflow's inbound webhook (HTTP trigger)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("enable",e,void 0,o)}),y.command("disable <uuid>").description("Disable the workflow's inbound webhook (HTTP trigger)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("disable",e,void 0,o)}),y.command("show <uuid>").description("Show current webhook config (which auth methods are on, masked token, IP list, URL)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("show",e,void 0,o)});const w=y.command("auth").description("Configure webhook auth methods: basic | ip | token");w.command("basic <uuid>").description("Enable HTTP Basic auth (or --disable to turn it off). Password optional on update.").option("--username <u>","Basic auth username").option("--password <p>","Basic auth password (plaintext; backend hashes it; omit to keep existing)").option("--disable","Turn Basic auth off").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("auth","basic",e,o)}),w.command("ip <uuid>").description("Set the IP allowlist (or --disable to turn it off)").option("--allow <cidr,...>","Comma-separated IPs/CIDRs, e.g. 1.2.3.4,10.0.0.0/8").option("--disable","Turn the IP allowlist off").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("auth","ip",e,o)}),w.command("token <uuid>").description("Generate a bearer token (--generate) \u2014 printed ONCE \u2014 or --disable to turn it off").option("--generate","Mint a new token; printed once in plaintext").option("--disable","Turn token auth off").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{webhookCommand:t}=await import("../commands/workflows/webhook.js");return t("auth","token",e,o)}),r.command("delete <uuid>").description("Delete a deployed workflow by UUID").action(async e=>{const{deleteWorkflowCommand:o}=await import("../commands/workflows/delete.js");return o(e,{})});const f=r.command("env").description("Manage per-workflow encrypted env vars (set ANTHROPIC_API_KEY, DATABASE_URL, etc. per workflow)");f.command("list <uuid>").description("List env var key names for a workflow (values never returned)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{listEnvCommand:t}=await import("../commands/workflows/env.js");return t(e,o)}),f.command("set <uuid> <kv>").description("Set or update one env var: zibby workflow env set <uuid> KEY=value").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o,t)=>{const{setEnvCommand:s}=await import("../commands/workflows/env.js");return s(e,o,t)}),f.command("unset <uuid> <key>").description("Remove one env var from a workflow").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o,t)=>{const{unsetEnvCommand:s}=await import("../commands/workflows/env.js");return s(e,o,t)}),f.command("push <uuid>").description("Bulk-replace env from one or more .env files (later files override). Removes any keys not in the new map.").option("--file <path>","Path to a .env file (repeatable, e.g. --file .env --file .env.prod)",p,[]).option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{pushEnvCommand:t}=await import("../commands/workflows/env.js");return t(e,o)});const $=n.command("project").description("Manage Zibby projects");$.command("list").description("List all projects").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async e=>{const{projectListCommand:o}=await import("../commands/project.js");return o(e)});const Q=n.command("run-queue").description("Parallel capacity \u2014 on-disk wait queue (see parallel.waitWhenAtCapacity in .zibby.config.mjs)");Q.command("list").description("List CLI processes waiting for a run slot").option("--config <path>","Path to config file",".zibby.config.mjs").action(async e=>{const{runCapacityQueueListCommand:o}=await import("../commands/run-capacity-queue-cli.js");await o(e),process.exit(0)});const X=n.command("mcp").description("Manage the Zibby Remote MCP integration in your AI agent");X.command("install").description("Auto-configure Zibby MCP into your AI agent (Claude Code/Desktop, Cursor, Codex, Gemini)").option("--agent <name>","claude-code | claude-desktop | cursor | codex | gemini").option("--all","Install for every supported agent on this machine").option("--token <pat>","Use this PAT (zby_pat_\u2026) instead of minting one via session. Also reads ZIBBY_PAT env var.").option("--force","Overwrite the existing zibby block even if unchanged").action(async e=>{const{mcpInstallCommand:o}=await import("../commands/mcp.js");await o(e),process.exit(0)});const i=n.command("app").description("Manage Zibby Managed Apps \u2014 templates, deploy, list, status, destroy");i.command("templates").description("List the app catalog (n8n, grafana, gas-town, \u2026)").action(async e=>{const{appTemplatesCommand:o}=await import("../commands/app.js");return o(e)}),i.command("list").description("List deployed app instances (use --project to scope to one project)").option("--project <id>","Project ID \u2014 defaults to all instances under your account").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async e=>{const{appListCommand:o}=await import("../commands/app.js");return o(e)}),i.command("deploy [appType]").description('Deploy an app \u2014 either from the catalog (e.g. `zibby app deploy grafana --project <id>`) or a free-form install described by --goal (e.g. `zibby app deploy --goal "Install n8n at /n8n on port 5678, persist data in /data" --project <id>`). Pass exactly one of <appType> OR --goal. Catalog deploys are curated by Zibby; goal-based deploys are user-directed installs where you (not Zibby) choose what gets installed and accept the license terms of whatever you install.').option("--mode <name>",'Deploy mode \u2014 "cloud" (default, shared Fargate) or "solo" (dedicated t4g.* EC2 per app, cheaper + isolated). Solo deploys take --repo / --tier / --secret instead of <appType>; see `zibby app deploy --mode solo --help` for the solo flags.').option("--slug <name>","[solo] App slug \u2014 used to form the public hostname <slug>.solo.zibby.app. lowercase [a-z0-9-], 1-40 chars.").option("--repo <ownerRepo>",'[solo] GitHub source repo in "owner/name" form. Mutually exclusive with --tarball.').option("--ref <ref>","[solo] Git ref (branch, tag, sha) to clone. Defaults to the repo's default branch.").option("--tarball <s3Url>","[solo] s3:// URL of a tarball source. Mutually exclusive with --repo.").option("--framework <name>",'[solo] Framework hint \u2014 auto (default), rails, node, python, static, other. "auto" lets agent-ops detect from the source tree.').option("--tier <id>","[solo] Instance tier id: micro | small | medium | large. Run `zibby app deploy --mode solo` without --tier to see the live pricing table.").option("--region <id>","[solo] AWS region for the VM: ap-southeast-2 (Sydney, default) | us-east-1 | us-west-2 | eu-west-1 | ap-northeast-1 | auto (latency-probe + pick nearest). The Zibby control plane stays in Sydney; only your app's EC2 + storage move. Pricing is the same in every region. Omit the flag in interactive mode to pick from a list sorted by measured latency.").option("--secret <kv...>","[solo] Repeatable. Each is KEY=VALUEREF where VALUEREF points at your workspace-credentials (uploaded via `zibby creds set`). Plaintext is NOT accepted here. Example: --secret STRIPE_KEY=workspace:stripe-prod.").option("--db-persistence <kind>","[solo] Database persistence: sqlite-litestream | postgres-walg | none (default).").option("--files-persistence <kind>","[solo] Files persistence: activestorage-s3 | rclone-bisync | none (default).").option("--no-tail","[solo] Skip the post-fire status tail. Default tails until phase=running/failed (max 15 min). --yes implies --no-tail.").option("-y, --yes","Non-interactive mode \u2014 exit 1 on any missing inputs instead of prompting. Implies --no-tail.").option("--project <id>","Project ID (interactive prompt if not provided)").option("--goal <text>",'Free-form natural-language description of what to install (mutually exclusive with <appType>). The agent-ops bootstrap follows the description \u2014 e.g. "install n8n on port 5678 with sqlite persistence". You are responsible for the license terms of any software you install via this path.').option("--name <name>","Instance display name (defaults to appType, or first line of --goal)").option("--provider <name>",'Agent provider \u2014 "claude" (default) or "codex"').option("--arch <name>",`CPU architecture \u2014 "x86_64" or "arm64" (default = catalog's first listed arch; arm64 is ~20% greener at the same price)`).option("--model <name>","Claude model identifier to use for the agent-ops bootstrap (e.g. claude-sonnet-4-6, claude-opus-4-5, claude-haiku-4-5-20251001). Overrides the daemon's baked default. Use a stronger model (Opus) for complex installs; a cheaper one (Haiku) for trivial ones.").option("--anthropic-token <token>","SENSITIVE: Per-deploy Claude credential override. Replaces the workspace-stored token for THIS deploy only \u2014 never persisted. Must start with sk-ant-oat01- (OAuth subscription) or sk-ant-api03- (Anthropic API key). Env equivalent: ZIBBY_ANTHROPIC_TOKEN.").option("--max-turns <n>","Cap on Claude subprocess --max-turns (cfg.Agent.MaxToolCallsPerTask). Default 25; bump for heavy goal-mode installs (n8n, OpenHands) that exhaust the default before finishing. Range 1..200. Example: --max-turns 60.").option("--timeout-min <n>","Bootstrap-task wall-clock cap in minutes. Default 30; bump when npm install / docker pull / native compile dominates wall time (n8n ~500MB install often takes 25-40min). Range 1..120. Example: --timeout-min 45.").option("--auth-type <kind>",'Optional auth sidecar \u2014 "basic" (username + password), "token" (bearer header), or "none" (default, no auth). Adds a tiny Caddy container in front of the public URL that gates requests. Use this on apps with weak / no built-in auth (Grafana ships admin/admin; n8n ships with nothing).').option("--auth-user <name>","Username for --auth-type basic. Required for basic auth. Printable ASCII, no spaces (1-64 chars).").option("--auth-password <pass>","SENSITIVE: Password for --auth-type basic. 8-256 chars; bcrypt-hashed server-side, plaintext never persisted. Env equivalent: ZIBBY_APP_AUTH_PASSWORD.").option("--auth-token <tok>","Optional explicit bearer token for --auth-type token. 16-128 chars, base64url alphabet only ([A-Za-z0-9_-]). Omit to let the backend auto-generate a 32-byte token (returned ONCE in the deploy response \u2014 save it). Env equivalent: ZIBBY_APP_AUTH_TOKEN.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appDeployCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("status <instanceId>").description("Show one instance: status, resources, public URL").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appStatusCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("destroy <instanceId>").description("Stop + remove an app instance (interactive confirm unless --yes)").option("-y, --yes","Skip the confirmation prompt").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appDestroyCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("upgrade <instanceId>").description("Roll the agent-ops container image without destroying the instance (EFS data preserved)").option("--version <tag>","Pin to a specific agent-ops version (e.g. 0.1.16). Defaults to whatever AppsFleet base task def says.").option("-y, --yes","Skip the confirmation prompt").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appUpgradeCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("update-credential <instanceId>").description("Rotate the per-instance Claude credential to whatever's currently in your workspace-credentials. EFS preserved; task restarts ~30s.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appUpdateCredentialCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("set-auth <instanceId>").description("Enable, rotate, or disable the optional Caddy auth sidecar on a running instance. Use --auth-type basic / token / none, or --off to disable. PATCH semantics: omitted flags preserve current state, so e.g. `zibby app set-auth <id> --auth-password new` rotates JUST the password on a basic-auth instance.").option("--auth-type <kind>",'"basic" | "token" | "none". Omit to keep current type (e.g. just rotate the password).').option("--auth-user <name>","Username for basic auth. Required when switching TO basic; preserved on subsequent rotations.").option("--auth-password <pass>","SENSITIVE: Password for basic auth. 8-256 chars; bcrypt-hashed server-side. Env equivalent: ZIBBY_APP_AUTH_PASSWORD.").option("--auth-token <tok>","Optional bearer token for token auth. Omit to let the backend regenerate a fresh 32-byte token (returned ONCE \u2014 save it). Env equivalent: ZIBBY_APP_AUTH_TOKEN.").option("--off","Disable the auth sidecar entirely (alias for --auth-type none). Caddy container removed; public URL exposes the app port directly again.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appSetAuthCommand:t}=await import("../commands/app.js");return t(e,o)});const l=i.command("auth").description("Manage access control on a running app instance: credential auth (basic / token / none) and/or an IP allowlist. `auth show|basic|token|clear|ip <instanceId>`.");l.command("show <instanceId>").description("Show the current access-control gate (credential auth type + IP allowlist).").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appAuthShowCommand:t}=await import("../commands/app-auth.js");return t(e,o)}),l.command("basic <instanceId>").description("Enable / rotate HTTP basic auth (username + password). Adds a Caddy sidecar that gates the public URL. Task restarts ~1 min.").requiredOption("--user <name>","Username (1-64 printable ASCII, no spaces)").option("--password <pass>","SENSITIVE: password (8-256 chars). Env equivalent: ZIBBY_APP_AUTH_PASSWORD.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appAuthBasicCommand:t}=await import("../commands/app-auth.js");return t(e,o)}),l.command("token <instanceId>").description("Enable / rotate bearer-token auth. Omit --token to let the backend auto-generate one (printed ONCE \u2014 save it). Task restarts ~1 min.").option("--token <tok>","Optional explicit token (16-128 chars, base64url [A-Za-z0-9_-]). Omit to auto-generate. Env equivalent: ZIBBY_APP_AUTH_TOKEN.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appAuthTokenCommand:t}=await import("../commands/app-auth.js");return t(e,o)}),l.command("clear <instanceId>").description("Disable credential auth (authType none). The Caddy credential check is removed; any IP allowlist is left intact (clear it with `auth ip --clear-ip`).").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appAuthClearCommand:t}=await import("../commands/app-auth.js");return t(e,o)}),l.command("ip <instanceId>").description("Manage the IP allowlist (independent of credential auth). Only the listed source IPs/CIDRs may reach the app; all others get 403. SECURITY: enforced behind the ALB via X-Forwarded-For \u2014 verify it works on your instance before relying on it.").option("--allow <cidr...>","One or more IPs/CIDRs to allow (e.g. --allow 203.0.113.5/32 198.51.100.0/24). Replaces the current allowlist.").option("--clear-ip","Remove the IP allowlist entirely (all source IPs allowed again). Credential auth is left untouched.").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appAuthIpCommand:t}=await import("../commands/app-auth.js");return t(e,o)}),i.command("logs <instanceId>").description("Show recent logs from an app instance (use -t to tail; polls every 3s)").option("-t, --follow","Tail mode \u2014 poll every 3s and print new lines as they arrive (Ctrl+C to stop)").option("--lines <n>","Max lines per fetch (default 200, max 5000)").option("--service <name>","For multi-container apps: limit logs to one service (e.g. `db`, `web`, `agent-ops`). Defaults to interleaved across all containers.").option("--json","Print raw JSON lines (one per line) instead of parsed summary").option("--verbose","Print the full line including JSON body (default: parsed `<time> <msg>` summary)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appLogsCommand:t}=await import("../commands/app.js");return t(e,o)}),i.command("run [cmd...]").description("Run a one-off command on a linked solo app (e.g. `zibby app run rails db:migrate`). Attaches your TTY via SSM \u2014 no AWS creds needed.").option("--app <slug>","App slug (defaults to the nearest .zibby/app.json)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appRunCommand:t}=await import("../commands/app-run.js");return t(e,o)}),i.command("console").description("Open the framework REPL on a linked solo app (rails console, python manage.py shell, node, iex -S mix)").option("--app <slug>","App slug (defaults to the nearest .zibby/app.json)").option("--framework <name>","Override the framework from the link file (rails | django | python | node | elixir)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async e=>{const{appConsoleCommand:o}=await import("../commands/app-run.js");return o(e)}),i.command("migrate").description("Run database migrations on a linked solo app (rails db:migrate / python manage.py migrate)").option("--app <slug>","App slug (defaults to the nearest .zibby/app.json)").option("--framework <name>","Override the framework from the link file").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async e=>{const{appMigrateCommand:o}=await import("../commands/app-run.js");return o(e)}),i.command("rollback [steps]").description("Roll back the last database migration(s) on a linked solo app (rails db:rollback STEP=<n>, default 1)").option("--app <slug>","App slug (defaults to the nearest .zibby/app.json)").option("--framework <name>","Override the framework from the link file").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appRollbackCommand:t}=await import("../commands/app-run.js");return t(e,o)}),i.command("link <slug>").description("Link the current directory to a solo app \u2014 writes .zibby/app.json (commit it so your team can `zibby app run` without --app)").option("--api-key <key>","API key (or ZIBBY_API_KEY env)").action(async(e,o)=>{const{appLinkCommand:t}=await import("../commands/app-run.js");return t(e,o)}),n.command("uninstall").description("Remove all Zibby data: global CLI, ~/.zibby, Cursor MCP config, Studio, and current project").option("--dry-run","Show what would be deleted without deleting").option("--deep","Also remove npx cache dirs containing zibby").action(async e=>{const{uninstallCommand:o}=await import("../commands/uninstall.js");await o(e),process.exit(0)}),n.parse();
@@ -113,7 +113,7 @@ Run this to activate in current session:`)),console.log(i.gray(` source ${l}
113
113
  Zibby Test Automation
114
114
  `:`
115
115
  Zibby Project Init
116
- `);let s=!o.skipMemory,r=["dolt","mem0"].includes(String(o.memoryBackend||"").toLowerCase())?String(o.memoryBackend).toLowerCase():"dolt",a=o.infer===!0;await Qt();let c=e?Pe(process.cwd(),e):process.cwd(),m=e||"zibby-tests",p=!!e;p&&b(c)&&(console.log(i.red(`
116
+ `);let s=!o.skipMemory,r=["dolt","mem0"].includes(String(o.memoryBackend||"").toLowerCase())?String(o.memoryBackend).toLowerCase():"mem0",a=o.infer===!0;await Qt();let c=e?Pe(process.cwd(),e):process.cwd(),m=e||"zibby-tests",p=!!e;p&&b(c)&&(console.log(i.red(`
117
117
  Directory "${e}" already exists!
118
118
  `)),process.exit(1)),!p&&b(g(c,".zibby.config.mjs"))&&!o.force&&(console.log(i.yellow(`
119
119
  Zibby is already initialized in this directory!
@@ -130,7 +130,7 @@ ZIBBY_API_KEY=${f}
130
130
  # AI Agent Key
131
131
  ${_.envVar}=${f}
132
132
  `,await x(d,u)}}if(p){let d=nn(m,l,{memoryBackend:r});await x(g(c,"package.json"),d)}if(!b(g(c,".gitignore"))){let d=rn();await x(g(c,".gitignore"),d)}if(t){if(!b(g(c,"playwright.config.js"))){let d=sn("on");await x(g(c,"playwright.config.js"),d)}if(!b(g(c,"test-specs/examples/example-domain.txt"))){let d=an();await x(g(c,"test-specs/examples/example-domain.txt"),d)}}let P=Pe(zo,"../../../../examples/.zibby/commands");if(b(P)){let d=ae(P).filter(f=>f.toLowerCase().endsWith(".md"));for(let f of d){let u=g(c,".zibby/commands",f);if(o.force||!b(u)){let h=await R(g(P,f),"utf-8");await x(u,h)}}}if(!b(g(c,".zibby/commands/example.md"))){let d=ln();await x(g(c,".zibby/commands/example.md"),d)}let W=Pe(zo,"../../templates"),Z=g(W,".claude"),ee=!1,K=0,oe=0,te=0,ce=null;if(b(Z)){await M(g(c,".claude"),{recursive:!0}),await M(g(c,".claude","commands"),{recursive:!0}),await M(g(c,".claude","agents"),{recursive:!0});let d=g(Z,"CLAUDE.md"),f=g(c,".claude","CLAUDE.md");if(b(d)&&(o.force||!b(f))){let y=await R(d,"utf-8");await x(f,y),ee=!0}let u=g(Z,"commands");if(b(u)){let y=ae(u).filter(v=>v.toLowerCase().endsWith(".md"));for(let v of y){let B=g(c,".claude","commands",v);if(o.force||!b(B)){let S=await R(g(u,v),"utf-8");await x(B,S),K++}}}let h=g(Z,"agents");if(b(h)){let y=ae(h).filter(v=>v.toLowerCase().endsWith(".md"));for(let v of y){let B=g(c,".claude","agents",v);if(o.force||!b(B)){let S=await R(g(h,v),"utf-8");await x(B,S),oe++}}}}let de=g(W,".cursor","rules");if(b(de)){await M(g(c,".cursor","rules"),{recursive:!0});let d=ae(de).filter(f=>f.toLowerCase().endsWith(".mdc"));for(let f of d){let u=g(c,".cursor","rules",f);if(o.force||!b(u)){let h=await R(g(de,f),"utf-8");await x(u,h),te++}}}let $e=g(W,"AGENTS.md");if(b($e)){let{upsertManagedBlock:d}=await Promise.resolve().then(()=>(Ue(),je)),f=g(c,"AGENTS.md"),u=await R($e,"utf-8"),h=b(f)?await R(f,"utf-8"):null,{content:y,action:v}=d(h,u);v!=="skipped"&&await x(f,y),ce=v}if(ee&&console.log(i.green(" \u2713 Wrote .claude/CLAUDE.md (workflow + apps knowledge)")),K>0&&console.log(i.green(` \u2713 Wrote .claude/commands/ (${K} slash command${K===1?"":"s"})`)),oe>0&&console.log(i.green(` \u2713 Wrote .claude/agents/ (${oe} subagent definition${oe===1?"":"s"})`)),te>0&&console.log(i.green(` \u2713 Wrote .cursor/rules/ (${te} Cursor rule${te===1?"":"s"})`)),ce==="created"?console.log(i.green(" \u2713 Wrote AGENTS.md (Zibby section, managed block)")):ce==="updated"&&console.log(i.green(" \u2713 Updated AGENTS.md (Zibby section, your content preserved)")),p){let d=cn(m,l);await x(g(c,"README.md"),d)}try{let{validateMemorySyncConfig:d,applyMemorySyncConfig:f}=await Promise.resolve().then(()=>(He(),Fe)),u=g(c,".zibby.config.mjs"),h=null;if(b(u))try{h=(await import(`file://${u}?t=${Date.now()}`)).default?.memorySync}catch{}let y=d(h);if(y.ok&&y.kind!=="noop"){let v=await import("@zibby/ui-memory").catch(()=>null),{getSessionToken:B}=await Promise.resolve().then(()=>(fe(),ge)),S=await f({cwd:c,projectId:l.projectId,block:h,memoryApi:v,getSessionToken:B,hostedSetup:async({cwd:J,projectId:X})=>{let{memoryRemoteUseHostedCommand:Se}=await Promise.resolve().then(()=>(vo(),wo));await Se({cwd:J,projectId:X})},logger:{info:()=>{},warn:()=>{},error:()=>{}}});S.action==="hosted"?console.log(i.green(" \u2713 Hosted memory-sync configured from .zibby.config.mjs")):S.action==="byo"?console.log(i.green(` \u2713 Memory remote configured from .zibby.config.mjs \u2192 ${S.remote}`)):S.action==="pending-login"?(console.log(i.yellow(` \u26A0 memorySync.remote = "hosted" but you're not logged in.`)),console.log(i.gray(" Run `zibby login` then `zibby memory remote use --hosted` to finish."))):S.action==="error"&&console.log(i.yellow(` \u26A0 memorySync setup skipped: ${S.reason}`))}else y.ok||console.log(i.yellow(` \u26A0 memorySync config invalid: ${y.error}`))}catch(d){console.log(i.yellow(` \u26A0 memorySync auto-apply failed: ${d.message}`))}if(I.succeed(p?"Project created!":"Zibby initialized!"),z||(console.log(""),console.log(i.gray(" No workflow scaffolded. Add one when ready:")),console.log(i.gray(" zibby template list # see available")),console.log(i.gray(" zibby workflow new <slug> -t <template> # named, deployable copy")),console.log("")),p&&!o.skipInstall){let d=U("Installing dependencies...").start();await new Promise((f,u)=>{Q("npm",["install"],{cwd:c,stdio:"pipe"}).on("close",y=>{y===0?(d.succeed("Dependencies installed!"),f()):(d.fail("Failed to install dependencies"),u(new Error("npm install failed")))})})}if(!p&&s&&r==="mem0"&&(console.log(i.yellow(`
133
- Using mem0 backend requires mem0ai in your project dependencies.`)),console.log(i.gray("Run this manually in your project when ready:")),console.log(i.white(` npm install mem0ai
133
+ The mem0 memory backend requires two dependencies in your project.`)),console.log(i.gray("Run this in your project when ready (or switch to the self-contained dolt backend with --memory-backend dolt):")),console.log(i.white(` npm install mem0ai@npm:@zibby/mem0ai@^3.0.5 better-sqlite3@^12.6.2
134
134
  `))),!o.skipInstall&&t){let d=U("Installing Playwright browsers...").start();await new Promise(f=>{let u=Q("npx",["playwright","install","chromium"],{cwd:c,stdio:"pipe"}),h="";u.stdout.on("data",y=>{h+=y.toString()}),u.stderr.on("data",y=>{h+=y.toString()}),u.on("close",y=>{y===0?(h.includes("already installed")||h.includes("up to date")?d.succeed("Playwright browsers already installed"):d.succeed("Playwright browsers installed!"),f()):(d.warn("Could not verify Playwright browsers"),console.log(i.yellow(`
135
135
  If tests fail, run: npx playwright install
136
136
  `)),f())})})}if(l.agent==="cursor"&&!o.skipInstall){let d=U("Checking cursor-agent CLI...").start();try{le("cursor-agent --version",{encoding:"utf-8",timeout:5e3,stdio:"pipe"}),d.succeed("cursor-agent CLI already installed")}catch{d.text="Installing cursor-agent CLI...";try{await new Promise((f,u)=>{Q("bash",["-c","curl https://cursor.com/install -fsS | bash"],{stdio:"pipe"}).on("close",y=>{if(y===0){let v=g(Y(),".local","bin");process.env.PATH.includes(v)||(process.env.PATH=`${v}:${process.env.PATH}`),d.succeed("cursor-agent CLI installed!"),f()}else u(new Error("cursor-agent install failed"))})})}catch{d.fail("Could not install cursor-agent CLI"),console.log(i.yellow(` Install manually: curl https://cursor.com/install -fsS | bash
@@ -150,7 +150,7 @@ All set!
150
150
  `))):(console.log(i.cyan("Add a workflow when ready:")),console.log(i.white(` zibby template list ${i.gray("# see available")}`)),console.log(i.white(` zibby workflow new my-pipeline ${i.gray("# blank scaffold")}`)),console.log(i.white(` zibby workflow new my-pip -t <name> ${i.gray("# from a template")}
151
151
  `)),console.log(i.cyan("Cloud features (optional):")),console.log(i.white(` zibby login ${i.gray("# unlock workflow deploy, hosted memory, etc.")}`)),console.log(""))}catch(k){I.fail("Failed to create project"),console.error(i.red(`
152
152
  Error: ${k.message}
153
- `)),process.exit(1)}}function en(e,o={},t={}){let s=["dolt","mem0"].includes(String(t.memoryBackend||"").toLowerCase())?String(t.memoryBackend).toLowerCase():"dolt",r=t.memoryInfer===!0,a=e.agentAuth==="oauth"||e.agentAuth==="api"?`
153
+ `)),process.exit(1)}}function en(e,o={},t={}){let s=["dolt","mem0"].includes(String(t.memoryBackend||"").toLowerCase())?String(t.memoryBackend).toLowerCase():"mem0",r=t.memoryInfer===!0,a=e.agentAuth==="oauth"||e.agentAuth==="api"?`
154
154
  auth: '${e.agentAuth}', // 'oauth' (subscription) or 'api' (pay-per-token); cloud needs 'api'`:"",c={claude:`
155
155
  claude: {
156
156
  model: 'auto', // Options: 'auto', 'sonnet-4.6', 'opus-4.6', 'sonnet-4.5', 'opus-4.5'
@@ -261,7 +261,7 @@ ${p}
261
261
  ZIBBY_MEM0_INFER=true
262
262
  `:`# Smart memory: set true to let the LLM distill/dedupe facts on store (mem0; costs tokens). Default off = embed-only, free.
263
263
  # ZIBBY_MEM0_INFER=false
264
- `}function on(e,o="dolt",t=!1){return`# Zibby Test Automation - Environment Variables
264
+ `}function on(e,o="mem0",t=!1){return`# Zibby Test Automation - Environment Variables
265
265
 
266
266
  # AI Provider Keys
267
267
  ${{claude:"ANTHROPIC_API_KEY=sk-ant-your_key_here",cursor:`# Cursor Agent uses cursor-agent CLI \u2014 no API key needed
@@ -278,7 +278,7 @@ ${{claude:"ANTHROPIC_API_KEY=sk-ant-your_key_here",cursor:`# Cursor Agent uses c
278
278
 
279
279
  # Chat memory backend
280
280
  ZIBBY_MEMORY_BACKEND=${o}
281
- ${To(t)}`}function tn(e,o,t="dolt",s=!1){return`# Zibby Test Automation - Environment Variables
281
+ ${To(t)}`}function tn(e,o,t="mem0",s=!1){return`# Zibby Test Automation - Environment Variables
282
282
 
283
283
  # AI Provider Keys
284
284
  ${{claude:"ANTHROPIC_API_KEY=sk-ant-your_key_here",cursor:"# Cursor Agent uses cursor-agent CLI \u2014 no API key needed",codex:"OPENAI_API_KEY=sk-your_key_here",gemini:"GEMINI_API_KEY=your_key_here"}[e.agent]||""}
@@ -293,7 +293,7 @@ ZIBBY_API_KEY=${o}
293
293
 
294
294
  # Chat memory backend
295
295
  ZIBBY_MEMORY_BACKEND=${t}
296
- ${To(s)}`}function nn(e,o,t={}){let r={"@zibby/cli":"latest","@zibby/core":Xt("../../package.json").dependencies?.["@zibby/core"]||"latest"};return t.memoryBackend==="mem0"&&(r.mem0ai="^2.4.6"),JSON.stringify({name:e,version:"1.0.0",type:"module",private:!0,scripts:{"test:spec":"zibby run",test:"playwright test","test:headed":"playwright test --headed"},dependencies:r,devDependencies:{"@playwright/test":"^1.49.0",dotenv:"^17.2.3"}},null,2)}function rn(){return`# Dependencies
296
+ ${To(s)}`}function nn(e,o,t={}){let r={"@zibby/cli":"latest","@zibby/core":Xt("../../package.json").dependencies?.["@zibby/core"]||"latest"};return t.memoryBackend==="mem0"&&(r.mem0ai="npm:@zibby/mem0ai@^3.0.5",r["better-sqlite3"]="^12.6.2"),JSON.stringify({name:e,version:"1.0.0",type:"module",private:!0,scripts:{"test:spec":"zibby run",test:"playwright test","test:headed":"playwright test --headed"},dependencies:r,devDependencies:{"@playwright/test":"^1.49.0",dotenv:"^17.2.3"}},null,2)}function rn(){return`# Dependencies
297
297
  node_modules/
298
298
 
299
299
  # Test artifacts