From Claude Code or Cursor to a deployed app.
Claude Code and Cursor leave you with an app that runs on your laptop: a dev server, a local .env, often a SQLite file, sometimes no lockfile. To deploy it, commit the lockfile, move secrets into environment variables, make the server read PORT and give it a real database. Then run canner deploy or let the agent deploy over MCP.
Facts checked
What the agent leaves you with
An agent optimises for “it works when I run it here”. That is the right goal while you build, and it leaves the same handful of things behind almost every time:
- A dev command, not a start command.
npm run dev,next devorviteonlocalhost:3000or5173. - Secrets in a local file.
.envor.env.localwith real keys. Sometimes an.env.examplelisting what the app expects, sometimes nothing. - A local database. A
dev.dbSQLite file, or aDATABASE_URLpointing at Postgres on your machine. - A lockfile that is missing or stale. The agent edited
package.jsonand never re-ran the install, or the lockfile was never written. - A port or URL typed in.
app.listen(3000), orhttp://localhost:3000as the API base in the frontend. - An adapter for someone else’s platform. Ask for “a SvelteKit app” after reading a Vercel tutorial and you may get
@sveltejs/adapter-vercel.
The gaps to close, and what the build log says
Until a project’s first successful deploy, Canner reads the upload before building and writes a warning for each of these into the build log, prefixed [canner] ⚠. The middle column is that text, or the error the build stops on. Fix them before the first deploy and you skip a round trip.
| Gap | What the build log says | Fix |
|---|---|---|
| No lockfile | [canner] no lockfile found — installing with … The build continues, but dependencies aren’t pinned. | Run npm install (or pnpm, yarn, bun) and keep the lockfile it writes. |
| Stale lockfile | npm’s own error: npm ci can only install packages when your package.json and package-lock.json … are in sync | Run the install again locally and deploy the updated lockfile. |
Variables in .env.example not set | Env vars RESEND_API_KEY are listed in .env.example but not set — add them in the project's Environment variables. | canner env set KEY=value --sensitive, or paste your .env into the bulk editor on the Env Vars tab. |
| Supabase keys missing at build | supabaseUrl is required. | Set VITE_SUPABASE_URL or NEXT_PUBLIC_SUPABASE_URL and the anon key before you build: browser variables are baked in at build time. |
| Hard-coded port | app did not respond on / within 30s | Listen on process.env.PORT. Canner sets it. |
| ORM but no database | Uses Prisma but the project has no database yet — create one on the project's Database page so DATABASE_URL is set at build and runtime. | canner db init. DATABASE_URL is injected for the build and the running app. |
| Vendor adapter | @sveltejs/adapter-vercel only runs on that vendor's platform — switch to the Node adapter for your framework. | Use @sveltejs/adapter-node (or your framework’s Node adapter). |
Deploy with the CLI
The CLI is the shortest path, and Claude Code or Cursor can run it in their own terminal. No Git repository is needed: canner deploy packs the folder and sends it to the same build pipeline a push uses.
npm install -g @canner-ca/cli # Node 20 or later
canner login # paste a cnr_ token from Identity → API keys
canner init # creates the project, writes canner.json
canner db init # only if the app uses Postgres
canner env set OPENAI_API_KEY=sk-... --sensitive
canner deploy --follow # uploads, builds, streams the logKeep your .env out of the upload
canner deploy always leaves out node_modules, .git, .next, .nuxt, .turbo, .vercel and .svelte-kit. It does not read .gitignore, so a local .env goes up with everything else unless you exclude it. Add a .cannerignore next to package.json:
Set the real values as environment variables instead. --follow exits with 0 when the app is live and 1 when the build fails, so an agent running the command sees the failure and can read the log. The compressed upload is capped at 100 MB on Starter and 500 MB on Live.
# .cannerignore (canner deploy does not read .gitignore)
.env
.env.*
*.sqlite
coverage/Or let the agent deploy through MCP
The Canner MCP server gives the agent tools instead of shell commands: canner_create_project, then canner_save_app with the files, then canner_get_deployment to read the build log. Deleting projects, databases, domains or tokens is not exposed, so an agent can’t do it by mistake.
- Prompt: “Create a Canner project for this app, save it with the Canner tools, set the environment variables from .env.example, and give me the live URL. If the build fails, read the log and fix it.”
- CLI or MCP?
canner_save_appneeds the complete contents of every file sent through the conversation, up to 2,000 files. That is fine for a small app and slow for a large one. For anything big, have the agent run the CLI. - Tokens: if you already ran
canner login, the local server reads that token and you can leave outCANNER_TOKEN. For a token pasted into a third-party tool, use the “MCP connector (deploy only)” type.
| Client | How to add Canner |
|---|---|
| Any agent with a terminal | No MCP needed: the agent runs canner deploy --follow itself. |
| Claude Code, local server † | claude mcp add --env CANNER_TOKEN=cnr_… --transport stdio canner -- npx -y @canner-ca/mcp |
| Claude Code, remote server † | claude mcp add --transport http canner https://api.canner.ca/mcp --header "Authorization: Bearer cnr_…" |
| Cursor † | Add the canner entry from the MCP docs to .cursor/mcp.json (this project) or ~/.cursor/mcp.json (every project). |
† Competitor details come from each vendor’s own published pages on the dates shown; prices and plans change, so check the vendor before you decide. Claude Code, local server (2026-10-29) · Claude Code, remote server (2026-10-29) · Cursor (2026-10-29)
After the first deploy
- Logs:
canner logs --followstreams the running app’s output. The agent can do the same with the MCP tools for errors and logs. - Migrations: put
npx prisma migrate deploy(or your tool’s equivalent) in the release command under Settings → Build, not in the build command. - Sleep: Starter apps sleep after 3 hours without a request and wake on the next one. Live keeps 2 projects always on and adds custom domains.
- Everything else for AI-built apps is on the Host AI-built apps page.
Questions
Can Claude Code deploy my app by itself?
Yes. It can run canner deploy --follow in its terminal and read the build log, or call the Canner MCP tools to create a project and save the app. Destructive actions such as deleting a project are not available to it.
Does canner deploy upload my .env file?
Yes, unless you exclude it. It skips node_modules, .git and build folders, but it does not read .gitignore. Add .env and .env.* to a .cannerignore and set the values as environment variables.
Do I need GitHub to deploy?
No. canner deploy and the MCP canner_save_app tool both upload files directly. Connect GitHub later if you want a deploy on every push and preview URLs for pull requests.
Why does the build fail with “supabaseUrl is required”?
The Supabase client is created during the build and the URL is empty. Browser variables such as VITE_* and NEXT_PUBLIC_* are baked in at build time, so set them on the project and deploy again.
Deploy what your agent built.
Starter is free and needs no card. Run canner deploy once and you have an HTTPS URL in Montréal.