@withandeo/cli 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +28 -11
  2. package/dist/api.d.ts +21 -2
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +9 -0
  5. package/dist/api.js.map +1 -1
  6. package/dist/artifact.d.ts.map +1 -1
  7. package/dist/artifact.js +21 -0
  8. package/dist/artifact.js.map +1 -1
  9. package/dist/capability-preflight.d.ts +7 -0
  10. package/dist/capability-preflight.d.ts.map +1 -0
  11. package/dist/capability-preflight.js +48 -0
  12. package/dist/capability-preflight.js.map +1 -0
  13. package/dist/contracts.d.ts +18 -0
  14. package/dist/contracts.d.ts.map +1 -1
  15. package/dist/documentation.d.ts +13 -0
  16. package/dist/documentation.d.ts.map +1 -0
  17. package/dist/documentation.js +70 -0
  18. package/dist/documentation.js.map +1 -0
  19. package/dist/main.d.ts.map +1 -1
  20. package/dist/main.js +80 -16
  21. package/dist/main.js.map +1 -1
  22. package/package.json +1 -1
  23. package/skill/tender-accounts/SKILL.md +48 -385
  24. package/skill/tender-accounts/references/authentication.md +38 -0
  25. package/skill/tender-accounts/references/configuration-secrets.md +21 -0
  26. package/skill/tender-accounts/references/delivery.md +125 -0
  27. package/skill/tender-accounts/references/domains-auth.md +13 -0
  28. package/skill/tender-accounts/references/managed-source.md +124 -0
  29. package/skill/tender-accounts/references/observability.md +18 -0
  30. package/skill/tender-accounts/references/releases-recovery.md +16 -0
  31. package/skill/tender-accounts/references/services.md +11 -0
  32. package/skill/tender-accounts/references/storage.md +13 -0
  33. package/skill/tender-accounts/references/workflows.md +69 -0
  34. package/templates/shopify-customer-account/apps/gateway/.tender/artifacts/current/tender-accounts-build.json +99 -0
  35. package/templates/shopify-customer-account/apps/gateway/.tender/artifacts/current/worker.mjs +1785 -0
  36. package/templates/shopify-customer-account/apps/gateway/.tender/build/worker.mjs +1785 -0
  37. package/templates/shopify-customer-account/apps/gateway/scripts/pack-tender-artifact.mjs +5 -2
package/dist/main.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { fileURLToPath } from "node:url";
2
2
  import { createRequire } from "node:module";
3
- import { copyFile, lstat, mkdir, mkdtemp, readFile, readdir, realpath, rm } from "node:fs/promises";
4
- import { basename, dirname, join, relative, resolve, sep } from "node:path";
3
+ import { lstat, mkdtemp, readFile, readdir, realpath, rm } from "node:fs/promises";
4
+ import { basename, join, relative, resolve, sep } from "node:path";
5
5
  import { homedir, hostname, tmpdir } from "node:os";
6
6
  import { createHash } from "node:crypto";
7
7
  import { AgentApiClient } from "./api.js";
@@ -16,6 +16,8 @@ import { captureCommand, runProjectCommand } from "./processes.js";
16
16
  import { createDefaultProfileBindings, } from "./profile-bindings.js";
17
17
  import { initializeStarter } from "./starter.js";
18
18
  import { normalizeAndeoEnvironment } from "./andeo-environment.js";
19
+ import { DOC_TOPICS, readDocumentation, installDocumentation, installedSkillCheck } from "./documentation.js";
20
+ import { capabilityPreflight } from "./capability-preflight.js";
19
21
  const packageMetadata = createRequire(import.meta.url)("../package.json");
