@mediamonks/canopy-cli 0.7.45 → 0.7.46

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 (52) hide show
  1. package/dist/{ai-FBHTSCLZ.mjs → ai-CWPQiUft.mjs} +2 -2
  2. package/dist/{api-Bl6SG8Oq.mjs → api-DmJrIsE7.mjs} +134 -19
  3. package/dist/{browse-B8-0dweq.mjs → browse-BPLWhoFI.mjs} +2 -2
  4. package/dist/{db-BJJGydgL.mjs → db-DpCMc0uz.mjs} +4 -4
  5. package/dist/{deploy-ExrIeX_m.mjs → deploy-BnRQusjJ.mjs} +51 -5
  6. package/dist/{dev-D-vwE8G-.mjs → dev-BmKeIdMi.mjs} +7 -7
  7. package/dist/dev-BvVlq9np.mjs +2 -0
  8. package/dist/docs/ci.md +112 -50
  9. package/dist/docs/cli-create.md +2 -0
  10. package/dist/docs/cli-deploy.md +1 -1
  11. package/dist/docs/cli-repo.md +34 -2
  12. package/dist/docs/cli-token.md +8 -6
  13. package/dist/docs/cli.md +6 -2
  14. package/dist/docs/deploy.md +3 -2
  15. package/dist/docs/index.json +3 -3
  16. package/dist/docs/platform-deploys-and-rollbacks.md +4 -4
  17. package/dist/{docs-Cpky2XNP.mjs → docs-CtMrMpt1.mjs} +4 -4
  18. package/dist/{egress-C2amvqmE.mjs → egress-BM4EpLBh.mjs} +3 -3
  19. package/dist/{feedback-CTV6inRg.mjs → feedback-BXhbxyXI.mjs} +5 -5
  20. package/dist/index.mjs +35 -35
  21. package/dist/{local-BThs382Y.mjs → local-C9Bi9f3y.mjs} +2 -2
  22. package/dist/{login-CREcZfLH.mjs → login-2MW9sGJO.mjs} +3 -3
  23. package/dist/{logs-BnrNZvLc.mjs → logs-dZMPTJLu.mjs} +3 -3
  24. package/dist/{mcp-Cy8EwhhD.mjs → mcp-CGmWkGN8.mjs} +3 -3
  25. package/dist/{migrations-D8NqjC5I.mjs → migrations-BReMlGWP.mjs} +2 -2
  26. package/dist/{open-Bpz4C2Sr.mjs → open-DcQSdfx5.mjs} +2 -2
  27. package/dist/{package-Dph4v1Cq.mjs → package-BdNHq8QV.mjs} +1 -1
  28. package/dist/{project-template-Cdr1uwwE.mjs → project-template-BPW_Dgxj.mjs} +3 -3
  29. package/dist/project-template-Dw11151p.mjs +2 -0
  30. package/dist/{projects-BRG2HnBs.mjs → projects-CnU3194_.mjs} +26 -8
  31. package/dist/{rename-BGKa25Rq.mjs → rename-BWvERJgA.mjs} +3 -3
  32. package/dist/{repo-CwT2RDoW.mjs → repo-6a7gRQaf.mjs} +171 -8
  33. package/dist/repo-C7AXDtFZ.mjs +2 -0
  34. package/dist/{roles-C7pq9bIx.mjs → roles-CrYf_8wk.mjs} +1 -1
  35. package/dist/{roles-DAPPXf4U.mjs → roles-S2D9Id0W.mjs} +3 -3
  36. package/dist/{schedule-BcqBspn3.mjs → schedule-DvHSSzfR.mjs} +3 -3
  37. package/dist/{secrets-BjbIi7Gp.mjs → secrets-BIn2RPoe.mjs} +3 -3
  38. package/dist/{site-0i7wAJqg.mjs → site-BL5Ik-yj.mjs} +50 -1
  39. package/dist/{skill-Zj19RNo2.mjs → skill-vzcCD1b4.mjs} +2 -2
  40. package/dist/{staging-_2Js0Fkc.mjs → staging-Dn8kH9cK.mjs} +3 -3
  41. package/dist/templates/spa/.github/workflows/canopy-deploy.yml +18 -12
  42. package/dist/templates/spa/README.md +1 -1
  43. package/dist/templates/worker/.github/workflows/canopy-deploy.yml +18 -12
  44. package/dist/templates/worker/README.md +1 -1
  45. package/dist/{token-7vSNuz-X.mjs → token-DMCj88A-.mjs} +6 -6
  46. package/dist/{ui-CLnICOne.mjs → ui-26ETk1n8.mjs} +1 -1
  47. package/dist/{upgrade-B9tCAbre.mjs → upgrade-8_pFNTo5.mjs} +2 -2
  48. package/dist/{usage-DGGmTwjJ.mjs → usage-Bpz5B1N1.mjs} +3 -3
  49. package/package.json +1 -1
  50. package/dist/dev-CSimnUP3.mjs +0 -2
  51. package/dist/project-template-715H_lnu.mjs +0 -2
  52. package/dist/repo-DmFs6H9m.mjs +0 -2
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: canopy repo
3
- description: Create, clone and set up the project's git repository on Canopy.
3
+ description: Create, clone and set up the project's git repository on Canopy, or link a GitHub repository so its pushes deploy.
4
4
  ---
