@mediamonks/canopy-cli 0.7.12 → 0.7.14

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 (119) hide show
  1. package/dist/{db-8Etjmzxh.mjs → db-DKnJQPm5.mjs} +2 -2
  2. package/dist/{deploy-B1WrPq5W.mjs → deploy-CnxJ4TE6.mjs} +2 -2
  3. package/dist/dev-BqLvttKc.mjs +2 -0
  4. package/dist/{dev-BnUYGQQm.mjs → dev-CyJT6EfQ.mjs} +4 -4
  5. package/dist/docs/ci.md +50 -0
  6. package/dist/docs/cli-create.md +46 -0
  7. package/dist/docs/cli-db.md +86 -0
  8. package/dist/docs/cli-delete.md +44 -0
  9. package/dist/docs/cli-deploy.md +58 -0
  10. package/dist/docs/cli-dev.md +82 -0
  11. package/dist/docs/cli-docs.md +47 -0
  12. package/dist/docs/cli-download.md +42 -0
  13. package/dist/docs/cli-egress.md +37 -0
  14. package/dist/docs/cli-feedback.md +85 -0
  15. package/dist/docs/cli-index.md +61 -0
  16. package/dist/docs/cli-init.md +46 -0
  17. package/dist/docs/cli-login.md +43 -0
  18. package/dist/docs/cli-logout.md +32 -0
  19. package/dist/docs/cli-logs.md +57 -0
  20. package/dist/docs/cli-open.md +41 -0
  21. package/dist/docs/cli-projects.md +43 -0
  22. package/dist/docs/cli-promote.md +44 -0
  23. package/dist/docs/cli-rollback.md +45 -0
  24. package/dist/docs/cli-skill.md +39 -0
  25. package/dist/docs/cli-staging.md +54 -0
  26. package/dist/docs/cli-token.md +47 -0
  27. package/dist/docs/cli-upgrade.md +43 -0
  28. package/dist/docs/cli-usage.md +43 -0
  29. package/dist/docs/cli-whoami.md +46 -0
  30. package/dist/docs/cli.md +86 -0
  31. package/dist/docs/data.md +85 -0
  32. package/dist/docs/deploy.md +81 -0
  33. package/dist/docs/dev.md +72 -0
  34. package/dist/docs/developers-agents-and-ai.md +95 -0
  35. package/dist/docs/developers-architecture.md +106 -0
  36. package/dist/docs/getting-started.md +108 -0
  37. package/dist/docs/index.json +336 -0
  38. package/dist/docs/infrastructure.md +406 -0
  39. package/dist/docs/migrations.md +183 -0
  40. package/dist/docs/overview-faq.md +105 -0
  41. package/dist/docs/overview-how-it-works.md +82 -0
  42. package/dist/docs/overview-use-cases.md +76 -0
  43. package/dist/docs/overview-what-is-canopy.md +75 -0
  44. package/dist/docs/platform-ai-usage.md +65 -0
  45. package/dist/docs/platform-client-access.md +54 -0
  46. package/dist/docs/platform-deploys-and-rollbacks.md +93 -0
  47. package/dist/docs/platform-egress.md +75 -0
  48. package/dist/docs/platform-feedback.md +119 -0
  49. package/dist/docs/platform-google.md +213 -0
  50. package/dist/docs/platform-members-and-access.md +71 -0
  51. package/dist/docs/platform-project-data.md +76 -0
  52. package/dist/docs/platform-schedules.md +90 -0
  53. package/dist/docs/platform-sites-and-profiles.md +61 -0
  54. package/dist/docs/porting-nextjs.md +233 -0
  55. package/dist/docs/sdk-ai.md +103 -0
  56. package/dist/docs/sdk-auth.md +57 -0
  57. package/dist/docs/sdk-database.md +126 -0
  58. package/dist/docs/sdk-files.md +82 -0
  59. package/dist/docs/sdk-services.md +58 -0
  60. package/dist/docs/sdk.md +126 -0
  61. package/dist/docs/staging.md +106 -0
  62. package/dist/docs/static-serving.md +323 -0
  63. package/dist/docs/troubleshooting.md +102 -0
  64. package/dist/{docs-DxB7NhZs.mjs → docs-3pQHiuTn.mjs} +2 -2
  65. package/dist/{egress-CN_axsAN.mjs → egress-BFSwa8Uu.mjs} +1 -1
  66. package/dist/{feedback-B-GXUBPs.mjs → feedback-DReTDDzD.mjs} +26 -7
  67. package/dist/index.mjs +25 -24
  68. package/dist/{local-BGRd_FMZ.mjs → local-BQxsp-ZQ.mjs} +2 -2
  69. package/dist/{login-D7dI8D9N.mjs → login-BDTO3nVw.mjs} +1 -1
  70. package/dist/{logs-DNiZquki.mjs → logs-C53y2eAS.mjs} +1 -1
  71. package/dist/{migrations-C-5x6SYf.mjs → migrations-C6EcKD6a.mjs} +1 -1
  72. package/dist/{open-DRPp4QJg.mjs → open-C5x3tX6I.mjs} +1 -1
  73. package/dist/{package-CDLufecy.mjs → package-CuyFMXam.mjs} +1 -1
  74. package/dist/{projects-C6JQjVqg.mjs → projects-MMbv7MmK.mjs} +1 -1
  75. package/dist/schedule-Cq9K0rnE.mjs +106 -0
  76. package/dist/skill/canopy/SKILL.md +160 -0
  77. package/dist/{skill-BOWfqwr2.mjs → skill-M4RHvuUB.mjs} +2 -2
  78. package/dist/{staging-Bw1D_J8M.mjs → staging-D8G4amjO.mjs} +1 -1
  79. package/dist/templates/spa/.github/workflows/canopy-deploy.yml +34 -0
  80. package/dist/templates/spa/AGENTS.md +47 -0
  81. package/dist/templates/spa/README.md +14 -0
  82. package/dist/templates/spa/_gitignore +4 -0
  83. package/dist/templates/spa/canopy.json +5 -0
  84. package/dist/templates/spa/index.html +12 -0
  85. package/dist/templates/spa/package.json +21 -0
  86. package/dist/templates/spa/src/app.tsx +25 -0
  87. package/dist/templates/spa/src/canopy.ts +5 -0
  88. package/dist/templates/spa/src/main.tsx +10 -0
  89. package/dist/templates/spa/src/style.css +29 -0
  90. package/dist/templates/spa/tsconfig.json +16 -0
  91. package/dist/templates/spa/vite.config.ts +7 -0
  92. package/dist/templates/static/AGENTS.md +45 -0
  93. package/dist/templates/static/README.md +9 -0
  94. package/dist/templates/static/_gitignore +2 -0
  95. package/dist/templates/static/canopy.json +4 -0
  96. package/dist/templates/static/index.html +21 -0
  97. package/dist/templates/static/main.js +9 -0
  98. package/dist/templates/static/style.css +29 -0
  99. package/dist/templates/worker/.dev.vars.example +9 -0
  100. package/dist/templates/worker/.github/workflows/canopy-deploy.yml +34 -0
  101. package/dist/templates/worker/AGENTS.md +63 -0
  102. package/dist/templates/worker/README.md +17 -0
  103. package/dist/templates/worker/_gitignore +5 -0
  104. package/dist/templates/worker/canopy.json +6 -0
  105. package/dist/templates/worker/index.html +12 -0
  106. package/dist/templates/worker/package.json +22 -0
  107. package/dist/templates/worker/src/app.tsx +25 -0
  108. package/dist/templates/worker/src/canopy.ts +5 -0
  109. package/dist/templates/worker/src/main.tsx +10 -0
  110. package/dist/templates/worker/src/style.css +29 -0
  111. package/dist/templates/worker/tsconfig.json +16 -0
  112. package/dist/templates/worker/vite.config.ts +7 -0
  113. package/dist/templates/worker/worker/index.ts +52 -0
  114. package/dist/{token-D7zrIF8G.mjs → token-BUxgRJVA.mjs} +1 -1
  115. package/dist/{ui-2mrJcjYC.mjs → ui-B1Px5y7q.mjs} +17 -0
  116. package/dist/{upgrade-fhfrid_O.mjs → upgrade-C8Xox-P-.mjs} +2 -2
  117. package/dist/{usage-CX1Izj_l.mjs → usage-DjNngyvy.mjs} +1 -1
  118. package/package.json +1 -1
  119. package/dist/dev-CySBxW7I.mjs +0 -2