20
22
  if (typeof packageMetadata.version !== "string" || packageMetadata.version.length === 0) {
21
23
  throw new Error("Andeo CLI package version is missing.");
@@ -94,6 +96,18 @@ async function execute(topic, options, cwd, runtime) {
94
96
  if (topic.startsWith("workflows "))
95
97
  return { value: await workflowCommand(topic.slice(10), cwd, options, runtime) };
96
98
  switch (topic) {
99
+ case "docs": {
100
+ const name = options.positionals[0];
101
+ if (!name)
102
+ return { value: { schema: "andeo.docs/v1", version: CLI_VERSION, topics: DOC_TOPICS } };
103
+ const content = await readDocumentation(name);
104
+ return options.json ? { value: { schema: "andeo.docs/v1", version: CLI_VERSION, topic: name, content } } : { raw: content };
105
+ }
106
+ case "capabilities": {
107
+ const context = await optionalContext(cwd);
108
+ const { client, projectId } = await sourceProjectAccess(cwd, context?.link ?? null, options, runtime, false);
109
+ return { value: await client.capabilities(projectId) };
110
+ }
97
111
  case "init":
98
112
  return { value: await initializeStarter({
99
113
  cwd,
@@ -186,6 +200,32 @@ async function execute(topic, options, cwd, runtime) {
186
200
  return { value: await sourceChangeClose(cwd, options, runtime) };
187
201
  case "source connect":
188
202
  return { value: await sourceConnect(cwd, options, runtime) };
203
+ case "source policy show":
204
+ case "source policy set": {
205
+ const context = await optionalContext(cwd);
206
+ const access = await sourceProjectAccess(cwd, context?.link ?? null, options, runtime, false);
207
+ if (topic === "source policy show")
208
+ return { value: await access.client.sourcePolicy(access.projectId) };
209
+ const publication = requiredFlag(options, "publication");
210
+ if (!["preview-only", "default-branch"].includes(publication))
211
+ throw new CliError("source_publication_invalid", "Choose preview-only or default-branch.");
212
+ return { value: await access.client.sourcePolicy(access.projectId, { repositoryId: requiredFlag(options, "repository"),
213
+ expectedRevision: Number(requiredFlag(options, "expected-revision")), enabled: publication === "default-branch",
214
+ idempotencyKey: requiredFlag(options, "idempotency-key") }) };
215
+ }
216
+ case "vars list":
217
+ case "vars set":
218
+ case "vars unset": {
219
+ const context = await optionalContext(cwd);
220
+ const access = await sourceProjectAccess(cwd, context?.link ?? null, options, runtime, false);
221
+ const environment = requiredFlag(options, "environment");
222
+ if (environment !== "preview" && environment !== "production")
223
+ throw new CliError("environment_invalid", "Choose preview or production.");
224
+ const input = topic === "vars list" ? undefined : { name: requiredFlag(options, "name"),
225
+ expectedRevision: Number(requiredFlag(options, "expected-revision")),
226
+ ...(topic === "vars unset" ? { remove: true } : { value: new TextDecoder("utf8", { fatal: true }).decode(await readBoundedFile(resolve(cwd, requiredFlag(options, "file")), 4096)) }) };
227
+ return { value: await access.client.runtimeVars(access.projectId, environment, input) };
228
+ }
189
229
  case "source pull":
190
230
  return { value: await sourcePull(cwd, options, runtime) };
191
231
  case "source token":
@@ -814,7 +854,7 @@ async function sourceConnect(cwd, options, runtime) {
814
854
  buildCommand: context.config.commands.package,
815
855
  workingDirectory,
816
856
  artifactLatestPath,
817
- autoPublishDefaultBranch: publication === "default-branch",
857
+ ...(options.flags.has("publication") ? { autoPublishDefaultBranch: publication === "default-branch" } : {}),
818
858
  });
819
859
  const remote = options.flags.get("remote") ?? "tender";
820
860
  await ensureGitRemote(gitRoot, remote, created.repository.remoteUrl, runtime);
@@ -1436,6 +1476,7 @@ async function linkProject(cwd, options, runtime) {
1436
1476
  }
1437
1477
  async function doctor(cwd, options, runtime) {
1438
1478
  const checks = [];
1479
+ checks.push(await installedSkillCheck(runtime.homeDirectory));
1439
1480
  const nodeMajor = Number(process.versions.node.split(".")[0]);
1440
1481
  checks.push({
1441
1482
  name: "node",
@@ -1464,6 +1505,18 @@ async function doctor(cwd, options, runtime) {
1464
1505
  checks.push(project
1465
1506
  ? { name: "project-access", status: project.role === "developer" ? "pass" : "fail", message: `${project.projectId} · ${project.role}` }
1466
1507
  : { name: "project-access", status: "fail", message: "The linked project is outside this credential's scope." });
1508
+ if (project && context.link) {
1509
+ try {
1510
+ const capabilities = await client.capabilities(context.link.projectId);
1511
+ if (capabilities.schema !== "andeo.capabilities/v1" || capabilities.projectId !== context.link.projectId) {
1512
+ throw new Error("Capability discovery unavailable; update the platform before relying on this check.");
1513
+ }
1514
+ checks.push(...await capabilityPreflight(context.root, resolveArtifactDirectory(context), capabilities, runtime.environment.WRANGLER_ENV));
1515
+ }
1516
+ catch (error) {
1517
+ checks.push({ name: "capabilities", status: "warn", message: `Capability preflight incomplete: ${normalizeError(error).message}` });
1518
+ }
1519
+ }
1467
1520
  }
1468
1521
  catch (error) {
1469
1522
  checks.push({ name: "authentication", status: "fail", message: normalizeError(error).message });
@@ -1932,13 +1985,7 @@ async function installSkill(cwd, options, runtime) {
1932
1985
  if (!base) {
1933
1986
  throw new CliError("skill_target_invalid", "--agent must be codex or claude unless --directory is provided.");
1934
1987
  }
1935
- const target = resolve(base, "andeo/SKILL.md");
1936
- if (await pathExists(target) && !options.booleans.has("force")) {
1937
- throw new CliError("skill_exists", `A Andeo skill already exists at ${target}.`, `andeo skill install --agent ${agent} --force`);
1938
- }
1939
- await mkdir(dirname(target), { recursive: true });
1940
- await copyFile(skillPath(), target);
1941
- return { status: "installed", agent, path: target };
1988
+ return { status: "installed", agent, ...await installDocumentation(base, options.booleans.has("force"), CLI_VERSION) };
1942
1989
  }
1943
1990
  async function readSkill() {
1944
1991
  return await readFile(skillPath(), "utf8");
@@ -1969,11 +2016,11 @@ function commandTopic(argv) {
1969
2016
  const topic = `preview ${argv[1]}`;
1970
2017
  return argv.includes("--help") || argv.includes("-h") ? { topic: "help", values: [topic] } : { topic, values: argv.slice(2) };
1971
2018
  }
1972
- if (parent === "auth" || parent === "delivery" || parent === "source" || parent === "skill" || parent === "config" || parent === "production" || parent === "workflows") {
2019
+ if (parent === "auth" || parent === "delivery" || parent === "source" || parent === "vars" || parent === "skill" || parent === "config" || parent === "production" || parent === "workflows") {
1973
2020
  const child = argv[1];
1974
2021
  if (!child || child.startsWith("--"))
1975
2022
  return { topic: "help", values: [parent] };
1976
- if (parent === "source" && (child === "default" || child === "history" || child === "operation" || child === "change")) {
2023
+ if (parent === "source" && (child === "default" || child === "history" || child === "operation" || child === "change" || child === "policy")) {
1977
2024
  const grandchild = argv[2];
1978
2025
  if (!grandchild || grandchild.startsWith("--"))
1979
2026
  return { topic: "help", values: [`${parent} ${child}`] };
@@ -2032,6 +2079,8 @@ function assertAllowedOptions(topic, options) {
2032
2079
  const common = ["cwd", "json"];
2033
2080
  const authentication = ["api-url", "token-stdin", "profile"];
2034
2081
  const allowed = {
2082
+ docs: common,
2083
+ capabilities: [...common, ...authentication, "project"],
2035
2084
  "workflows list": [...common, ...authentication, "project", "environment", "limit", "offset"],
2036
2085
  "workflows runs": [...common, ...authentication, "project", "scope", "limit", "offset"],
2037
2086
  "workflows status": [...common, ...authentication, "project", "scope", "run"],
@@ -2082,6 +2131,11 @@ function assertAllowedOptions(topic, options) {
2082
2131
  "production releases": [...common, ...authentication, "project"],
2083
2132
  "production rollback": [...common, ...authentication, "project", "release", "expected-release", "expected-revision", "idempotency-key"],
2084
2133
  "source branches": [...common, ...authentication, "project"],
2134
+ "source policy show": [...common, ...authentication, "project"],
2135
+ "source policy set": [...common, ...authentication, "project", "repository", "publication", "expected-revision", "idempotency-key"],
2136
+ "vars list": [...common, ...authentication, "project", "environment"],
2137
+ "vars set": [...common, ...authentication, "project", "environment", "name", "file", "expected-revision"],
2138
+ "vars unset": [...common, ...authentication, "project", "environment", "name", "expected-revision"],
2085
2139
  "source log": [...common, ...authentication, "project", "branch", "limit"],
2086
2140
  "source compare": [...common, ...authentication, "project", "base", "head"],
2087
2141
  "source default set": [
@@ -2136,6 +2190,7 @@ function assertAllowedOptions(topic, options) {
2136
2190
  throw new CliError("argument_unknown", `Option --${unexpected} is not valid for ${topic}.`, `tender-accounts ${topic} --help`);
2137
2191
  }
2138
2192
  const positionalLimits = {
2193
+ docs: { minimum: 0, maximum: 1 },
2139
2194
  "auth create": { minimum: 1, maximum: 1 },
2140
2195
  "auth delete": { minimum: 1, maximum: 1 },
2141
2196
  "auth activate": { minimum: 1, maximum: 2 },
@@ -2241,6 +2296,10 @@ Choose background preview routing with preview-service-set --target-project PROJ
2241
2296
  Only non-secret JSON belongs in workflow params/events. Keep credentials in the connected service's native secrets.
2242
2297
  Account workflow entitlement is required for new starts. Run status is authoritative; list results are a timestamped projection.`;
2243
2298
  const topics = {
2299
+ vars: "Usage: andeo vars <list|set|unset> --environment preview|production [options]\n\nManage saved non-secret runtime variables. Changes apply on the next delivery.",
2300
+ "source policy": "Usage: andeo source policy <show|set> [options]\n\nInspect or update the administrator-authorized automatic publication policy.",
2301
+ docs: "Usage: andeo docs [TOPIC] [--json]\n\nRead offline guidance bundled with this CLI. No login or checkout needed.\n\nExamples:\n andeo docs --json\n andeo docs workflows\n andeo docs configuration-secrets --json",
2302
+ capabilities: "Usage: andeo capabilities [--project PROJECT_ID] [--json]\n\nRead supported resources, account enablement/quotas and scoped permissions. Read-only and advisory; not proof of provisioning or remaining capacity. Requires the capability-discovery agent API.\n\nExamples:\n andeo capabilities --json\n andeo capabilities --project prj_... --json",
2244
2303
  init: "Usage: andeo init --name NAME [--slug SLUG] [--directory PATH] [--template shopify-customer-account] [--dry-run] [--json]\n\nCreate a new merchant-owned Shopify gateway and React portal in an empty directory.\n\nExamples:\n andeo init --name \"Acme account\" --directory ./acme-account\n andeo init --name \"Acme account\" --directory ./acme-account --dry-run --json",
2245
2304
  auth: "Usage: andeo auth <login|create|activate|deactivate|status|list|delete|logout> [options]",
2246
2305
  "auth login": "Usage: andeo auth login [--device] [--project PROJECT_ID] [--no-open] [--wait] [--force] [--json]\n\nCreate or refresh the default login. Browser-capable terminals use Authorization Code with PKCE. --device returns an agent-safe approval URL and code; add --wait to keep polling. Use auth create for named merchant profiles.",
@@ -2261,14 +2320,14 @@ Account workflow entitlement is required for new starts. Run status is authorita
2261
2320
  production: "Usage: andeo production <releases|rollback> [options]",
2262
2321
  "production releases": "Usage: andeo production releases [--project PROJECT_ID] [--json]\n\nList immutable production releases and rollback eligibility.",
2263
2322
  "production rollback": "Usage: andeo production rollback [--project PROJECT_ID] --release RELEASE_ID --expected-release CURRENT_ID --expected-revision N --idempotency-key KEY [--json]\n\nMerchant administrators restore a previously successful app release without building or uploading code.",
2264
- source: "Usage: andeo source <status|branches|log|compare|connect|pull|push|change|default|promote|history|operation> [options]\n\nUse standard Git through Andeo for a gateway or service project. Source changes never publish production directly.",
2323
+ source: "Usage: andeo source <status|branches|log|compare|connect|policy|pull|push|change|default|promote|history|operation> [options]\n\nUse standard Git through Andeo for a gateway or service project. Default-branch changes follow the saved publication policy.",
2265
2324
  "source status": "Usage: andeo source status [--project PROJECT_ID] [--json]\n\nRead the managed repository, immutable build contract, and recent source builds. --project works before a checkout is linked.\n\nExamples:\n andeo source status --project prj_... --json\n andeo source status --json",
2266
2325
  "source branches": "Usage: andeo source branches [--project PROJECT_ID] [--json]\n\nList exact branch refs and identify Andeo's authoritative default separately from the provider's create-time default. Uses a short-lived read credential without persisting it.",
2267
2326
  "source log": "Usage: andeo source log [--project PROJECT_ID] [--branch BRANCH] [--limit 20] [--json]\n\nRead bounded commit history from one exact managed branch without requiring a checkout.",
2268
2327
  "source compare": "Usage: andeo source compare [--project PROJECT_ID] --base BRANCH --head BRANCH [--json]\n\nCompare exact managed refs and report identical, fast-forward, behind, diverged, or unrelated history plus a bounded file list.",
2269
2328
  "source default": "Usage: andeo source default set --branch BRANCH --expected-current BRANCH [--dry-run] [--json]",
2270
2329
  "source default set": "Usage: andeo source default set [--project PROJECT_ID] --branch BRANCH --expected-current BRANCH [--idempotency-key KEY] [--dry-run] [--no-wait] [--json]\n\nSet an existing branch as Andeo's authoritative default with compare-and-swap. This metadata-only operation cannot change production.",
2271
- "source promote": "Usage: andeo source promote [--project PROJECT_ID] --head BRANCH [--base BRANCH] --expected-current SHA [--idempotency-key KEY] [--dry-run] [--no-wait] [--json]\n\nPromote a successfully previewed head into the current default branch using an exact expected-SHA lease. Normal preview/publication policy applies to the resulting push; protected gateways remain preview-only.",
2330
+ "source promote": "Usage: andeo source promote [--project PROJECT_ID] --head BRANCH [--base BRANCH] --expected-current SHA [--idempotency-key KEY] [--dry-run] [--no-wait] [--json]\n\nPromote a successfully previewed head into the current default branch using an exact expected-SHA lease. Normal preview/publication policy applies to the resulting push; automatic publication requires the saved opt-in policy.",
2272
2331
  "source history": "Usage: andeo source history replace --head BRANCH --expected-current SHA --confirm REPOSITORY_ID [--dry-run] [--json]",
2273
2332
  "source history replace": "Usage: andeo source history replace [--project PROJECT_ID] --head BRANCH [--target BRANCH] --expected-current SHA --confirm REPOSITORY_ID [--idempotency-key KEY] [--dry-run] [--no-wait] [--json]\n\nExceptional source migration only: archive the exact previous target, then replace it with an expected-SHA compare-and-swap. Automatic production publication is always suppressed.",
2274
2333
  "source operation": "Usage: andeo source operation <status|retry> --operation sop_... [--json]",
@@ -2279,7 +2338,12 @@ Account workflow entitlement is required for new starts. Run status is authorita
2279
2338
  "source change list": "Usage: andeo source change list [--state open|closed|all] [--json]\n\nList reviewed source changes for this exact linked project.",
2280
2339
  "source change show": "Usage: andeo source change show --change scr_... [--json]\n\nRead exact snapshot, preview, decision, and landing state.",
2281
2340
  "source change close": "Usage: andeo source change close --change scr_... [--json]\n\nClose an unlanded change without changing source or production.",
2282
- "source connect": "Usage: andeo source connect [--repo-name NAME] [--default-branch NAME] [--publication preview-only|default-branch] [--remote NAME] [--install-command COMMAND] [--working-directory PATH] [--artifact-path PATH] [--json]\n\nCreate or reconnect this linked project to Andeo-managed Git. Build and artifact commands come from tender-accounts.json. Protected gateways accept preview-only publication.",
2341
+ "source connect": "Usage: andeo source connect [--repo-name NAME] [--default-branch NAME] [--publication preview-only|default-branch] [--remote NAME] [--install-command COMMAND] [--working-directory PATH] [--artifact-path PATH] [--json]\n\nCreate or reconnect this linked project to Andeo-managed Git. Use source policy set to change an existing publication policy.",
2342
+ "source policy show": "Usage: andeo source policy show [--project PROJECT_ID] [--json]\n\nInspect the saved managed-source publication policy and revision.",
2343
+ "source policy set": "Usage: andeo source policy set [--project PROJECT_ID] --repository SRC_ID --publication preview-only|default-branch --expected-revision N --idempotency-key KEY [--json]\n\nMerchant administrators enable or disable automatic publication of future default-branch changes after successful preview and production validation. Saving a policy does not publish an existing build. Manual uploads remain explicit.",
2344
+ "vars list": "Usage: andeo vars list --environment preview|production [--project PROJECT_ID] [--json]\n\nList saved variable names and the configuration revision. Values are never returned.",
2345
+ "vars set": "Usage: andeo vars set --environment preview|production --name NAME --file PATH --expected-revision N [--project PROJECT_ID] [--json]\n\nSave a non-secret runtime variable from a UTF-8 file. Applied on the next deployment. Use existing administrator Secrets controls for credentials.",
2346
+ "vars unset": "Usage: andeo vars unset --environment preview|production --name NAME --expected-revision N [--project PROJECT_ID] [--json]\n\nRemove a variable from the next deployment's configuration.",
2283
2347
  "source pull": "Usage: andeo source pull [--project PROJECT_ID] [--remote NAME] [--dry-run] [--json]\n\nClone the exact connected Andeo-managed repository into an empty workspace, or fast-forward an existing clean matching checkout. The app is linked automatically and the short-lived Git credential is never persisted.\n\nExamples:\n andeo source pull --project prj_... --dry-run --json\n andeo source pull --project prj_... --json\n andeo source pull --json",
2284
2348
  "source token": "Usage: andeo source token [--ttl-seconds N] [--json]\n\nIssue a short-lived read-only repository credential. It is shown once and is never stored by the CLI.",
2285
2349
  "source push": "Usage: andeo source push [--branch NAME] [--remote NAME] [--no-wait] [--json]\n\nPush the exact committed revision. Reviewed repositories upload a bounded Git bundle and never expose a write credential; the default branch remains protected. Dirty working-tree changes are excluded.",
@@ -2297,7 +2361,7 @@ Account workflow entitlement is required for new starts. Run status is authorita
2297
2361
  };
2298
2362
  if (topic && topics[topic])
2299
2363
  return topics[topic];
2300
- return `Andeo merchant developer CLI ${CLI_VERSION}\n\nCommands:\n init Create a new Shopify account starter\n auth login Create or refresh the default login\n auth create Create or re-authorize a named login\n auth activate Bind a named login to a directory tree\n auth deactivate Remove an exact directory binding\n auth status Validate one login or scoped credential\n auth list List local login profiles and bindings\n auth delete Revoke one named login\n auth logout Revoke the default or every login\n link Link this checkout to one permitted project\n doctor Check developer readiness\n dev Run the project-owned local dev command\n check Run project validation\n build Package and verify a portable artifact\n upload Retain a build for administrator publication\n preview Build and deploy an exact preview\n preview entries List eligible connected entry apps\n preview open Reopen an exact deployed preview\n source status Inspect Andeo-managed Git and recent builds\n source branches List exact managed branches and default policy\n source compare Compare two managed branches\n source connect Connect this linked project to managed Git\n source pull Clone or fast-forward the exact connected repository\n source token Issue a short-lived repository credential\n source push Push the exact commit without persisting a token\n source promote Fast-forward the default after successful preview checks\n source history Run guarded, archived source-history migration\n workflows Inspect and control app-defined background runs\n tail Stream logs for one exact linked project\n delivery status Read preview workflow state\n delivery retry Retry a failed preview workflow\n skill install Install the Andeo agent skill\n config example Print the project configuration contract\n\nThere is intentionally no production publish command.\nRun andeo <command> --help for examples.`;
2364
+ return `Andeo merchant developer CLI ${CLI_VERSION}\n\nCommands:\n docs Read version-matched offline guides\n capabilities Inspect scoped support, enablement and permissions\n init Create a new Shopify account starter\n auth login Create or refresh the default login\n auth create Create or re-authorize a named login\n auth activate Bind a named login to a directory tree\n auth deactivate Remove an exact directory binding\n auth status Validate one login or scoped credential\n auth list List local login profiles and bindings\n auth delete Revoke one named login\n auth logout Revoke the default or every login\n link Link this checkout to one permitted project\n doctor Check developer readiness\n dev Run the project-owned local dev command\n check Run project validation\n build Package and verify a portable artifact\n upload Retain a build for administrator publication\n preview Build and deploy an exact preview\n preview entries List eligible connected entry apps\n preview open Reopen an exact deployed preview\n source status Inspect Andeo-managed Git and recent builds\n source branches List exact managed branches and default policy\n source compare Compare two managed branches\n source connect Connect this linked project to managed Git\n source pull Clone or fast-forward the exact connected repository\n source token Issue a short-lived repository credential\n source push Push the exact commit without persisting a token\n source promote Fast-forward the default after successful preview checks\n source history Run guarded, archived source-history migration\n workflows Inspect and control app-defined background runs\n vars Manage saved per-environment runtime variables\n source policy Inspect or change automatic publication\n tail Stream logs for one exact linked project\n delivery status Read preview workflow state\n delivery retry Retry a failed preview workflow\n skill install Install the Andeo agent skill\n config example Print the project configuration contract\n\nThere is intentionally no production publish command.\nRun andeo <command> --help for examples.`;
2301
2365
  }
2302
2366
  function normalizeError(error) {
2303
2367
  if (error instanceof CliApiError) {