@mediamonks/canopy-cli 0.7.45 → 0.7.47

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 (55) 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/audience-B68YZBGy.mjs +121 -0
  4. package/dist/{browse-B8-0dweq.mjs → browse-BPLWhoFI.mjs} +2 -2
  5. package/dist/{db-BJJGydgL.mjs → db-DpCMc0uz.mjs} +4 -4
  6. package/dist/{deploy-ExrIeX_m.mjs → deploy-BnRQusjJ.mjs} +51 -5
  7. package/dist/{dev-D-vwE8G-.mjs → dev-BmKeIdMi.mjs} +7 -7
  8. package/dist/dev-BvVlq9np.mjs +2 -0
  9. package/dist/docs/ci.md +112 -50
  10. package/dist/docs/cli-audience.md +47 -0
  11. package/dist/docs/cli-create.md +2 -0
  12. package/dist/docs/cli-deploy.md +1 -1
  13. package/dist/docs/cli-repo.md +34 -2
  14. package/dist/docs/cli-token.md +8 -6
  15. package/dist/docs/cli.md +6 -2
  16. package/dist/docs/deploy.md +3 -2
  17. package/dist/docs/index.json +8 -3
  18. package/dist/docs/platform-deploys-and-rollbacks.md +4 -4
  19. package/dist/docs/platform-members-and-access.md +20 -0
  20. package/dist/{docs-Cpky2XNP.mjs → docs-D5gmZRJk.mjs} +4 -4
  21. package/dist/{egress-C2amvqmE.mjs → egress-BM4EpLBh.mjs} +3 -3
  22. package/dist/{feedback-CTV6inRg.mjs → feedback-C6kiYRro.mjs} +5 -5
  23. package/dist/index.mjs +36 -35
  24. package/dist/{local-BThs382Y.mjs → local-C9Bi9f3y.mjs} +2 -2
  25. package/dist/{login-CREcZfLH.mjs → login-2MW9sGJO.mjs} +3 -3
  26. package/dist/{logs-BnrNZvLc.mjs → logs-dZMPTJLu.mjs} +3 -3
  27. package/dist/{mcp-Cy8EwhhD.mjs → mcp-DuCxfb85.mjs} +3 -3
  28. package/dist/{migrations-D8NqjC5I.mjs → migrations-BReMlGWP.mjs} +2 -2
  29. package/dist/{open-Bpz4C2Sr.mjs → open-DcQSdfx5.mjs} +2 -2
  30. package/dist/{package-Dph4v1Cq.mjs → package-BksVeJZB.mjs} +1 -1
  31. package/dist/{project-template-Cdr1uwwE.mjs → project-template-BPW_Dgxj.mjs} +3 -3
  32. package/dist/project-template-Dw11151p.mjs +2 -0
  33. package/dist/{projects-BRG2HnBs.mjs → projects-CnU3194_.mjs} +26 -8
  34. package/dist/{rename-BGKa25Rq.mjs → rename-BWvERJgA.mjs} +3 -3
  35. package/dist/{repo-CwT2RDoW.mjs → repo-6a7gRQaf.mjs} +171 -8
  36. package/dist/repo-C7AXDtFZ.mjs +2 -0
  37. package/dist/{roles-C7pq9bIx.mjs → roles-CrYf_8wk.mjs} +1 -1
  38. package/dist/{roles-DAPPXf4U.mjs → roles-S2D9Id0W.mjs} +3 -3
  39. package/dist/{schedule-BcqBspn3.mjs → schedule-DvHSSzfR.mjs} +3 -3
  40. package/dist/{secrets-BjbIi7Gp.mjs → secrets-BIn2RPoe.mjs} +3 -3
  41. package/dist/{site-0i7wAJqg.mjs → site-BL5Ik-yj.mjs} +50 -1
  42. package/dist/{skill-Zj19RNo2.mjs → skill-Bz39NhTN.mjs} +2 -2
  43. package/dist/{staging-_2Js0Fkc.mjs → staging-Dn8kH9cK.mjs} +3 -3
  44. package/dist/templates/spa/.github/workflows/canopy-deploy.yml +18 -12
  45. package/dist/templates/spa/README.md +1 -1
  46. package/dist/templates/worker/.github/workflows/canopy-deploy.yml +18 -12
  47. package/dist/templates/worker/README.md +1 -1
  48. package/dist/{token-7vSNuz-X.mjs → token-DMCj88A-.mjs} +6 -6
  49. package/dist/{ui-CLnICOne.mjs → ui-26ETk1n8.mjs} +1 -1
  50. package/dist/{upgrade-B9tCAbre.mjs → upgrade-BjDaghNf.mjs} +2 -2
  51. package/dist/{usage-DGGmTwjJ.mjs → usage-Bpz5B1N1.mjs} +3 -3
  52. package/package.json +1 -1
  53. package/dist/dev-CSimnUP3.mjs +0 -2
  54. package/dist/project-template-715H_lnu.mjs +0 -2
  55. package/dist/repo-DmFs6H9m.mjs +0 -2