@@ -1,6 +1,6 @@
1
1
  import { c as resolveProject, o as projectFlagArgs } from "./site-BUlQR117.mjs";
2
- import { i as unwrap, n as reportErrors, o as apiDataRequest, r as requireTty, u as withContext } from "./ui-2mrJcjYC.mjs";
3
- import { n as migrateProject, r as readMigrationFiles, t as describeMigrateResult } from "./migrations-C-5x6SYf.mjs";
2
+ import { i as unwrap, n as reportErrors, o as apiDataRequest, r as requireTty, u as withContext } from "./ui-B1Px5y7q.mjs";
3
+ import { n as migrateProject, r as readMigrationFiles, t as describeMigrateResult } from "./migrations-C6EcKD6a.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { readFileSync, writeFileSync } from "node:fs";
6
6
  import * as p from "@clack/prompts";
@@ -1,6 +1,6 @@
1
1
  import { a as projectDirArgs, c as resolveProject, l as stagingUrl, n as siteConfig, o as projectFlagArgs, s as projectUrl, u as tryReadCanopyJson } from "./site-BUlQR117.mjs";
2
- import { c as apiRequest, i as unwrap, n as reportErrors, o as apiDataRequest, s as apiDownload, u as withContext } from "./ui-2mrJcjYC.mjs";
3
- import { n as migrateProject, r as readMigrationFiles, t as describeMigrateResult } from "./migrations-C-5x6SYf.mjs";
2
+ import { c as apiRequest, i as unwrap, n as reportErrors, o as apiDataRequest, s as apiDownload, u as withContext } from "./ui-B1Px5y7q.mjs";
3
+ import { n as migrateProject, r as readMigrationFiles, t as describeMigrateResult } from "./migrations-C6EcKD6a.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
6
6
  import { tmpdir } from "node:os";
@@ -0,0 +1,2 @@
1
+ import { t as devCommand } from "./dev-CyJT6EfQ.mjs";
2
+ export { devCommand };
@@ -1,6 +1,6 @@
1
1
  import { a as projectDirArgs, c as resolveProject, i as projectDialect, n as siteConfig, u as tryReadCanopyJson } from "./site-BUlQR117.mjs";
2
- import { a as ApiError, c as apiRequest, n as reportErrors, u as withContext } from "./ui-2mrJcjYC.mjs";
3
- import { r as readMigrationFiles } from "./migrations-C-5x6SYf.mjs";
2
+ import { a as ApiError, c as apiRequest, n as reportErrors, u as withContext } from "./ui-B1Px5y7q.mjs";
3
+ import { r as readMigrationFiles } from "./migrations-C6EcKD6a.mjs";
4
4
  import { createRequire } from "node:module";
5
5
  import { defineCommand } from "citty";
6
6
  import { existsSync } from "node:fs";
