@canner-ca/cli
v0.4.1
Published
Canner deploy CLI — git push from any terminal, no GitHub required
Downloads
224
Maintainers
Readme
@canner-ca/cli
Deploy to Canner from any terminal. Works in macOS, Linux, Windows, and Cursor's integrated terminal. No git required.
Install
npm install -g @canner-ca/cliOr run without installing:
npx @canner-ca/cli@latest deploy --followRequires Node.js 20 or later.
Quick start
# Sign in once (paste an API token from canner.ca/dashboard/account)
canner login
# In your project directory, create a Canner project
canner init
# Ship it
canner deploy --follow--follow streams the build log live and exits with the build's success code, so it works as the last step of a CI pipeline.
Commands
Setup
| Command | What it does |
|---|---|
| canner login | Prompt for an API token, store it at ~/.canner/credentials (mode 0600). |
| canner logout | Delete ~/.canner/credentials from this machine. |
| canner whoami | Show the email + plan this CLI is signed in as. |
Projects
| Command | What it does |
|---|---|
| canner projects | List your projects. |
| canner init [--slug X] | Create a new Canner project and write canner.json in the current directory. |
| canner status [--slug X] | Show one project's state — URL, status, source, last request. |
| canner open [--slug X] [--dashboard] | Open the tenant URL (or the dashboard project page) in your browser. |
Deploys
| Command | What it does |
|---|---|
| canner deploy [path] [--slug X] [--follow] | Tar the directory and upload. Works for any project — GitHub-connected or upload-only. --follow streams the build log and exits with the build's success code. |
| canner redeploy [--slug X] [--follow] | Trigger a rebuild from the GitHub repo's HEAD without uploading. GitHub-connected projects only. |
| canner deployments [--slug X] | List the project's recent deployments. |
| canner deployments <id> [--slug X] [--follow] | Show one deployment's build log; --follow streams if it's still in progress. |
| canner cancel [<id>] [--slug X] | Abort the in-flight build (or a specific one by id). |
| canner logs [--slug X] [--lines N] [--follow] | Stream the running tenant's runtime logs (last 200 lines by default). |
Resources
| Command | What it does |
|---|---|
| canner token list | List your cnr_ API tokens. |
| canner token create <name> | Mint a new token. The secret is printed once — copy it immediately. |
| canner token revoke <id\|name> | Revoke a token. |
| canner env [list] [--reveal] [--slug X] | List a project's environment variables. Values marked sensitive are redacted (••••••, or null in --json) unless --reveal is passed. |
| canner env set KEY=VALUE [--env production\|preview] [--sensitive] [--slug X] | Add an environment variable. |
| canner env rm <KEY\|id> [--env ...] [--slug X] | Delete an environment variable. |
| canner domains [list] [--slug X] | List a project's custom domains. |
| canner domains add <hostname> [--slug X] | Attach a custom domain (starts pending). |
| canner domains verify <hostname\|id> [--slug X] | Re-check DNS and provision TLS. |
| canner domains rm <hostname\|id> [--slug X] | Detach a custom domain. |
JSON output
Add --json to any command for machine-readable output — tables and progress lines are suppressed and a single JSON value is printed to stdout, so the result pipes straight into jq or an agent. Errors are written to stderr as {"error":"..."} with a non-zero exit code. With --json, deploy --follow does not stream the build log (it would corrupt the JSON); poll canner deployments <id> --json for the terminal status instead.
canner projects --json | jq -r '.[].slug'
canner deploy --json # → {"deployment_id":"…","status":"queued",…}
canner env list --slug my-app --jsonThis pairs with the REST API directly: every command wraps an endpoint documented in the API reference (interactive explorer at https://api.canner.ca/docs, OpenAPI spec at https://api.canner.ca/openapi.json).
What gets uploaded
The CLI tars the current directory into a .tar.gz, excludes the "build noise" defaults, and streams it to the same upload endpoint the dashboard's drag-drop uses. The server-side build pipeline detects the framework and runs install / build / deploy just like a git push.
Always excluded (no opt-out): node_modules/, .git/, .next/, .nuxt/, .turbo/, .vercel/, .svelte-kit/, .DS_Store, Thumbs.db. The server-side pipeline rebuilds these from your package.json anyway.
Additionally excluded if present: anything in .cannerignore. Format is similar to .gitignore but simpler:
# comment lines start with #
build
coverage/
*.log
/dist # leading slash anchors to project rootSupported: basename matches anywhere in the tree, trailing-slash for directory-only, leading-slash for root-anchored, single-segment * glob. No negation.
Per-project config: canner.json
canner init writes this in your project root. Commit it alongside your source so canner deploy knows the target slug:
{
"slug": "my-app"
}Override the slug per-run with --slug=other-app if you maintain multiple environments.
Environment variables
| Variable | Purpose |
|---|---|
| CANNER_TOKEN | Use this token instead of the one in ~/.canner/credentials. Handy for CI. |
| CANNER_API_BASE | Override the API endpoint. Default https://api.canner.ca. |
CI / GitHub Actions
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npx @canner-ca/cli@latest deploy --follow
env:
CANNER_TOKEN: ${{ secrets.CANNER_TOKEN }}--follow exits with the build's success code, so a failed build fails the workflow.
Cursor / AI agents
Works in any terminal, including Cursor's integrated terminal. Agents can invoke it as a shell tool — no extension or MCP server required:
canner deploy --followPlan size caps
The CLI uploads under the same per-tier compressed-archive cap as the dashboard:
- Starter — 100 MB
- Live — 500 MB
- Dedicated — 1 GB
If your project is bigger than that compressed, drop heavier directories into .cannerignore or upgrade your plan. node_modules is already excluded; the typical thing that pushes a project over the cap is a public/ folder full of media.
What this CLI stores and sends
Written to your machine — two files, both plain text you can read:
| Path | Contents | Written by |
|---|---|---|
| ~/.canner/credentials | { api_base, token }, mode 0600 | canner login |
| ./canner.json | Your project slug, in the project directory | canner init |
Nothing else is written. No system settings, shell profiles, PATH entries, or startup items are modified.
Sent over the network: requests go only to https://api.canner.ca (or
whatever CANNER_API_BASE is set to). canner deploy uploads a tar of your
project directory — minus node_modules, .git, build output, and anything in
your .cannerignore — so that we can build and host it.
Telemetry: none. There is no usage tracking, analytics, crash reporting, or phone-home of any kind. The CLI makes no network request you didn't ask for by running a command.
Removing the CLI
canner logout # delete ~/.canner/credentials
npm uninstall -g @canner-ca/cli # remove the packagecanner logout removes the stored credential from this machine only. The
token itself stays valid — the same token may be in use in CI or on another
machine, so logging out on your laptop deliberately doesn't kill it. To revoke
it everywhere, run canner token revoke <name> before logging out, or revoke it
from your dashboard's API tokens page.
If you've already uninstalled the package and want to clear the leftover
credential, delete ~/.canner/credentials by hand. Removing it affects nothing
else; canner.json in a project directory is just a slug and is safe to keep or
delete.
Terms
Use of the CLI and the Canner service is governed by the Terms of Service and the Privacy Policy.
License
MIT.