package/dist/docs/ci.md CHANGED
@@ -1,75 +1,137 @@
1
1
  ---
2
- title: CI and deploy tokens
3
- description: Push-to-main deploys using a project-scoped deploy token, and why we recommend deploying from your own machine instead.
2
+ title: CI deploys
3
+ description: Deploy on every push from GitHub Actions with no secret — link the repository once. Deploy tokens for other CI.
4
4
  ---
5
5
 
6
- ## Our recommendation: deploy manually
6
+ ## Link, push, done
7
+
8
+ A project can deploy itself from GitHub Actions. Link the repository once, and
9
+ every push to its main branch deploys the project. There is no secret to create,
10
+ paste or rotate: the run proves which repository and branch it comes from with
11
+ GitHub's own sign-in, and Canopy only accepts runs from the repository you
12
+ linked.
13
+
14
+ Only the project owner (or a platform admin) can link a repository. In the
15
+ project's folder:
16
+
17
+ ```bash
18
+ canopy repo link
19
+ ```
20
+
21
+ With no argument it links the repository the folder's `origin` remote points
22
+ at, on github.com or the Monks GitHub Enterprise (`monks.ghe.com`). Name it
23
+ yourself if needed:
24
+
25
+ ```bash
26
+ canopy repo link monks/my-tool # on this site's GitHub Enterprise
27
+ canopy repo link github.com/monks/my-tool # on github.com
28
+ ```
29
+
30
+ `canopy create` scaffolds `.github/workflows/canopy-deploy.yml`, which deploys
31
+ on every push to `main`. If you write your own workflow, it needs the
32
+ `id-token: write` permission and nothing else:
33
+
34
+ ```yaml
35
+ on:
36
+ push:
37
+ branches: [main]
38
+
39
+ permissions:
40
+ id-token: write
41
+ contents: read
42
+
43
+ jobs:
44
+ deploy:
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - uses: actions/checkout@v7
48
+ - uses: actions/setup-node@v7
49
+ with:
50
+ node-version: 24
51
+ - run: npm ci
52
+ - run: npm exec --yes @mediamonks/canopy-cli deploy
53
+ ```
7
54
 
8
- Most Canopy users don't have a GitHub Enterprise seat, so they can't see or
9
- interact with GitHub Actions. That is why Canopy repositories are created with
10
- Actions turned **off**: pushing a workflow file works, but nothing runs, and
11
- there is no Actions tab for you to look at. Turning Actions on for a repository
12
- is something only a GitHub administrator can do, and you would still not see
13
- the runs.
55
+ A run from any other branch, a pull request or a fork deploys nothing. Until a
56
+ repository is linked, runs skip the deploy with a warning instead of failing.
14
57
 