@@ -165,7 +165,7 @@ async function devRemote(flags, slug) {
165
165
  async function devLocal(flags, slug) {
166
166
  let dump;
167
167
  if (flags.pull) {
168
- const { fetchProjectDump } = await import("./local-BGRd_FMZ.mjs");
168
+ const { fetchProjectDump } = await import("./local-BQxsp-ZQ.mjs");
169
169
  console.log(`Pulling a fresh export of ${slug}${flags.staging ? " [staging]" : ""}…`);
170
170
  dump = await fetchProjectDump(slug, flags.staging ? "staging" : "live");
171
171
  }
@@ -180,7 +180,7 @@ async function devLocal(flags, slug) {
180
180
  const reason = err instanceof ApiError ? err.explain().why : String(err);
181
181
  console.log(`Note: ai/services will be unavailable — could not reach the platform (${reason}).`);
182
182
  }
183
- const { createSandbox } = await import("./local-BGRd_FMZ.mjs");
183
+ const { createSandbox } = await import("./local-BQxsp-ZQ.mjs");
184
184
  const sandbox = await createSandbox({
185
185
  slug,
186
186
  persistDir: join(flags.dir, ".canopy", "local"),
@@ -0,0 +1,50 @@
1
+ ---
2
+ title: CI and deploy tokens
3
+ description: Push-to-main deploys using a project-scoped deploy token.
4
+ ---
5
+
6
+ Interactive `canopy login` is for humans at a terminal. For automated deploys
7
+ (GitHub Actions, etc.) use a **deploy token**: a project-scoped credential that
8
+ can deploy that one project and nothing else.
9
+
10
+ ## Create a token
11
+
12
+ From inside the project directory:
13
+
14
+ ```bash
15
+ canopy token create --name "GitHub Actions"
16
+ ```
17
+
18
+ This prints the token **once** — copy it immediately and store it as a CI secret
19
+ (e.g. `CANOPY_DEPLOY_TOKEN`). It is not shown again.
20
+
21
+ Manage tokens:
22
+
23
+ ```bash
24
+ canopy token list
25
+ canopy token revoke <id>
26
+ ```
27
+
28
+ ## Use it in CI
29
+
30
+ The CLI picks up `CANOPY_DEPLOY_TOKEN` from the environment and uses it instead
31
+ of an interactive login. A minimal GitHub Actions step:
32
+
33
+ ```yaml
34
+ - run: npm install -g @mediamonks/canopy-cli
35
+ - run: canopy deploy
36
+ env:
37
+ CANOPY_DEPLOY_TOKEN: ${{ secrets.CANOPY_DEPLOY_TOKEN }}
38
+ ```
39
+
40
+ (`canopy deploy` runs the project's `canopy.json` build command by default;
41
+ pass `--no-build` if CI already built the output directory.)
42
+
43
+ No `canopy login` step is needed — the token is the credential.
44
+
45
+ ## Notes
46
+
47
+ - A deploy token can only deploy its own project — it reaches that project's
48
+ deploy endpoints and upload grants and nothing else. If it strays to another
49
+ project's resources, the platform rejects it.
50
+ - Revoke a token the moment it might be exposed; create a fresh one to replace it.
@@ -0,0 +1,46 @@
1
+ ---
2
+ title: canopy create
3
+ description: Register a new project on Canopy and scaffold it locally from a starter template.
4
+ ---
5
+
6
+ `canopy create` is the start of every new project: it registers the project on Canopy (claiming its slug and live URL) and scaffolds a runnable starter into `./<slug>/`. Everything is prompted for interactively, or passable as flags for scripted use.
7
+
8
+ ## Usage
9
+
10
+ ```bash
11
+ canopy create # fully interactive
12
+ canopy create "My Portfolio" --slug my-portfolio --template spa
13
+ canopy create existing-app --no-scaffold # register only, no files written
14
+ ```
15
+
16
+ ## Arguments & flags
17
+
18
+ - `<name>` — the project's display name. Multi-word names work unquoted (every positional joins the name). Prompted for when omitted on a TTY.
19
+ - `--slug <slug>` — the URL slug; the project will live at `https://<slug>.<site-domain>`. Lowercase letters, digits and dashes only. Defaults to a slugified version of the name (prompted on a TTY).
20
+ - `--template <id>` — starter to scaffold: `static` (plain HTML/CSS/JS, no build step, untyped SDK from the platform — simplest apps), `spa` (Vite + React + TypeScript with the typed SDK from npm — best for real SDK use or growth), or `worker` (`spa` plus a backend worker in `worker/` — for server-side code: secrets, schedules, calling external APIs). A picker appears when omitted on a TTY; `static` is the default otherwise.
21
+ - `--scaffold` / `--no-scaffold` — whether to write `./<slug>/` from the template. When neither is given, the CLI scaffolds unless the current directory already has a `canopy.json` (in which case it assumes you're registering an existing app and only registers).
22
+ - `--profile <site>` — global flag (or `CANOPY_PROFILE`): which site to create the project on. The chosen profile is pinned into the scaffolded `canopy.json`.
23
+
24
+ ## How it works
25
+
26
+ The project is registered with the platform first — this is what reserves the slug and creates the entry you'll see in `canopy projects` and the dashboard. Taken, reserved, or invalid slugs fail here with an actionable error, before anything touches disk.
27
+
28
+ With scaffolding on, the CLI then copies the template into `./<slug>/` (refusing if that directory already exists), substituting the name and slug into the files, and writes a `canopy.json` containing the slug and the profile pin. Templates ship a README, an `AGENTS.md`, and a `.gitignore`; the `spa` template also needs an `npm install` before `canopy dev`. With `--no-scaffold`, nothing is written — an existing `canopy.json` is left untouched, and you're told to add one if the directory has none.
29
+
30
+ The live URL is printed at the end, but it only serves content after your first `canopy deploy`.
31
+
32
+ ## Examples
33
+
34
+ ```bash
35
+ canopy create
36
+ ```
37
+
38
+ Walks you through name, slug, and template, registers the project, and scaffolds a ready-to-run starter with next steps printed.
39
+
40
+ ```bash
41
+ canopy create "Team Retro Board" --slug retro-board --template spa
42
+ ```
43
+
44
+ Registers `retro-board`, scaffolds a React SPA into `./retro-board/`, and tells you to `npm install` then `canopy dev`.
45
+
46
+ To set up a local folder for a project that already exists on Canopy, use [canopy init](https://docs.canopy.website/cli/init) instead. See also [canopy projects](https://docs.canopy.website/cli/projects) and [canopy delete](https://docs.canopy.website/cli/delete).
@@ -0,0 +1,86 @@
1
+ ---
2
+ title: canopy db
3
+ description: Pull, snapshot, list, restore, and migrate a project's database from the terminal.
4
+ ---
5
+
6
+ `canopy db` is the data-safety toolbox: export the project database as SQL, store restorable snapshots server-side, restore from either, and apply schema migrations. The project comes from `canopy.json` in the current directory, or from `--project <slug>` on any subcommand.
7
+
8
+ The habit that makes restores safe: **always `canopy db snapshot` before `canopy db restore`**. A restore replaces everything, and a snapshot taken seconds earlier is your undo button.
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ canopy db pull [--out <file>] [--project <slug>]
14
+ canopy db snapshot [--project <slug>]
15
+ canopy db snapshots [--project <slug>]
16
+ canopy db restore [file.sql] [--snapshot <key>] [--yes] [--project <slug>]
17
+ canopy db migrate [--plan] [--project <slug>]
18
+ ```
19
+
20
+ All subcommands accept `--project <slug>` (overrides `canopy.json` in the
21
+ current directory), and `--staging` to operate on the
22
+ [staging channel's](https://docs.canopy.website/guides/staging) database instead of live — its snapshots
23
+ live in their own history, and `db migrate --staging` is the migration
24
+ rehearsal.
25
+
26
+ ### canopy db pull
27
+
28
+ Downloads a fresh SQL dump of the project database to a local file.
29
+
30
+ - `--out <file>` — output path. Defaults to `<slug>-<timestamp>.sql` in the current directory.
31
+
32
+ The platform exports the database and hands the CLI a download URL; the CLI fetches it and writes the file, reporting its size. Use this for local inspection, ad-hoc backups, or as input to a later `db restore`.
33
+
34
+ ### canopy db snapshot
35
+
36
+ Stores a dump **server-side**, restorable anytime from the CLI or the dashboard. No flags beyond `--project`. On success it prints the snapshot key and size, plus the exact `canopy db restore --snapshot <key>` command to bring it back. Take one before every restore, schema experiment, or bulk data change.
37
+
38
+ ### canopy db snapshots
39
+
40
+ Lists stored snapshots for the project — one line per snapshot with its key, size, and creation time. If there are none yet, it points you at `canopy db snapshot`.
41
+
42
+ ### canopy db restore
43
+
44
+ Replaces **all** current project data from a snapshot or a local `.sql` file.
45
+
46
+ - `[file.sql]` — positional: a local SQL dump to restore from.
47
+ - `--snapshot <key>` — a server-side snapshot key to restore from instead.
48
+ - `--yes` — skip the confirmation (default `false`).
49
+
50
+ Behavior:
51
+
52
+ 1. With neither a file nor `--snapshot`, and on an interactive terminal, it fetches the stored snapshots and lets you pick one. On a non-TTY you must pass a source explicitly.
53
+ 2. Unless `--yes` is passed, it asks you to **type the project slug** to confirm — a deliberate speed bump, since restore is destructive. A non-TTY without `--yes` errors instead of guessing.
54
+ 3. The chosen snapshot or file replaces the entire database, and the CLI confirms `Restored <slug>.`
55
+
56
+ ### canopy db migrate
57
+
58
+ Applies pending schema migrations to the project's **live** database, without deploying. Requires a `"migrations"` directory in `canopy.json` (for example your `drizzle-kit generate` output — see the [migrations guide](https://docs.canopy.website/guides/migrations)).
59
+
60
+ - `--plan` — dry run: lists what would apply, touches nothing.
61
+
62
+ Migration files are ordered `.sql` files, applied in filename order and journaled in the database, so each file applies exactly once. The platform stores an automatic **pre-migrate snapshot** before applying anything — a botched migration is one `canopy db restore` away. Files that were already applied must not be edited afterwards (write a new migration instead); the platform refuses edited history.
63
+
64
+ Normally you won't run this yourself: `canopy deploy` applies pending migrations automatically so schema and code ship together. `canopy db migrate` exists for applying schema changes without a deploy, and for CI.
65
+
66
+ ## Examples
67
+
68
+ ```bash
69
+ canopy db snapshot && canopy db pull
70
+ ```
71
+
72
+ Belt and braces before risky work: a server-side snapshot you can restore from the dashboard, plus a local dump on disk.
73
+
74
+ ```bash
75
+ canopy db restore --snapshot snap-2026-08-11-1200 --yes --project my-app
76
+ ```
77
+
78
+ Non-interactive restore (for scripts): restores the named snapshot into `my-app` without the typed confirmation — only sensible right after taking it.
79
+
80
+ ```bash
81
+ canopy db restore seed.sql
82
+ ```
83
+
84
+ Loads a local dump — for example a seed file — after the type-the-slug confirmation.
85
+
86
+ See also the [Data guide](https://docs.canopy.website/guides/data) and [Project data](https://docs.canopy.website/platform/project-data) for how the database, snapshots, and blobs fit together.
@@ -0,0 +1,44 @@
1
+ ---
2
+ title: canopy delete
3
+ description: Permanently delete a Canopy project — its deploys, database, and files.
4
+ ---
5
+
6
+ `canopy delete` removes a project from Canopy entirely: the live site stops serving, and its deploy history, database, and stored files are torn down. It is not a pause or an archive — there is no undo, and nothing to restore from afterwards.
7
+
8
+ ## Usage
9
+
10
+ ```bash
11
+ canopy delete my-project
12
+ canopy delete my-project --yes # skip the confirmation (scripts/agents)
13
+ canopy delete # pick from a list of your projects
14
+ ```
15
+
16
+ ## Arguments & flags
17
+
18
+ - `<slug>` — the project to delete. When omitted on a TTY, you pick from a list of projects you can actually delete (deleting is owner-level: owners see their own projects, admins see all).
19
+ - `--yes` — skip the type-the-slug confirmation. Required on non-interactive runs; use with care, since it removes the last safeguard.
20
+ - `--profile <site>` — global flag (or `CANOPY_PROFILE`): sites are independent, so make sure you're deleting on the site you mean. Deleting a project on `main` does not touch a same-named project on `staging`.
21
+
22
+ ## Details
23
+
24
+ Without `--yes`, the CLI asks you to **type the slug back exactly** to confirm; anything else aborts with no changes. On a non-TTY, omitting `--yes` (or the slug) is an error rather than a hang.
25
+
26
+ Once confirmed, the platform tears the project down completely: the project itself, its deploys (so rollback targets are gone too), its database, and its uploaded files. Your local project directory is **not** touched — the code on disk survives, only the platform side is destroyed. That local copy is your only remaining artifact, so if you might want the data later, pull a database snapshot first.
27
+
28
+ Only project owners (and site admins) can delete; the platform refuses the request otherwise.
29
+
30
+ ## Examples
31
+
32
+ ```bash
33
+ canopy delete old-prototype
34
+ ```
35
+
36
+ Prompts you to type `old-prototype` to confirm, then tears the project down and prints a success line.
37
+
38
+ ```bash
39
+ canopy delete scratch-test --yes --profile staging
40
+ ```
41
+
42
+ Deletes without prompting — the pattern for cleaning up scratch projects in scripts, made explicit about which site it hits.
43
+
44
+ See also [canopy projects](https://docs.canopy.website/cli/projects) to find slugs, and [Project data](https://docs.canopy.website/platform/project-data) for what a project stores.
@@ -0,0 +1,58 @@
1
+ ---
2
+ title: canopy deploy
3
+ description: Build the project and push a new version live, from your machine or from CI.
4
+ ---
5
+
6
+ `canopy deploy` builds your project (if `canopy.json` defines a build command), uploads the output directory, and makes the new version live at the project's URL. It's the same command whether you run it by hand or from a CI runner with a deploy token.
7
+
8
+ ## Usage
9
+
10
+ ```bash
11
+ canopy deploy # build, upload, go live
12
+ canopy deploy --no-build # deploy the output directory as-is
13
+ canopy deploy --project my-app ./out
14
+ ```
15
+
16
+ ## Arguments & flags
17
+
18
+ - `[dir]` — project directory (defaults to the current directory).
19
+ - `--project <slug>` — project slug, overriding `canopy.json`. With `--project`, a `canopy.json` is optional — you can deploy any static directory; when one exists it still supplies `build` and `dist`.
20
+ - `--build` / `--no-build` — run the `canopy.json` build command first (default on). Use `--no-build` when the output is already built, e.g. a CI step that built earlier.
21
+ - `--migrate` / `--no-migrate` — apply pending schema migrations before the new version goes live (default on; only does anything when `canopy.json` configures a `"migrations"` directory — see the [migrations guide](https://docs.canopy.website/guides/migrations)).
22
+ - `--staging` — deploy to the project's [staging channel](https://docs.canopy.website/guides/staging) instead of live: created on first use with a copy of the live database, served at `staging-dot-<slug>`, promoted with [canopy promote](https://docs.canopy.website/cli/promote). Pending migrations apply to the _staging_ database (the rehearsal). Not to be confused with `--profile staging`, which picks a whole different site.
23
+ - `--profile <site>` / `CANOPY_PROFILE` — which site to deploy to (`main`, `staging`, …). Always pass it explicitly when the target matters; a `canopy.json` profile pin is the fallback.
24
+
25
+ ## How it works
26
+
27
+ 1. **Build.** If `canopy.json` has a `build` command and you didn't pass `--no-build`, it runs in the project directory with your shell; a non-zero exit aborts the deploy.
28
+ 2. **Collect files.** Everything under the `dist` directory from `canopy.json` (default: the project directory itself) is gathered, skipping `canopy.json`, `README.md`, `AGENTS.md`, `CLAUDE.md`, `.gitignore`, `.DS_Store`, and any dot-directories plus `.git`, `node_modules`, and `.claude`. An empty or missing output directory is an error.
29
+ 3. **Bundle the backend (if any).** When `canopy.json` names a `worker` entry, that backend code is bundled into a single file (dependencies included) and ships in the same version as the static files — frontend and backend always move together.
30
+ 4. **Upload.** The files upload in parallel; the new version is staged alongside the old one, so the live site keeps serving until everything has arrived.
31
+ 5. **Migrate (if configured).** With a `"migrations"` directory in `canopy.json`, pending schema migrations apply now — after the bundle is staged, before the version flips — so the incoming code never runs against the old schema. The platform stores an automatic pre-migrate snapshot first. If a migration fails, the deploy aborts and the live version is unchanged; the error names the snapshot to restore if needed.
32
+ 6. **Go live.** The platform validates the staged version and switches the site over to it in one step. The upload must contain an `index.html` at the top level — the deploy is rejected otherwise — so double-check `dist` points at the folder that actually holds `index.html`. On success the CLI prints the live URL and version number (plus the backend service URL for worker projects).
33
+
34
+ Deploys are versioned and immutable: nothing overwrites an old version, so [canopy rollback](https://docs.canopy.website/cli/rollback) can always take you back.
35
+
36
+ **CI.** Set the `CANOPY_DEPLOY_TOKEN` environment variable to a project-scoped deploy token (from [canopy token create](https://docs.canopy.website/cli/token)) and `canopy deploy` works with no `canopy login` — the token can deploy exactly one project and nothing else. Deploys from GitHub Actions are tagged with their source in the deploy history.
37
+
38
+ ## Examples
39
+
40
+ ```bash
41
+ canopy deploy
42
+ ```
43
+
44
+ From a project directory: runs the build from `canopy.json`, uploads the `dist` output, and prints the live URL with the new version number.
45
+
46
+ ```bash
47
+ canopy deploy --profile staging
48
+ ```
49
+
50
+ Same project, deployed to the staging site instead of the profile pinned in `canopy.json`.
51
+
52
+ ```bash
53
+ CANOPY_DEPLOY_TOKEN=cnpy_… canopy deploy --no-build
54
+ ```
55
+
56
+ A CI step deploying already-built output with a deploy token — no interactive login involved.
57
+
58
+ See also [canopy rollback](https://docs.canopy.website/cli/rollback), [canopy token](https://docs.canopy.website/cli/token), the [deploy guide](https://docs.canopy.website/guides/deploy), and [CI setup](https://docs.canopy.website/guides/ci).
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: canopy dev
3
+ description: Run your project locally with a Vite dev server, against live platform data or a local sandbox.
4
+ ---
5
+
6
+ `canopy dev` starts a Vite dev server for the project directory and wires up `/_api` so the SDK works exactly as it does in production. By default it's remote-first: your local pages talk to the **live** platform API and see the same data the deployed app sees. When you'd rather experiment on a disposable copy, `--local` swaps in a sandbox on your machine.
7
+
8
+ ## Usage
9
+
10
+ ```bash
11
+ canopy dev # remote-first: live project data
12
+ canopy dev --local # local sandbox: your data stays on your machine
13
+ canopy dev --local --pull # sandbox hydrated from a fresh prod export
14
+ ```
15
+
16
+ ## Arguments & flags
17
+
18
+ - `[dir]` — project directory (defaults to the current directory). Needs a `canopy.json` unless you pass `--project`.
19
+ - `--project <slug>` — project slug, overriding the `canopy.json` in the target directory.
20
+ - `--port <n>` — dev server port (Vite picks one when omitted).
21
+ - `--local` — use the local-data sandbox instead of live data. Default off.
22
+ - `--pull` — hydrate the sandbox from a fresh export of the project's production database first. Only valid with `--local`; the command errors otherwise (remote dev already sees live data).
23
+ - `--staging` — point remote dev at the [staging channel's](https://docs.canopy.website/guides/staging) data instead of live (the safe remote target while a schema is in flux), or, with `--local --pull`, hydrate the sandbox from the staging dump.
24
+ - `--profile <site>` / `CANOPY_PROFILE` — which site the dev token and API calls target. Projects usually pin a profile in `canopy.json`.
25
+
26
+ ## How it works
27
+
28
+ **Remote-first (default).** The CLI mints a short-lived, project-scoped dev token from the platform, then starts Vite with a proxy: every `/_api/*` request is forwarded to the real platform API with that token attached. The token stays inside the proxy — browser code never holds a credential. When the token expires (the expiry is printed at startup), restart `canopy dev`. Because you're on live data, the startup banner suggests `canopy db snapshot` before risky changes, or switching to `--local --pull`.
29
+
30
+ **Local sandbox (`--local`).** Database, file, and auth requests are answered entirely on your machine, from a sandbox stored under `.canopy/local/` in the project directory — no database to install, and writes never reach the platform. The sandbox behaves the same as the real API, so code that works locally works deployed. Two things still go remote: `ai` and `services` calls go through to the real platform (metered as usual) when you're logged in — fully offline, they return errors until you log in and restart.
31
+
32
+ **Matching your site's SQL dialect.** The document API (`canopy.db.collection(…)`) behaves identically everywhere, but raw `canopy.db.sql()` speaks the deployment target's dialect — SQLite on Cloudflare-backed sites, Postgres on GCP-backed ones (see [dialect()](https://docs.canopy.website/guides/data)). The sandbox defaults to Postgres. If your project uses raw SQL written for a SQLite site, lock the dialect in `canopy.json`:
33
+
34
+ ```json
35
+ { "slug": "my-project", "dialect": "sqlite" }
36
+ ```
37
+
38
+ With the lock in place, `--local` runs on an embedded SQLite engine instead — the same raw SQL, full-text search behavior, and `--pull` dumps as your deployed site. `"dialect": "postgres"` makes today's default explicit. Each engine keeps its own state under `.canopy/local/`, so switching the lock never corrupts data. The SQLite engine uses Node's built-in database and needs **Node 24+** (older Node builds lack full-text search); the CLI says so plainly if yours is older.
39
+
40
+ **Your backend worker.** If `canopy.json` names a `worker` entry (the worker scaffold does), `canopy dev` serves it too: requests to `/api/*` go to your worker, everything else to the SPA — the same split the platform makes once you deploy. There's no build step; save the file and the next request runs the new code.
41
+
42
+ Your worker gets the same `env` it gets in production: `env.CANOPY.fetch` for the SDK, `env.DB` and `env.BLOB` for raw database and file access, `env.USER` for the signed-in person, `env.PROJECT_SLUG`. They all follow the mode you're in — live project data by default, your sandbox under `--local`. Two differences worth knowing: `env.USER` is you (the account you logged in with), since there's no company login in front of a local server, and a write through `env.DB` reports no row count locally.
43
+
44
+ To tick a schedule by hand, post its name to the same path the platform uses:
45
+
46
+ ```bash
47
+ curl -X POST localhost:5173/__canopy/scheduled -d '{"name":"nightly-digest"}'
48
+ ```
49
+
50
+ **Worker secrets.** Secrets you set in the dashboard are never downloaded — the platform can't hand a stored value back, and your laptop is not where a live API key belongs. Put local values in a `.dev.vars` file next to `canopy.json` instead:
51
+
52
+ ```
53
+ STRIPE_KEY=sk_test_local
54
+ SLACK_WEBHOOK="https://hooks.slack.com/services/…"
55
+ ```
56
+
57
+ Your worker reads them exactly as it reads dashboard secrets (`c.env.STRIPE_KEY`). Keep `.dev.vars` out of git — the scaffolds already ignore it. At startup `canopy dev` lists the dashboard secret names your `.dev.vars` doesn't define, so you know what's still missing (names only, never values).
58
+
59
+ **`--pull`.** Before the sandbox boots, the CLI requests a fresh SQL export of the project's production database and applies it locally. Sync is pull-only — nothing ever pushes back. Blobs are not pulled; the local blob store starts empty.
60
+
61
+ **Schema migrations.** When `canopy.json` configures a `"migrations"` directory (see the [migrations guide](https://docs.canopy.website/guides/migrations)), the `--local` sandbox applies pending migrations on boot, so the local schema always matches the repo. Remote-first dev **never** applies migrations — it points at production, and schema changes ship with `canopy deploy`. While a schema change is in flux, work in `--local`.
62
+
63
+ A few practical notes:
64
+
65
+ - If your project ships its own Vite (the spa and worker scaffolds do), `canopy dev` uses that install and merges your `vite.config`; the `/_api` proxy always wins. The no-build static scaffold falls back to the CLI's bundled Vite.
66
+ - If the slug in `canopy.json` isn't registered on Canopy (or your account can't access it), the dev-token lookup fails with instructions to either fix the slug or create the project in the dashboard.
67
+
68
+ ## Examples
69
+
70
+ ```bash
71
+ canopy dev
72
+ ```
73
+
74
+ Serves the current directory and proxies `/_api` to the live project — good for day-to-day work where you want real data.
75
+
76
+ ```bash
77
+ canopy dev --local --pull --port 3000
78
+ ```
79
+
80
+ Pulls a fresh copy of production data into `.canopy/local/`, then serves the app on port 3000 against that copy — safe for destructive experiments.
81
+
82
+ See also [canopy deploy](https://docs.canopy.website/cli/deploy) and the [local development guide](https://docs.canopy.website/guides/dev).
@@ -0,0 +1,47 @@
1
+ ---
2
+ title: canopy docs
3
+ description: Read the Canopy docs from the terminal — live from the platform, with offline fallbacks.
4
+ ---
5
+
6
+ `canopy docs` lists and prints the full Canopy documentation in the terminal — the same content as this site, section by section: the overview, the guides, the platform pages, and the CLI and SDK references. It's built for agents and humans alike: the content is served live by the platform so it never goes stale, but the command still works offline and before you've ever signed in.
7
+
8
+ ## Usage
9
+
10
+ ```bash
11
+ canopy docs # list all topics
12
+ canopy docs <topic> # print one topic
13
+ canopy docs <topic> --refresh
14
+ ```
15
+
16
+ ## Arguments & flags
17
+
18
+ - `[topic]` — positional: the topic slug to print. Omit it to list every topic with a one-line summary, grouped by section. Guides keep bare slugs (`deploy`, `staging`); other sections prefix theirs (`sdk-database`, `cli-deploy`, `platform-schedules`).
19
+ - `--refresh` — re-fetch from the platform, bypassing the local cache. Default `false`.
20
+
21
+ ## How it works
22
+
23
+ Content resolves in a fixed fallback order:
24
+
25
+ 1. **Platform** — fetched live (topics are cached for an hour; `--refresh` forces a fetch). Requests carry your CLI token or `CANOPY_DEPLOY_TOKEN` when one exists, since platform docs require a login.
26
+ 2. **Local cache** — `~/.canopy/docs-cache/`, filled by every successful platform fetch.
27
+ 3. **Bundled snapshot** — a copy of the docs shipped inside the CLI package itself.
28
+
29
+ That last step is why `canopy docs` works with no network and no login: a fresh install always has the bundled snapshot, and it only gets fresher from there. Fetches time out after a few seconds and fall through silently, so a flaky connection degrades to slightly older docs rather than an error.
30
+
31
+ Asking for an unknown topic errors with the list of available slugs. Everything prints as plain Markdown to stdout, so it pipes cleanly into a pager or an agent's context.
32
+
33
+ ## Examples
34
+
35
+ ```bash
36
+ canopy docs
37
+ ```
38
+
39
+ Lists every topic with its summary — the starting point when you're not sure which guide covers what you're doing.
40
+
41
+ ```bash
42
+ canopy docs deploy --refresh
43
+ ```
44
+
45
+ Prints the deploy guide, guaranteed fresh from the platform rather than the hour-old cache.
46
+
47
+ See also [canopy skill](https://docs.canopy.website/cli/skill), which teaches coding agents to reach for `canopy docs` on their own.
@@ -0,0 +1,42 @@
1
+ ---
2
+ title: canopy download
3
+ description: Download the deployed files of any version of a project as a zip archive.
4
+ ---
5
+
6
+ `canopy download` fetches the exact files a deploy is serving — the live version by default, or any version from the history — and writes them to a zip on your machine. Useful for recovering a project whose source you've lost, auditing what's actually live, or diffing two versions.
7
+
8
+ ## Usage
9
+
10
+ ```bash
11
+ canopy download # the live version (or pick from history)
12
+ canopy download v3 # a specific version
13
+ canopy download --project my-app --out backup.zip
14
+ ```
15
+
16
+ ## Arguments & flags
17
+
18
+ - `[version]` — the deploy version to download, as `3` or `v3`. Optional: on an interactive terminal you get a picker over the deploy history with the live version preselected; on a non-TTY run the live version is taken automatically (an error if the project has no live version — pass one explicitly).
19
+ - `--out <file>` — output file path. Defaults to `<slug>-v<version>.zip` in the current directory.
20
+ - `--project <slug>` — project slug, overriding `canopy.json` in the target directory.
21
+ - `--dir <path>` — project directory (defaults to the current directory).
22
+ - `--profile <site>` / `CANOPY_PROFILE` — which site to download from.
23
+
24
+ ## How it works
25
+
26
+ The CLI resolves the target version (argument, picker, or live), asks the platform for that deploy's assets as a zip, and writes the archive to `--out`. The zip contains the deployed bundle as uploaded — the static files, and for worker projects the bundled `_canopy/worker.mjs`. It does not include files [canopy deploy](https://docs.canopy.website/cli/deploy) skips (like `canopy.json` itself), nor your project's database or blobs — those are handled by the data tooling, not deploy versions. A project with no deploys yet has nothing to download.
27
+
28
+ ## Examples
29
+
30
+ ```bash
31
+ canopy download
32
+ ```
33
+
34
+ From a project directory: pick a version from history (live preselected) and get e.g. `my-app-v5.zip` next to you, with the written size reported.
35
+
36
+ ```bash
37
+ canopy download v2 --project legacy-site --out /tmp/legacy-v2.zip
38
+ ```
39
+
40
+ Grabs version 2 of another project without needing its directory, writing to an explicit path — handy before comparing it against what's live now.
41
+
42
+ See also [canopy deploy](https://docs.canopy.website/cli/deploy), [canopy rollback](https://docs.canopy.website/cli/rollback), and [Deploys & rollbacks](https://docs.canopy.website/platform/deploys-and-rollbacks).
@@ -0,0 +1,37 @@
1
+ ---
2
+ title: canopy egress
3
+ description: Manage which outbound hosts the project's backend worker may fetch.
4
+ ---
5
+
6
+ `canopy egress` manages the project's outbound-host allowlist. Worker `fetch`
7
+ calls to hosts outside the list are denied (`egress_denied`) — see
8
+ [Outbound requests](https://docs.canopy.website/platform/egress).
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ canopy egress list
14
+ canopy egress allow api.example.com
15
+ canopy egress allow "*.googleapis.com"
16
+ canopy egress remove api.example.com
17
+ ```
18
+
19
+ ## Arguments & flags
20
+
21
+ All subcommands resolve the project the usual way — `canopy.json` in the
22
+ target directory, or `--project <slug>` to override — and honor the global
23
+ `--profile <site>` / `CANOPY_PROFILE`.
24
+
25
+ - `list` — print the allowed hosts, one per line.
26
+ - `allow <host>` — add a hostname (or `*.` subdomain wildcard; quote it so the
27
+ shell doesn't expand the `*`).
28
+ - `remove <host>` — remove an entry (as shown by `list`).
29
+
30
+ ## How it works
31
+
32
+ The list lives on the platform, per project, shared by the live and staging
33
+ channels — deliberately **not** in `canopy.json`, so a repo file can never
34
+ widen egress silently on deploy. Changes re-roll the running workers
35
+ immediately; no deploy is needed. Entries are validated server-side: bare
36
+ hostnames or `*.` wildcards only, no IPs, ports, schemes, or paths, at most 32
37
+ entries.
@@ -0,0 +1,85 @@
1
+ ---
2
+ title: canopy feedback
3
+ description: Read and triage a project's feedback inbox, or file a bug/feedback report — against a project or against Canopy itself.
4
+ ---
5
+
6
+ `canopy feedback` is the CLI side of [Feedback & bug reports](https://docs.canopy.website/platform/feedback):
7
+ agents (and humans) pull reports, append findings, move statuses, and file new
8
+ ones.
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ canopy feedback list --status investigate
14
+ canopy feedback show <id>
15
+ canopy feedback comment <id> "root cause: the upload grant expires too early"
16
+ canopy feedback status <id> investigated --comment "root cause: the grant expires too early"
17
+ canopy feedback list --status accepted
18
+ canopy feedback status <id> resolved --comment "fixed in v42"
19
+ canopy feedback mine
20
+ canopy feedback report "canopy deploy exits 1 after upload" --command "canopy deploy"
21
+ canopy feedback report "the header overlaps the logo" --attach ./shot.png
22
+ canopy feedback attach <id> ./after-fix.png --comment "fixed — see the shot"
23
+ ```
24
+
25
+ ## Subcommands
26
+
27
+ Inbox commands (`list`, `show`, `comment`, `status`) resolve the project the
28
+ usual way — `canopy.json` in the target directory, or `--project <slug>` — and
29
+ require project membership. `list` and `show` take `--json` for
30
+ machine-readable output.
31
+
32
+ - `list [--status <s>] [--kind <k>]` — the project's inbox. Statuses:
33
+ `investigate`, `investigated`, `accepted`, `in_progress`, `resolved`,
34
+ `declined`; kinds: `bug`, `feedback`, `docs`. (Reports filed before triage
35
+ statuses existed sit in `new`, which you can still filter for.)
36
+ - `show <id> [--download <dir>]` — full detail: body, captured context (page
37
+ URL, deploy version, console errors — or CLI context), the screenshots on
38
+ the report, and the comment trail. `--download` saves the screenshots into
39
+ a directory so you can actually look at them.
40
+ - `comment <id> <text> [--internal]` — append a comment (findings, questions,
41
+ updates). `--internal` (members only) keeps the note off the reporter's
42
+ view — for stack traces, table names, and other working detail that would
43
+ only confuse them.
44
+ - `attach <id> <file> [--attach <more>] [--caption <text>] [--comment <text>] [--internal]` —
45
+ add screenshots to an existing report. With `--comment`, the comment is
46
+ posted first and the screenshots hang off that trail entry — how you show
47
+ "here's what it looks like after the fix". `--internal` makes that comment a
48
+ members-only note, screenshots included.
49
+ - `status <id> <new-status> [--comment <note>]` — move the ticket; the
50
+ transition is recorded on the trail. Moving to `investigated` needs the
51
+ findings: pass `--comment`, or comment first.
52
+ - `mine [--project <slug>] [--json]` — your own reports across all projects,
53
+ with current statuses.
54
+ - `report <text> [--kind bug|feedback] [--project <slug>] [--command <cmd>] [--error <output>] [--attach <file>] [--caption <text>]` —
55
+ file a new report. **Without `--project` it goes to the platform inbox**
56
+ (Canopy itself) — the right target when a `canopy` command misbehaves. The
57
+ CLI attaches its version, the active site, your platform, and the project
58
+ you were working in. Reports open as `investigate`; a project member may
59
+ pass `--status` to open one further along — `investigated` when the report
60
+ itself is the write-up of what you found, `accepted` when the person you are
61
+ working with asked for it.
62
+
63
+ ## For agents
64
+
65
+ Two loops.
66
+
67
+ **Investigate:** `list --status investigate` is everything nobody has looked at
68
+ yet. Reproduce with the context in `show` (including the deploy version that
69
+ served the page), then `status <id> investigated --comment "<what you found>"`.
70
+ Stop there — say what it would take to fix and let the person decide.
71
+
72
+ Split your findings by audience: the status comment is what the **reporter**
73
+ reads, so keep it plain ("the upload fails for files over 5 MB — looking into
74
+ it"). The tech-loaded version — stack traces, table names, reproduction
75
+ queries — goes in `comment <id> "<detail>" --internal`, which only project
76
+ members see. An internal note counts as findings for `investigated`.
77
+
78
+ **Build:** `list --status accepted` is what a person has asked for. Do the
79
+ work, then `resolve` with a note, or `declined` if it turns out to be a bad
80
+ idea. Set `accepted` yourself only when the person you are working with told
81
+ you to.
82
+
83
+ When a `canopy` command itself fails: rule out user error, check
84
+ `canopy feedback mine` for a duplicate, then `report` with the exact command
85
+ and error output.