5
5
 
6
6
  `canopy repo` manages the project's git repository. A project has at most one: a
@@ -16,6 +16,10 @@ canopy repo create
16
16
  canopy repo clone <slug> [folder]
17
17
  canopy repo connect
18
18
  canopy repo delete [--yes]
19
+ canopy repo link [<host>/<owner/name>] [--ref <branch>] [--staging-ref <branch>]
20
+ canopy repo branches [--ref <branch>] [--staging-ref <branch>|none]
21
+ canopy repo deploys on|off
22
+ canopy repo unlink
19
23
  ```
20
24
 
21
25
  ## Arguments & flags
@@ -41,6 +45,25 @@ the global `--profile <site>` / `CANOPY_PROFILE`.
41
45
  type the slug.
42
46
  - `--yes` — skip that question.
43
47
 
48
+ These set up [CI deploys](https://docs.canopy.website/guides/ci) from GitHub Actions. All of them are
49
+ owner only (or a platform admin):
50
+
51
+ - `link [<host>/<owner/name>]` — link a GitHub repository outside Canopy, so a
52
+ push to its live branch deploys the project. With no argument it links the
53
+ folder's `origin` remote. The host is github.com or this site's GitHub
54
+ Enterprise (`monks.ghe.com`), which is the default.
55
+ - `--ref <branch>` — the live branch (default `main`).
56
+ - `--staging-ref <branch>` — a staging branch, whose pushes deploy to the
57
+ staging channel only.
58
+ - `branches` — change the live or staging branch, for a linked repository or a
59
+ Canopy one. `--staging-ref none` removes the staging branch.
60
+ - `deploys on|off` — turn CI deploys on or off without unlinking. Off makes
61
+ runs skip the deploy with a warning. Deploy tokens are not affected.
62
+ - `unlink` — remove the link.
63
+
64
+ `show` also prints the repository CI deploys from, both branches and whether
65
+ CI deploys are on.
66
+
44
67
  ## How it works
45
68
 
46
69
  Setting up a folder (`create`, `clone`, `connect`) does two things:
@@ -54,7 +77,9 @@ for a short-lived token that only works for this repository, keeps it in
54
77
  `~/.canopy` for up to an hour, and gets a new one when needed. `canopy logout`
55
78
  throws them away.
56
79
 
57
- Pushing doesn't deploy. Run `canopy deploy` for that.
80
+ Pushing doesn't deploy by itself. Run `canopy deploy`, or set up
81
+ [CI deploys](https://docs.canopy.website/guides/ci): a Canopy repository needs no link, but GitHub Actions
82
+ are off on it until a platform administrator turns them on.
58
83
 
59
84
  ## Examples
60
85
 
@@ -84,4 +109,11 @@ canopy repo show --json
84
109
  }
85
110
  ```
86
111
 