15
- Deploy from your machine (or let your coding agent do it): run
16
- `canopy deploy --staging`, check the result, then `canopy promote`. It is
17
- usually quicker than waiting for a pipeline, and your agent can verify the
18
- deploy right afterwards. Run your typecheck, lint and tests locally before you
19
- deploy.
58
+ Deploys from CI show up in the history under the repository and branch, e.g.
59
+ `monks/my-tool @ main`.
20
60
 
21
- The rest of this page is for teams that run their own CI somewhere they can
22
- see it.
61
+ A project with a Canopy repository needs no link: CI deploys from it already.
62
+ GitHub Actions are off on Canopy repositories until a platform administrator
63
+ turns them on for one.
64
+
65
+ ## Our recommendation: deploy manually
23
66
 
24
- Interactive `canopy login` is for humans at a terminal. For automated deploys
25
- (GitHub Actions, etc.) use a **deploy token**: a project-scoped credential that
26
- can deploy that one project and nothing else.
67
+ Most Canopy users don't have a GitHub Enterprise seat, so they can't see the
68
+ runs. Deploying from your machine (or letting your coding agent do it) is
69
+ usually quicker: run `canopy deploy --staging`, check the result, then
70
+ `canopy promote`. Run your typecheck, lint and tests locally before you deploy.
27
71
 
28
- ## Create a token
72
+ ## A staging branch
29
73
 
