Deploy to Granite with Claude Code

Say "deploy this to Granite" and the agent reads your repository, writes the manifest, ships the image and hands you back a URL. One git clone to set up, and every command it runs is one you could have typed yourself.

How do I deploy an app to Granite with Claude Code?

Install the Granite CLI, log in, then clone the Granite skill into ~/.claude/skills/novps. Claude Code loads it automatically the next time you mention deploying, and drives the CLI for you — no MCP server, no API keys beyond your own personal access token.

Three commands, then a sentence:

$ curl https://cli.granite.so | sh && novps auth login
Installed novps to ~/.local/bin/novps
Enter your Personal Access Token: nvps_****
Authenticated as you@example.com (project: default)
$ git clone https://github.com/granite-so/claude-skill ~/.claude/skills/novps
Cloning into '/Users/you/.claude/skills/novps'...
done.
The directory must be named novps — Claude Code takes the skill name from the folder. Clone it into .claude/skills/novps inside a project instead if you only want it there. Requires the Granite CLI at v0.3.0 or later.
$ claude
> deploy this to Granite

Reading the repository… found a Dockerfile, a GitHub Actions workflow
publishing ghcr.io/you/api, and a docker-compose.yml with Postgres.
Proposing novps.yaml with one web-app on the published image.

  novps apps apply my-api -f novps.yaml --wait

Deployment succeeded. https://my-api-api.granite.app
The agent proposes before it applies, and shows you the exact command. Nothing here is a special integration — it is the same CLI you would run by hand.

What the skill actually does

It is a set of instructions, not a black box. Every step maps to a command you can read in the skill file and run yourself.
Reads the project before it asks
Git remotes, CI workflows, compose files and framework layout, then a manifest that matches what the repository already does — rather than a questionnaire you have to answer twice.
Prefers the image you already build
If your CI publishes a Docker image, the skill deploys that image instead of rebuilding from source, and resolves the registry credentials for you. A second build of the same commit is time you do not get back.
Monorepo aware
Frontend and backend are deployed from separate images, so a commit to one does not rebuild the other. Building from source has no path filter, and the skill knows it.
Provisions databases
Managed Postgres, MySQL or Redis, created with the CLI and wired into the manifest and your .env, so the connection string never lands in a committed file.
Operates, not just deploys
Tail logs, open a shell in a running container, forward a database port to your machine, scale a resource, rotate registry credentials, redeploy.
Bootstraps from what exists
Already have an app in the dashboard? novps apps export writes the manifest for it, and the skill takes over from there.
Learn more

What the agent can run

The skill is a wrapper around the Granite CLI. This is the surface it works with — the full reference lives in the CLI repository.
Command surface
Everything below is scriptable and takes --json, which is what makes it safe to hand to an agent in the first place.
apps apply
Create or update an application from novps.yaml. Idempotent, matches resources by name. With --wait it polls the deployment and prints the public and private endpoints.
apps export
Turn an application that already exists into a manifest compatible with apply. Registry credentials are never returned.
resources set-image, deploy
Ship a new tag to a running resource — the two commands behind a release when your CI builds the image.
resources logs, connect
Follow logs with -f, filter with --since and --search, or open an interactive shell in the running container.
resources scale, set-env
Change replica size and count, or set environment variables, merging with what is already there or replacing it outright.
databases create
Managed Postgres, MySQL or Redis, with read replicas, backups, connection pools and per-app access rules. --wait returns the connection details once it is ready.
port-forward database
Databases are not exposed publicly. This is how the agent — or you — connects a local client to one.

The manifest it writes

novps.yaml is a plain file you own. The agent proposes it, you read it, and it goes in the repository next to your Dockerfile.
$ cat novps.yaml
envs:
  - key: LOG_LEVEL
    value: info
  - key: DATABASE_URL
    value: ${DATABASE_URL}

resources:
  - name: api
    type: web-app
    source_type: docker
    source:
      type: docker
      name: ghcr.io/you/api
      tag: ${IMAGE_TAG}
    config:
      port: "8080"
    replicas:
      type: sm
      count: 2

  - name: worker
    type: worker
    source_type: docker
    source:
      type: docker
      name: ghcr.io/you/api
      tag: ${IMAGE_TAG}
    config:
      command: "python -m app.worker"
${VAR} is substituted locally from your shell or a --env-file before the manifest is sent, which is how secrets stay out of the committed file. The web app and the queue worker run the same image with different commands.

Before you start

Nothing here is specific to the agent — it is the same setup you need to use the CLI by hand.
Requirements
Granite CLI v0.3.0+
Install with curl https://cli.granite.so | sh. Linux and macOS, x86_64 and arm64.
A personal access token
Create one in the dashboard, then run novps auth login. Tokens start with nvps_.
Claude Code
Or any Claude Agent SDK harness that loads skills. The skill is a folder of markdown, so there is no daemon and no background process.
A Dockerfile, ideally
Docker mode deploys an image your CI already publishes. GitHub mode builds from source instead and needs the Granite GitHub App installed on the repository.

Using another agent

The skill file targets Claude Code, but the CLI underneath was built to be driven by a program.

Cursor, Codex, a shell script in CI or an agent you wrote yourself — all of them can run the same commands. Three properties are what make that workable rather than fragile:

Machine-readable output
Every list and get command takes --json, and so do apps apply, apps deploy and resources deploy. With apply --wait --json the payload includes the deployment status and the resolved endpoints, so an agent never has to parse a table.
Honest exit codes
apps apply --wait exits non-zero when the deployment does not reach success, which means a failed deploy fails the pipeline instead of passing quietly. --force skips every typed confirmation when you genuinely want no prompt.

Claude Code and Granite questions

More questions? Email us at support@granite.so

Every plan includes monthly usage credits and unlimited workspace seats.
See pricing
Be first in line for updates
and special pricing
Get early access to new features and exclusive discounts delivered straight to your inbox