112
+ ```bash
113
+ canopy repo link --staging-ref develop
114
+ ```
115
+
116
+ Links the GitHub repository this folder's `origin` points at: pushes to `main`
117
+ deploy live, pushes to `develop` deploy to staging.
118
+
87
119
  Read the [git guide](https://docs.canopy.website/guides/git) for the bigger picture.
@@ -3,12 +3,14 @@ title: canopy token
3
3
  description: Create, list, and revoke project-scoped deploy tokens for CI and push-to-main deploys.
4
4
  ---
5
5
 
6
- `canopy token` manages deploy tokens: standing `cnpy_` bearer credentials that can do exactly one thing — deploy one specific project. You reach for it when setting up CI (typically GitHub Actions deploying on every push to main) so the runner never needs a personal login.
6
+ `canopy token` manages deploy tokens: standing `cnpy_` bearer credentials that can do exactly one thing — deploy one specific project. You reach for it when setting up CI other than GitHub Actions, so the runner never needs a personal login.
7
+
8
+ GitHub Actions doesn't need a token: link the repository with [`canopy repo link`](https://docs.canopy.website/cli/repo) and pushes deploy with no secret. See [CI deploys](https://docs.canopy.website/guides/ci).
7
9
 
8
10
  ## Usage
9
11
 
10
12
  ```bash
11
- canopy token create --name "GitHub Actions"
13
+ canopy token create --name "Buildkite"
12
14
  canopy token list
13
15
  canopy token revoke <id>
14
16
  ```
@@ -18,7 +20,7 @@ canopy token revoke <id>
18
20
  All subcommands resolve the project the usual way — `canopy.json` in the target directory, or `--project <slug>` to override — and honor the global `--profile <site>` / `CANOPY_PROFILE` for which site the token belongs to.
19
21
 
20
22
  - `create` — mint a new deploy token for the project. Owner only: editors get a clear error and should ask the owner.
21
- - `--name <label>` — a label shown in the dashboard, e.g. `"GitHub Actions"`. Optional but recommended so you can tell tokens apart later.
23
+ - `--name <label>` — a label shown in the dashboard, e.g. `"Buildkite"`. Optional but recommended so you can tell tokens apart later.
22
24
  - `list` — show the project's deploy tokens: id, name, creation time, who created them, and when each was last used. Token values are never shown here.
23
25
  - `revoke <id>` — delete a token by its id (from `canopy token list`). Deploys using it stop working immediately.
24
26
 
@@ -28,17 +30,17 @@ All subcommands resolve the project the usual way — `canopy.json` in the targe
28
30
 
29
31
  The token belongs to the project rather than to whoever created it, so CI keeps working when that person leaves. It has no fixed expiry but stops working after 90 days without a deploy; `list` shows when each token was last used.
30
32
 
31
- To use it in CI, put the value in the `CANOPY_DEPLOY_TOKEN` environment variable — the CLI checks it before the login token, so `canopy deploy` works on a runner with no `canopy login`. For GitHub Actions, add it as the repo secret `CANOPY_DEPLOY_TOKEN` (`gh secret set CANOPY_DEPLOY_TOKEN`, or Settings → Secrets); pushes to main then deploy via the project's `canopy-deploy.yml` workflow.
33
+ To use it in CI, put the value in the `CANOPY_DEPLOY_TOKEN` environment variable — the CLI checks it first, so `canopy deploy` works on a runner with no `canopy login`. In GitHub Actions a token wins over the linked repository, and keeps working while CI deploys are switched off.
32
34
 
33
35
  If a deploy fails with a rejected token, it was likely revoked — create a fresh one here or in the dashboard (Settings → Deploy tokens) and update the secret. Losing a token is never a problem: revoke the old id and mint a new one.
34
36
 
35
37
  ## Examples
36
38
 
37
39
  ```bash
38
- canopy token create --name "GitHub Actions"
40
+ canopy token create --name "Buildkite"
39
41
  ```
40
42
 
41
- Prints a new `cnpy_` token once, with instructions for storing it as the `CANOPY_DEPLOY_TOKEN` repo secret.
43
+ Prints a new `cnpy_` token once, to store as the CI's `CANOPY_DEPLOY_TOKEN` secret.
42
44
 
43
45
  ```bash
44
46
  canopy token list --project my-app
package/dist/docs/cli.md CHANGED
@@ -63,9 +63,13 @@ has a full page per command.
63
63
  - `canopy ai models` — the AI models and `auto/*` aliases this site offers,
64
64
  with prices. Works from any directory; `--json` for agents.
65
65
 
66
- ## CI / deploy tokens
66
+ ## CI deploys
67
67
 
68
- - `canopy token create` — create a project-scoped deploy token for CI.
68
+ - `canopy repo link` — link the folder's GitHub repository (owner only): pushes
69
+ to `main` then deploy from GitHub Actions with no secret.
70
+ `--staging-ref <branch>` adds a branch that deploys to staging only.
71
+ - `canopy repo deploys on|off` — pause or resume CI deploys without unlinking.
72
+ - `canopy token create` — create a project-scoped deploy token for other CI.
69
73
  `--name "<label>"` to label it.
70
74
  - `canopy token list` — list the project's deploy tokens.
71
75
  - `canopy token revoke <id>` — revoke a token.
@@ -77,5 +77,6 @@ canopy open
77
77
 
78
78
  ## Deploying from CI
79
79
 
80
- For automated push-to-main deploys, use a deploy token instead of an interactive
81
- login — see `canopy docs ci`.
80
+ For automated push-to-main deploys from GitHub Actions, link the repository with
81
+ `canopy repo link` — no secret needed. Other CI uses a deploy token. See
82
+ `canopy docs ci`.
@@ -69,8 +69,8 @@
69
69
  },
70
70
  {
71
71
  "slug": "ci",
72
- "title": "CI and deploy tokens",
73
- "summary": "Push-to-main deploys using a project-scoped deploy token, and why we recommend deploying from your own machine instead."
72
+ "title": "CI deploys",
73
+ "summary": "Deploy on every push from GitHub Actions with no secret — link the repository once. Deploy tokens for other CI."
74
74
  },
75
75
  {
76
76
  "slug": "git",
@@ -284,7 +284,7 @@
284
284
  {
285
285
  "slug": "cli-repo",
286
286
  "title": "canopy repo",
287
- "summary": "Create, clone and set up the project's git repository on Canopy."
287
+ "summary": "Create, clone and set up the project's git repository on Canopy, or link a GitHub repository so its pushes deploy."
288
288
  },
289
289
  {
290
290
  "slug": "cli-template",
@@ -27,9 +27,9 @@ the previous version keeps serving until the new one is complete.
27
27
  [deploy guide](https://docs.canopy.website/guides/deploy) for details.
28
28
  - **From the dashboard** — on the project's Overview tab, upload a new version
29
29
  by dragging in a zip, a folder, or loose files. No command line required.
30
- - **Automatically from CI** — create a project-scoped deploy token, add it to
31
- your repository's secrets, and merging to `main` ships a new version on its
32
- own. See [CI and deploy tokens](https://docs.canopy.website/guides/ci).
30
+ - **Automatically from CI** — link the project's GitHub repository once
31
+ (`canopy repo link`), and every push to `main` ships a new version on its own,
32
+ with no secret. Other CI uses a deploy token. See [CI deploys](https://docs.canopy.website/guides/ci).
33
33
 
34
34
  The dashboard's deploy history shows every version with who published it and
35
35
  where it came from (CLI, dashboard, or CI).
@@ -90,4 +90,4 @@ Downloads are limited to the project's members; the deploy bundle is your
90
90
  source, not the public site.
91
91
 
92
92
  - [Deploying](https://docs.canopy.website/guides/deploy) — Build commands, canopy.json, and what canopy deploy does step by step.
93
- - [CI and deploy tokens](https://docs.canopy.website/guides/ci) — Ship a new version automatically on every push to main.
93
+ - [CI deploys](https://docs.canopy.website/guides/ci) — Ship a new version automatically on every push to main.
@@ -1,8 +1,8 @@
1
- import { t as version } from "./package-Dph4v1Cq.mjs";
2
- import { r as siteConfig } from "./site-0i7wAJqg.mjs";
1
+ import { t as version } from "./package-BdNHq8QV.mjs";
2
+ import { r as siteConfig } from "./site-BL5Ik-yj.mjs";
3
3
  import { i as latestKnownVersion, r as compareSemver } from "./version-check-CcsA1QjI.mjs";
4
- import { n as agentHeaders } from "./api-Bl6SG8Oq.mjs";
5
- import { r as reportErrors } from "./ui-CLnICOne.mjs";
4
+ import { n as agentHeaders } from "./api-DmJrIsE7.mjs";
5
+ import { r as reportErrors } from "./ui-26ETk1n8.mjs";
6
6
  import { defineCommand } from "citty";
7
7
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
8
8
  import { homedir } from "node:os";
@@ -1,6 +1,6 @@
1
- import { l as resolveProject, o as projectDirArgs } from "./site-0i7wAJqg.mjs";
2
- import { a as apiRequest, f as withContext } from "./api-Bl6SG8Oq.mjs";
3
- import { a as unwrap, i as requireTty, r as reportErrors, t as formatDateTime } from "./ui-CLnICOne.mjs";
1
+ import { c as projectDirArgs, d as resolveProject } from "./site-BL5Ik-yj.mjs";
2
+ import { a as apiRequest, m as withContext } from "./api-DmJrIsE7.mjs";
3
+ import { a as unwrap, i as requireTty, r as reportErrors, t as formatDateTime } from "./ui-26ETk1n8.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import * as p from "@clack/prompts";
6
6
  //#region src/egress.ts
@@ -1,7 +1,7 @@
1
- import { t as version } from "./package-Dph4v1Cq.mjs";
2
- import { f as tryReadCanopyJson, l as resolveProject, o as projectDirArgs, p as tryResolveProject, r as siteConfig } from "./site-0i7wAJqg.mjs";
3
- import { a as apiRequest, c as credentials, i as apiDownload, o as apiUpload, s as commonHeaders } from "./api-Bl6SG8Oq.mjs";
4
- import { r as reportErrors, t as formatDateTime } from "./ui-CLnICOne.mjs";
1
+ import { t as version } from "./package-BdNHq8QV.mjs";
2
+ import { c as projectDirArgs, d as resolveProject, h as tryResolveProject, m as tryReadCanopyJson, r as siteConfig } from "./site-BL5Ik-yj.mjs";
3
+ import { a as apiRequest, c as credentials, i as apiDownload, o as apiUpload, s as commonHeaders } from "./api-DmJrIsE7.mjs";
4
+ import { r as reportErrors, t as formatDateTime } from "./ui-26ETk1n8.mjs";
5
5
  import { defineCommand } from "citty";
6
6
  import { basename, extname, join } from "node:path";
7
7
  import { readFile, writeFile } from "node:fs/promises";
@@ -562,7 +562,7 @@ const watchCommand = defineCommand({
562
562
  } else tryResolveProject({});
563
563
  if (args.since && args.after) throw new Error("Pass --since or --after, not both (--after already says where to resume).");
564
564
  if (args.since && Number.isNaN(Date.parse(args.since))) throw new Error(`--since must be an ISO time such as 2026-10-23T09:00:00Z (got "${args.since}").`);
565
- const { apiUrl, token } = credentials();
565
+ const { apiUrl, token } = await credentials();
566
566
  const controller = new AbortController();
567
567
  const stop = () => controller.abort();
568
568
  process.once("SIGINT", stop);
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { t as version } from "./package-Dph4v1Cq.mjs";
3
- import { i as siteHeaderLine, n as setInvocationProfile } from "./site-0i7wAJqg.mjs";
2
+ import { t as version } from "./package-BdNHq8QV.mjs";
3
+ import { i as siteHeaderLine, n as setInvocationProfile } from "./site-BL5Ik-yj.mjs";
4
4
  import { a as notifyOfUpdate, o as runRefresh } from "./version-check-CcsA1QjI.mjs";
5
5
  import { defineCommand, runMain } from "citty";
6
6
  //#region src/index.ts
@@ -63,39 +63,39 @@ const main = defineCommand({
63
63
  description: "canopy — create and deploy vibecoded projects"
64
64
  },
65
65
  subCommands: {
66
- login: () => import("./login-CREcZfLH.mjs").then((m) => m.loginCommand),
67
- whoami: () => import("./login-CREcZfLH.mjs").then((m) => m.whoamiCommand),
68
- logout: () => import("./login-CREcZfLH.mjs").then((m) => m.logoutCommand),
69
- create: () => import("./projects-BRG2HnBs.mjs").then((m) => m.createCommand),
70
- init: () => import("./projects-BRG2HnBs.mjs").then((m) => m.initCommand),
71
- projects: () => import("./projects-BRG2HnBs.mjs").then((m) => m.projectsCommand),
72
- delete: () => import("./projects-BRG2HnBs.mjs").then((m) => m.deleteCommand),
73
- rename: () => import("./rename-BGKa25Rq.mjs").then((m) => m.renameCommand),
74
- dev: () => import("./dev-CSimnUP3.mjs").then((m) => m.devCommand),
75
- deploy: () => import("./deploy-ExrIeX_m.mjs").then((m) => m.deployCommand),
76
- promote: () => import("./deploy-ExrIeX_m.mjs").then((m) => m.promoteCommand),
77
- staging: () => import("./staging-_2Js0Fkc.mjs").then((m) => m.stagingCommand),
78
- rollback: () => import("./deploy-ExrIeX_m.mjs").then((m) => m.rollbackCommand),
79
- download: () => import("./deploy-ExrIeX_m.mjs").then((m) => m.downloadCommand),
80
- token: () => import("./token-7vSNuz-X.mjs").then((m) => m.tokenCommand),
81
- egress: () => import("./egress-C2amvqmE.mjs").then((m) => m.egressCommand),
82
- secrets: () => import("./secrets-BjbIi7Gp.mjs").then((m) => m.secretsCommand),
83
- roles: () => import("./roles-C7pq9bIx.mjs").then((m) => m.rolesCommand),
84
- members: () => import("./roles-C7pq9bIx.mjs").then((m) => m.membersCommand),
85
- schedule: () => import("./schedule-BcqBspn3.mjs").then((m) => m.scheduleCommand),
86
- feedback: () => import("./feedback-CTV6inRg.mjs").then((m) => m.feedbackCommand),
87
- db: () => import("./db-BJJGydgL.mjs").then((m) => m.dbCommand),
88
- usage: () => import("./usage-DGGmTwjJ.mjs").then((m) => m.usageCommand),
89
- ai: () => import("./ai-FBHTSCLZ.mjs").then((m) => m.aiCommand),
90
- open: () => import("./open-Bpz4C2Sr.mjs").then((m) => m.openCommand),
91
- browse: () => import("./browse-B8-0dweq.mjs").then((m) => m.browseCommand),
92
- docs: () => import("./docs-Cpky2XNP.mjs").then((m) => m.docsCommand),
93
- skill: () => import("./skill-Zj19RNo2.mjs").then((m) => m.skillCommand),
94
- upgrade: () => import("./upgrade-B9tCAbre.mjs").then((m) => m.upgradeCommand),
95
- logs: () => import("./logs-BnrNZvLc.mjs").then((m) => m.logsCommand),
96
- mcp: () => import("./mcp-Cy8EwhhD.mjs").then((m) => m.mcpCommand),
97
- repo: () => import("./repo-DmFs6H9m.mjs").then((m) => m.repoCommand),
98
- template: () => import("./project-template-715H_lnu.mjs").then((m) => m.templateCommand)
66
+ login: () => import("./login-2MW9sGJO.mjs").then((m) => m.loginCommand),
67
+ whoami: () => import("./login-2MW9sGJO.mjs").then((m) => m.whoamiCommand),
68
+ logout: () => import("./login-2MW9sGJO.mjs").then((m) => m.logoutCommand),
69
+ create: () => import("./projects-CnU3194_.mjs").then((m) => m.createCommand),
70
+ init: () => import("./projects-CnU3194_.mjs").then((m) => m.initCommand),
71
+ projects: () => import("./projects-CnU3194_.mjs").then((m) => m.projectsCommand),
72
+ delete: () => import("./projects-CnU3194_.mjs").then((m) => m.deleteCommand),
73
+ rename: () => import("./rename-BWvERJgA.mjs").then((m) => m.renameCommand),
74
+ dev: () => import("./dev-BvVlq9np.mjs").then((m) => m.devCommand),
75
+ deploy: () => import("./deploy-BnRQusjJ.mjs").then((m) => m.deployCommand),
76
+ promote: () => import("./deploy-BnRQusjJ.mjs").then((m) => m.promoteCommand),
77
+ staging: () => import("./staging-Dn8kH9cK.mjs").then((m) => m.stagingCommand),
78
+ rollback: () => import("./deploy-BnRQusjJ.mjs").then((m) => m.rollbackCommand),
79
+ download: () => import("./deploy-BnRQusjJ.mjs").then((m) => m.downloadCommand),
80
+ token: () => import("./token-DMCj88A-.mjs").then((m) => m.tokenCommand),
81
+ egress: () => import("./egress-BM4EpLBh.mjs").then((m) => m.egressCommand),
82
+ secrets: () => import("./secrets-BIn2RPoe.mjs").then((m) => m.secretsCommand),
83
+ roles: () => import("./roles-CrYf_8wk.mjs").then((m) => m.rolesCommand),
84
+ members: () => import("./roles-CrYf_8wk.mjs").then((m) => m.membersCommand),
85
+ schedule: () => import("./schedule-DvHSSzfR.mjs").then((m) => m.scheduleCommand),
86
+ feedback: () => import("./feedback-BXhbxyXI.mjs").then((m) => m.feedbackCommand),
87
+ db: () => import("./db-DpCMc0uz.mjs").then((m) => m.dbCommand),
88
+ usage: () => import("./usage-Bpz5B1N1.mjs").then((m) => m.usageCommand),
89
+ ai: () => import("./ai-CWPQiUft.mjs").then((m) => m.aiCommand),
90
+ open: () => import("./open-DcQSdfx5.mjs").then((m) => m.openCommand),
91
+ browse: () => import("./browse-BPLWhoFI.mjs").then((m) => m.browseCommand),
92
+ docs: () => import("./docs-CtMrMpt1.mjs").then((m) => m.docsCommand),
93
+ skill: () => import("./skill-vzcCD1b4.mjs").then((m) => m.skillCommand),
94
+ upgrade: () => import("./upgrade-8_pFNTo5.mjs").then((m) => m.upgradeCommand),
95
+ logs: () => import("./logs-dZMPTJLu.mjs").then((m) => m.logsCommand),
96
+ mcp: () => import("./mcp-CGmWkGN8.mjs").then((m) => m.mcpCommand),
97
+ repo: () => import("./repo-C7AXDtFZ.mjs").then((m) => m.repoCommand),
98
+ template: () => import("./project-template-Dw11151p.mjs").then((m) => m.templateCommand)
99
99
  }
100
100
  });
101
101
  const quiet = process.argv[2] === "mcp" && process.argv[3] === "serve" || process.argv[2] === "repo" && process.argv[3] === "credential";
@@ -1,6 +1,6 @@
1
- import { r as apiDataRequest } from "./api-Bl6SG8Oq.mjs";
1
+ import { r as apiDataRequest } from "./api-DmJrIsE7.mjs";
2
2
  import { a as realtimeRouter, c as META_COLUMNS, l as blobRouter, n as WORKER_ATTEST_HEADER, o as dbRouter, s as hasPrivateNames } from "./src-8vxOBOxW.mjs";
3
- import { a as rewriteApiPath } from "./dev-D-vwE8G-.mjs";
3
+ import { a as rewriteApiPath } from "./dev-BmKeIdMi.mjs";
4
4
  import { createRequire } from "node:module";
5
5
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
6
6
  import { dirname, join, relative, sep } from "node:path";
@@ -1,6 +1,6 @@
1
- import { _ as setActiveProfile, b as getBakedProfile, g as readConfigFile, h as listBakedProfiles, m as clearAllProfileTokens, r as siteConfig, v as upsertProfileAuth, x as isProfileId, y as writeConfigFile } from "./site-0i7wAJqg.mjs";
2
- import { n as agentHeaders } from "./api-Bl6SG8Oq.mjs";
3
- import { n as openBrowser, r as reportErrors } from "./ui-CLnICOne.mjs";
1
+ import { C as isProfileId, S as getBakedProfile, _ as listBakedProfiles, b as upsertProfileAuth, g as clearAllProfileTokens, r as siteConfig, v as readConfigFile, x as writeConfigFile, y as setActiveProfile } from "./site-BL5Ik-yj.mjs";
2
+ import { n as agentHeaders } from "./api-DmJrIsE7.mjs";
3
+ import { n as openBrowser, r as reportErrors } from "./ui-26ETk1n8.mjs";
4
4
  import { n as clearRepoTokenCache } from "./repo-credential-CNDRM-tG.mjs";
5
5
  import { defineCommand } from "citty";
6
6
  import { hostname } from "node:os";
@@ -1,6 +1,6 @@
1
- import { l as resolveProject, s as projectFlagArgs } from "./site-0i7wAJqg.mjs";
2
- import { a as apiRequest, f as withContext } from "./api-Bl6SG8Oq.mjs";
3
- import { r as reportErrors } from "./ui-CLnICOne.mjs";
1
+ import { d as resolveProject, l as projectFlagArgs } from "./site-BL5Ik-yj.mjs";
2
+ import { a as apiRequest, m as withContext } from "./api-DmJrIsE7.mjs";
3
+ import { r as reportErrors } from "./ui-26ETk1n8.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  //#region src/logs.ts
6
6
  /**
@@ -1,6 +1,6 @@
1
- import { t as version } from "./package-Dph4v1Cq.mjs";
2
- import { c as projectUrl, d as stagingUrl, p as tryResolveProject, r as siteConfig } from "./site-0i7wAJqg.mjs";
3
- import { a as apiRequest, d as noticeRenamesOnly, l as currentSlug, t as ApiError } from "./api-Bl6SG8Oq.mjs";
1
+ import { t as version } from "./package-BdNHq8QV.mjs";
2
+ import { h as tryResolveProject, p as stagingUrl, r as siteConfig, u as projectUrl } from "./site-BL5Ik-yj.mjs";
3
+ import { a as apiRequest, f as noticeRenamesOnly, l as currentSlug, t as ApiError } from "./api-DmJrIsE7.mjs";
4
4
  import { t as liveDevServer } from "./dev-server-file-Dk9pk4AR.mjs";
5
5
  import { defineCommand } from "citty";
6
6
  import { serveStdio } from "@modelcontextprotocol/server/stdio";
@@ -1,5 +1,5 @@
1
- import { f as tryReadCanopyJson } from "./site-0i7wAJqg.mjs";
2
- import { r as apiDataRequest } from "./api-Bl6SG8Oq.mjs";
1
+ import { m as tryReadCanopyJson } from "./site-BL5Ik-yj.mjs";
2
+ import { r as apiDataRequest } from "./api-DmJrIsE7.mjs";
3
3
  import { readFileSync, readdirSync } from "node:fs";
4
4
  import { join, resolve } from "node:path";
5
5
  //#region src/migrations.ts
@@ -1,5 +1,5 @@
1
- import { c as projectUrl, d as stagingUrl, l as resolveProject, o as projectDirArgs } from "./site-0i7wAJqg.mjs";
2
- import { n as openBrowser, r as reportErrors } from "./ui-CLnICOne.mjs";
1
+ import { c as projectDirArgs, d as resolveProject, p as stagingUrl, u as projectUrl } from "./site-BL5Ik-yj.mjs";
2
+ import { n as openBrowser, r as reportErrors } from "./ui-26ETk1n8.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  //#region src/open.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "0.7.45";
2
+ var version = "0.7.46";
3
3
  //#endregion
4
4
  export { version as t };
@@ -1,6 +1,6 @@
1
- import { l as resolveProject, o as projectDirArgs } from "./site-0i7wAJqg.mjs";
2
- import { a as apiRequest, f as withContext } from "./api-Bl6SG8Oq.mjs";
3
- import { a as unwrap, i as requireTty, r as reportErrors } from "./ui-CLnICOne.mjs";
1
+ import { c as projectDirArgs, d as resolveProject } from "./site-BL5Ik-yj.mjs";
2
+ import { a as apiRequest, m as withContext } from "./api-DmJrIsE7.mjs";
3
+ import { a as unwrap, i as requireTty, r as reportErrors } from "./ui-26ETk1n8.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import * as p from "@clack/prompts";
6
6
  /** Plain words for the API's template errors. */
@@ -0,0 +1,2 @@
1
+ import { a as templateCommand } from "./project-template-BPW_Dgxj.mjs";
2
+ export { templateCommand };
@@ -1,8 +1,8 @@
1
- import { c as projectUrl, f as tryReadCanopyJson, r as siteConfig } from "./site-0i7wAJqg.mjs";
2
- import { a as apiRequest, f as withContext } from "./api-Bl6SG8Oq.mjs";
3
- import { a as unwrap, i as requireTty, r as reportErrors } from "./ui-CLnICOne.mjs";
4
- import { i as nextSteps, n as describeCopy, r as fetchTemplate, t as TEMPLATE_FIXES } from "./project-template-Cdr1uwwE.mjs";
5
- import { i as offerRepoOnCreate, n as cloneProjectRepo } from "./repo-CwT2RDoW.mjs";
1
+ import { m as tryReadCanopyJson, r as siteConfig, u as projectUrl } from "./site-BL5Ik-yj.mjs";
2
+ import { a as apiRequest, m as withContext } from "./api-DmJrIsE7.mjs";
3
+ import { a as unwrap, i as requireTty, r as reportErrors } from "./ui-26ETk1n8.mjs";
4
+ import { i as nextSteps, n as describeCopy, r as fetchTemplate, t as TEMPLATE_FIXES } from "./project-template-BPW_Dgxj.mjs";
5
+ import { a as offerRepoOnCreate, i as githubOrigin, n as cloneProjectRepo } from "./repo-6a7gRQaf.mjs";
6
6
  import { defineCommand } from "citty";
7
7
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
8
8
  import { join, relative, resolve, sep } from "node:path";
@@ -84,6 +84,17 @@ function slugify(input) {
84
84
  function shouldScaffoldCreate(requested, cwd = process.cwd()) {
85
85
  return requested ?? !existsSync(join(cwd, "canopy.json"));
86
86
  }
87
+ /**
88
+ * The "deploy from GitHub" next step (OpenSpec platform-oauth-oidc). Never a
89
+ * link: linking turns CI deploys on, which is the owner's call. With a GitHub
90
+ * `origin` the exact command; without one the shape of it. A folder that
91
+ * pushes to a Canopy repository needs no link, so no step.
92
+ */
93
+ async function ciLinkStep(dir, canopyRemote) {
94
+ if (canopyRemote) return [];
95
+ const origin = await githubOrigin(dir);
96
+ return origin ? [`canopy repo link ${origin.host}/${origin.repository} (deploy on every push to main)`] : ["canopy repo link <owner/name> (once it's on GitHub: deploy on every push to main)"];
97
+ }
87
98
  const createCommand = defineCommand({
88
99
  meta: {
89
100
  name: "create",
@@ -186,13 +197,15 @@ const createCommand = defineCommand({
186
197
  `cd ${slug}`,
187
198
  ...template.needsInstall ? ["npm install"] : [],
188
199
  ...remote ? [`git add -A && git commit -m "Initial commit" && git push -u ${remote} main`] : [],
189
- "canopy dev (or deploy right away: canopy deploy)"
200
+ "canopy dev (or deploy right away: canopy deploy)",
201
+ ...await ciLinkStep(targetDir, remote)
190
202
  ];
191
203
  p.note(steps.join("\n"), `Scaffolded ./${slug}/ (${template.id}) — next`);
192
204
  p.outro(`Live URL (after first deploy): ${projectUrl(project.slug)}`);
193
205
  } else {
194
206
  const remote = await offerRepoOnCreate(slug, process.cwd(), args.repo);
195
207
  if (remote) p.log.info(`This folder pushes to the project's git repository as "${remote}".`);
208
+ for (const step of await ciLinkStep(process.cwd(), remote)) p.log.info(`Next: ${step}`);
196
209
  p.outro(existsSync(join(process.cwd(), "canopy.json")) ? "Registered without scaffolding — the existing canopy.json was left unchanged." : "Registered without scaffolding — add a canopy.json to deploy an existing app.");
197
210
  }
198
211
  })
@@ -319,7 +332,8 @@ const initCommand = defineCommand({
319
332
  const steps = [
320
333
  ...rel === "." ? [] : [`cd ${rel}`],
321
334
  ...template.needsInstall ? ["npm install"] : [],
322
- "canopy dev (or deploy right away: canopy deploy)"
335
+ "canopy dev (or deploy right away: canopy deploy)",
336
+ ...await ciLinkStep(targetDir, null)
323
337
  ];
324
338
  p.note(steps.join("\n"), `Scaffolded ${rel}/ (${template.id}) for ${slug} — next`);
325
339
  p.outro(`Live URL (after first deploy): ${projectUrl(slug)}`);
@@ -333,7 +347,11 @@ const initCommand = defineCommand({
333
347
  return;
334
348
  }
335
349
  writeCanopyJson(targetDir, { slug });
336
- p.note("Add \"dist\"/\"build\" to canopy.json if this app has a build step, then:\ncanopy deploy", `Linked ${rel} to ${slug}`);
350
+ p.note([
351
+ "Add \"dist\"/\"build\" to canopy.json if this app has a build step, then:",
352
+ "canopy deploy",
353
+ ...await ciLinkStep(targetDir, null)
354
+ ].join("\n"), `Linked ${rel} to ${slug}`);
337
355
  p.outro(`Live URL (after first deploy): ${projectUrl(slug)}`);
338
356
  })
339
357
  });
@@ -1,6 +1,6 @@
1
- import { c as projectUrl, l as resolveProject, o as projectDirArgs, u as rewriteCanopyJsonSlug } from "./site-0i7wAJqg.mjs";
2
- import { a as apiRequest, f as withContext } from "./api-Bl6SG8Oq.mjs";
3
- import { a as unwrap, i as requireTty, r as reportErrors } from "./ui-CLnICOne.mjs";
1
+ import { c as projectDirArgs, d as resolveProject, f as rewriteCanopyJsonSlug, u as projectUrl } from "./site-BL5Ik-yj.mjs";
2
+ import { a as apiRequest, m as withContext } from "./api-DmJrIsE7.mjs";
3
+ import { a as unwrap, i as requireTty, r as reportErrors } from "./ui-26ETk1n8.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import * as p from "@clack/prompts";
6
6
  //#region src/rename.ts