30
- Only the project owner can create a deploy token (any editor can list
31
- and revoke them). From inside the project directory:
74
+ Pushes to a second branch can deploy to the project's
75
+ [staging channel](https://docs.canopy.website/guides/staging) only. They can never change what is live:
76
+ no live deploy, promote or rollback.
32
77
 
33
78
  ```bash
34
- canopy token create --name "GitHub Actions"
79
+ canopy repo branches --staging-ref develop
35
80
  ```
36
81
 
37
- This prints the token **once** — copy it immediately and store it as a CI secret
38
- (e.g. `CANOPY_DEPLOY_TOKEN`). It is not shown again.
82
+ Then add the branch to the workflow's trigger so its pushes run it:
39
83
 
40
- Manage tokens:
84
+ ```yaml
85
+ on:
86
+ push:
87
+ branches: [main, develop]
88
+ ```
89
+
90
+ The same workflow deploys `main` live and `develop` to staging. Promote from
91
+ staging to live by hand with `canopy promote`.
92
+
93
+ ## Pausing CI deploys
94
+
95
+ Turn CI deploys off without unlinking or editing the workflow:
41
96
 
42
97
  ```bash
43
- canopy token list
44
- canopy token revoke <id>
98
+ canopy repo deploys off
99
+ canopy repo deploys on
45
100
  ```
46
101
 
47
- ## Use it in CI
102
+ While they are off, runs skip the deploy with a warning. The link and branches
103
+ stay as they were. You can also flip the switch on the project's Deploys tab.
48
104
 
49
- The CLI picks up `CANOPY_DEPLOY_TOKEN` from the environment and uses it instead
50
- of an interactive login. A minimal GitHub Actions step:
105
+ `canopy repo show` prints the repository, both branches and whether CI deploys
106
+ are on. `canopy repo unlink` removes the link.
51
107
 
52
- ```yaml
53
- - run: npm install -g @mediamonks/canopy-cli
54
- - run: canopy deploy
55
- env:
56
- CANOPY_DEPLOY_TOKEN: ${{ secrets.CANOPY_DEPLOY_TOKEN }}
108
+ ## Other CI: deploy tokens
109
+
110
+ For CI that isn't GitHub Actions, or a repository you can't link, use a
111
+ **deploy token**: a project-scoped credential that can deploy that one project
112
+ and nothing else.
113
+
114
+ Only the project owner can create one (any editor can list and revoke them).
115
+ From inside the project directory:
116
+
117
+ ```bash
118
+ canopy token create --name "Buildkite"
57
119
  ```
58
120
 
59
- (`canopy deploy` runs the project's `canopy.json` build command by default;
60
- pass `--no-build` if CI already built the output directory.)
121
+ This prints the token **once** — store it as a CI secret right away. It is not
122
+ shown again.
61
123
 
62
- No `canopy login` step is needed — the token is the credential.
124
+ ```bash
125
+ canopy token list
126
+ canopy token revoke <id>
127
+ ```
63
128
 
64
- ## Notes
129
+ Set it as `CANOPY_DEPLOY_TOKEN` in the CI environment and run `canopy deploy`.
130
+ No `canopy login` is needed. A deploy token also works in GitHub Actions, and
131
+ wins over the linked repository when both are there.
65
132
 
66
- - A deploy token can only deploy its own project — it reaches that project's
67
- deploy endpoints and upload grants and nothing else. If it strays to another
68
- project's resources, the platform rejects it.
69
- - The token belongs to the project, not to the person who created it. It keeps
70
- working when they leave the project or the company; deploys it makes show up
71
- in the history under the token's name.
72
- - A token that goes 90 days without a deploy stops working. Active pipelines
73
- never notice; a forgotten one dies on its own. The token list shows when each
74
- was last used.
75
- - Revoke a token the moment it might be exposed; create a fresh one to replace it.
133
+ - A deploy token can only deploy its own project.
134
+ - It belongs to the project, not to the person who created it, and keeps
135
+ working when they leave.
136
+ - A token that goes 90 days without a deploy stops working.
137
+ - Turning CI deploys off does not stop a deploy token. Revoke it for that.
@@ -0,0 +1,47 @@
1
+ ---
2
+ title: canopy audience
3
+ description: Say who a project is for and whether it's still a draft.
4
+ ---
5
+
6
+ `canopy audience` sets the labels people see on the dashboard's project list:
7
+ who the project was made for, and whether it's still a draft. They never
8
+ change who can open the project. Read
9
+ [Saying who it's for](https://docs.canopy.website/platform/members-and-access#saying-who-its-for).
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ canopy audience show
15
+ canopy audience set <everyone|personal>
16
+ canopy audience set <client|department> <name>
17
+ canopy audience draft
18
+ canopy audience ready
19
+ ```
20
+
21
+ ## Arguments & flags
22
+
23
+ Each subcommand works on the project in the current folder (`canopy.json`),
24
+ or the one you name with `--project <slug>`. All of them honour the global
25
+ `--profile <site>` / `CANOPY_PROFILE`. Owners, managers and editors can change
26
+ them.
27
+
28
+ - `show` — who the project is for, and whether it's a draft.
29
+ - `set <kind> [name]` — `everyone` (the default), `personal`, or `client` /
30
+ `department` with a name of up to 40 characters. Quote names with spaces.
31
+ - `draft` — mark it as not ready yet. It shows greyed out on the project list
32
+ but stays listed and usable.
33
+ - `ready` — it's no longer a draft.
34
+
35
+ ## Examples
36
+
37
+ ```bash
38
+ canopy audience set client "Uniqlo"
39
+ ```
40
+
41
+ Marks the project as made for the Uniqlo client team.
42
+
43
+ ```bash
44
+ canopy audience draft --project retro-board
45
+ ```
46
+
47
+ Marks `retro-board` as a draft without being in its folder.
@@ -40,6 +40,8 @@ canopy create
40
40
 
41
41
  Walks you through name, slug, and template, registers the project, and scaffolds a ready-to-run starter with next steps printed.
42
42
 
43
+ The starter includes `.github/workflows/canopy-deploy.yml`, which deploys on every push to `main` once the repository is linked. `create` never links a repository itself; the next steps print the exact [`canopy repo link`](https://docs.canopy.website/cli/repo) command for the folder's GitHub `origin`. See [CI deploys](https://docs.canopy.website/guides/ci).
44
+
43
45
  ```bash
44
46
  canopy create "Team Retro Board" --slug retro-board --template spa
45
47
  ```
@@ -33,7 +33,7 @@ canopy deploy --project my-app ./out
33
33
 
34
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
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.
36
+ **CI.** In GitHub Actions, `canopy deploy` needs no secret and no `canopy login`: with `permissions: id-token: write` in the workflow, it proves which repository and branch the run comes from and deploys a project [linked](https://docs.canopy.website/cli/repo) to that repository. A run on the project's staging branch deploys to staging without `--staging`. An unlinked project, or one whose CI deploys are off, skips the deploy with a warning instead of failing. Elsewhere, set `CANOPY_DEPLOY_TOKEN` to a project-scoped deploy token (from [canopy token create](https://docs.canopy.website/cli/token)); it wins over the linked repository when both are there. Deploys from GitHub Actions are tagged with their source in the deploy history. See [CI deploys](https://docs.canopy.website/guides/ci).
37
37
 
38
38
  ## Examples
39
39
 
@@ -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",
@@ -246,6 +246,11 @@
246
246
  "title": "canopy rename",
247
247
  "summary": "Change a project's slug — its address — and update canopy.json."
248
248
  },
249
+ {
250
+ "slug": "cli-audience",
251
+ "title": "canopy audience",
252
+ "summary": "Say who a project is for and whether it's still a draft."
253
+ },
249
254
  {
250
255
  "slug": "cli-dev",
251
256
  "title": "canopy dev",
@@ -284,7 +289,7 @@
284
289
  {
285
290
  "slug": "cli-repo",
286
291
  "title": "canopy repo",
287
- "summary": "Create, clone and set up the project's git repository on Canopy."
292
+ "summary": "Create, clone and set up the project's git repository on Canopy, or link a GitHub repository so its pushes deploy."
288
293
  },
289
294
  {
290
295
  "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.
@@ -113,6 +113,26 @@ Turning it off again is the same toggle.
113
113
  > **Note:** Members-only gates the **live app**. Management pages (settings, data, deploys) are always for the
114
114
  > owner, managers and editors only, whatever this toggle says.
115
115
 
116
+ ## Saying who it's for
117
+
118
+ Not every project is meant for everyone who scrolls past it. In **Settings →
119
+ Audience** you can say who it was made for:
120
+
121
+ - **Everyone**, the default. Nothing extra shows on the project list.
122
+ - **Just me**, for a personal tool or experiment.
123
+ - **A client team** or **a department**, with its name (up to 40 characters).
124
+
125
+ Other people see the audience as a small badge next to **Visit** on the
126
+ project list, and personal projects sort below the ones meant for everyone.
127
+ Every Monk can read the name, the same as the project's name and description.
128
+
129
+ Turn on **Still a draft** while it isn't ready. The project shows greyed out
130
+ and sorts lower, but it stays listed and anyone who could open it still can.
131
+
132
+ Both are labels only. They never change who can open the project; that's
133
+ what members-only and the client password are for. From the CLI, use
134
+ [`canopy audience`](https://docs.canopy.website/cli/audience).
135
+
116
136
  ## Platform admins and the Admin page
117
137
 
118
138
  Platform admins get an extra **Admin** page in the dashboard. Its **Users**
@@ -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-BksVeJZB.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-BksVeJZB.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-BksVeJZB.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,40 @@ 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-C6kiYRro.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-D5gmZRJk.mjs").then((m) => m.docsCommand),
93
+ skill: () => import("./skill-Bz39NhTN.mjs").then((m) => m.skillCommand),
94
+ upgrade: () => import("./upgrade-BjDaghNf.mjs").then((m) => m.upgradeCommand),
95
+ logs: () => import("./logs-dZMPTJLu.mjs").then((m) => m.logsCommand),
96
+ mcp: () => import("./mcp-DuCxfb85.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
+ audience: () => import("./audience-B68YZBGy.mjs").then((m) => m.audienceCommand)
99
100
  }
100
101
  });
101
102
  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";