# How to let an AI coding agent deploy your app safely

*Versions: Claude Code 2.1.322, Hubfly space CLI v5.0.1*

Your coding agent can write the feature and run the tests. Then it hands you a list of deploy commands to paste. Giving it your cloud CLI fixes that, but the same agent can now delete a database or print its password into the chat. This guide shows how to let an AI coding agent deploy your app safely: it reads freely, asks before anything that ships or costs money, and is blocked from the common commands that destroy data or reveal secrets. A spending cap in the dashboard backs it up.

[Try it on Hubfly space →](https://dashboard.hubfly.space/?ref=coding-agent-deploy-safely-hubfly)

## How to let an AI coding agent deploy safely: three fences

1. **The agent's habits:** the Hubfly space agent skill tells it how to plan, when to ask and what never to print.
2. **Your agent's permission rules:** Claude Code checks every shell command against allow, ask and deny lists before it runs.
3. **The platform:** a monthly budget cap and a separate project for agent work, set in the dashboard.

![An agent's command passes the skill's rules, then Claude Code's permission check, then the project's budget cap](https://eager-gecko.eu1.hubfly.app/blog-images/blog/2026/11/a2525ba4-6e09-4569-ac5e-8ed692e7fb42.png)

## Step 1: Install the CLI and log in yourself

Install the Hubfly space CLI (v5.0.1 at the time of writing) from the [CLI docs](https://www.hubfly.space/docs/cli/auth/?ref=coding-agent-deploy-safely-hubfly), then run `hubfly login` in your own terminal, never through the agent's chat. Why: the agent can use your session without the token ever appearing in the conversation.

## Step 2: Add the agent skill to your repo

Hubfly space publishes a skill file for coding agents. Save it where Claude Code looks for project skills:

```bash
mkdir -p .claude/skills/hubfly-cli
curl -fsSL https://www.hubfly.space/skills/hubfly-cli/SKILL.md \
  -o .claude/skills/hubfly-cli/SKILL.md
```

For other agents, `.agents/skills/hubfly-cli/SKILL.md` is the portable location that Codex and Cursor also scan.

Read it before you commit it. Why: these are the instructions your agent will follow. Four rules do most of the safety work:

- `--yes` "is not user authorization". It only skips the CLI's own prompt after you have approved the exact operation.
- `hubfly stack down --volumes` counts as data deletion and needs a separate confirmation that names the volumes.
- Secrets stay out of the chat: `db url`, `db env` and `db credentials` hide values unless `--reveal` is added, and the agent is told to avoid `printenv`.
- `hubfly deploy plan` is **not** guaranteed to be read-only. It skips the image build, upload and rollout, but it can write `hubfly.build.json`, download a builder, or bind or create a project.

Two more things the skill does:

- **It re-fetches itself.** The agent loads the live skill at the start of every task and follows it where your copy differs. That keeps it current, but a change reaches your agent before you read it.
- **It edits your instruction file.** On first use, the agent adds a short block between `<!-- hubfly:skill:start -->` and `<!-- hubfly:skill:end -->` to `CLAUDE.md`, `AGENTS.md` or similar, so later sessions remember where the project deploys. Review that diff like any other.

## Step 3: Write the permission rules

Save this as `.claude/settings.json` in the repo:

```json
{
  "permissions": {
    "allow": [
      "Bash(hubfly whoami)",
      "Bash(hubfly version)",
      "Bash(hubfly stack status *)",
      "Bash(hubfly stack logs *)",
      "Bash(hubfly logs *)",
      "Bash(hubfly build validate *)",
      "Bash(hubfly build explain *)"
    ],
    "ask": [
      "Bash(hubfly deploy *)",
      "Bash(hubfly stack plan *)",
      "Bash(hubfly stack up *)",
      "Bash(hubfly stack exec *)",
      "Bash(hubfly stack ssh *)",
      "Bash(hubfly compose *)",
      "Bash(hubfly container *)",
      "Bash(hubfly exec *)",
      "Bash(hubfly ssh *)",
      "Bash(hubfly tunnel *)",
      "Bash(hubfly env *)",
      "Bash(hubfly db *)",
      "Bash(hubfly database *)",
      "Bash(hubfly databases *)",
      "Bash(hubfly storage *)",
      "Bash(hubfly realtime *)",
      "Bash(hubfly rt *)",
      "Bash(hubfly update *)",
      "Bash(hubfly config *)"
    ],
    "deny": [
      "Bash(hubfly stack down *)",
      "Bash(hubfly compose down *)",
      "Bash(hubfly * delete *)",
      "Bash(hubfly storage rm *)",
      "Bash(hubfly * rotate *)",
      "Bash(hubfly * revoke *)",
      "Bash(hubfly * credentials *)",
      "Bash(hubfly * --reveal*)",
      "Bash(hubfly login *)",
      "Bash(hubfly logout *)",
      "Bash(hubfly auth *)",
      "Bash(printenv *)",
      "Bash(env)"
    ]
  }
}
```

Here is what Claude Code 2.1.322 does with this file:

![What Claude Code does with each command: whoami, stack status and logs run; deploy, deploy plan and db list ask; delete, --reveal, chained stack down and printenv are blocked](https://eager-gecko.eu1.hubfly.app/blog-images/blog/2026/11/da9d3b64-44ec-4d43-bae6-8959cb859706.png)

Why the file looks the way it does:

- **Deny beats ask, and ask beats allow.** So `hubfly db url orders-db --reveal` is blocked even though `db` is in ask, and `hubfly deploy --yes` still asks. The flip side: an allow rule can't carve a hole in an ask rule, so `hubfly deploy status` asks too.
- **A `*` in the middle works.** `hubfly * delete *` blocks `db delete`, `database delete`, `rt delete` and `storage buckets delete` with one line.
- **Watch out for aliases.** The CLI accepts `database` and `databases` for `db`, and `rt` for `realtime`. A deny rule written as `hubfly db delete *` would miss `hubfly database delete orders-db`.
- **Use `--reveal*`, not `--reveal *`.** The version with a space doesn't match when `--reveal` is the last word.
- **Chained commands are checked part by part.** In `hubfly whoami && hubfly stack down --volumes` the second part hits deny, so nothing runs.
- **`build validate` and `build explain` stay in allow** because they don't deploy anything, though they can create or normalise `hubfly.build.json`. `git diff` shows what changed.
- **You log in and out, not the agent.** Denying `login`, `logout` and `auth` stops it from switching accounts.

If you need a secret in a local file, run the `--reveal` command yourself in your own terminal and keep that file in `.gitignore`.

## Step 4: Add the platform fence

Permission rules match command text, and Claude Code's docs say Bash rules aren't a security boundary. For example, `sh -c 'hubfly stack down'` doesn't match the deny rule: it gets a normal permission prompt, so it only stops if you read it and say no. So add limits that live outside the agent's files:

- **A separate project for agent work.** Name it after the app, such as `shop-web`, and tell the agent to deploy only with `--project shop-web`. If something goes wrong, only that project is affected.
- **A monthly budget cap.** When you create the project, open **Advanced Options** and set **Monthly Budget Limit**: $10, $50, $100, Unlimited, or any amount above $1.00. You can change it later in the project's **Settings → General & Budget**.

![Monthly Budget Limit set to $10 in Advanced Options when creating a project](https://eager-gecko.eu1.hubfly.app/blog-images/blog/2026/11/ac8a0554-a4bf-4960-a959-f26ba67ae0ba.png)

The cap is a hard stop. You get emails at 80% and 90%. When the month's spend (UTC) reaches the cap, the project's running containers, Hubfly space Boxes and managed services stop, and new starts and deploys are blocked. Raising the cap, or the next month, lifts the block, but stopped workloads don't restart on their own.

![Project settings showing a $10 monthly cap, $0.00 spent and the hard-stop rules](https://eager-gecko.eu1.hubfly.app/blog-images/blog/2026/11/7cc623c6-b0a7-4050-a52a-1de42b3c15ba.png)

- **Know what the token can do.** API tokens support exact-match scopes and can be pinned to up to 50 projects ([API authentication](https://www.hubfly.space/docs/api/authentication/?ref=coding-agent-deploy-safely-hubfly)), but the CLI docs say a CLI login token carries full project deployment and execution scope. Treat the agent's session as having that full access. That's why the deny list and the cap matter.

## Step 5: Ask for a deploy

Start Claude Code in the repo, run `/permissions` to see the rules it loaded, then try:

> Deploy my web app to the shop-web project with HTTPS and keep Postgres private.

Status checks run without asking. Every `plan`, `up`, `deploy`, `env` or `db` command stops for a yes, so approve the plan first and read what will change. The skill tells the agent to report success only when the deployment session reaches its final state, along with the build ID.

## What it costs

The skill and CLI are free. One always-on Dedicated Hubfly space Cell (1 vCPU, 512 MB RAM, 5 GB disk) for a 730-hour month:

| Item | Math | Monthly |
| --- | --- | --- |
| CPU | 1 × $0.004 × 730 | $2.92 |
| RAM | 0.5 GB × $0.002 × 730 | $0.73 |
| Storage | 5 GB × $0.00001536 × 730 | $0.06 |
| **Total** |  | **≈ $3.71** |

That fits well under a $10 cap. Shared-tier containers sleep when idle and come with 360 free compute hours a month, which suits preview deploys. Creating new resources needs a one-time deposit of $5 or more, kept in your account as credit.

## What can go wrong

1. **`hubfly deploy` runs with no prompt.** Open `/permissions`, check the ask rule is listed, and make sure you haven't switched to a mode that skips prompts. `--yes` never skips Claude Code's prompt.
2. **A command you expected to run keeps asking.** An ask rule wins over a more specific allow rule. Approve it, or accept the extra prompt.
3. **Secrets land in the chat.** `--reveal` and `printenv` are blocked, but an `exec` or `ssh` command that runs `env` inside a container is another route. That's why `exec` and `ssh` are in ask: read the command before you approve.
4. **A wrapped command gets a prompt instead of a block.** Say no to any prompt that hides a `hubfly` command inside `sh -c` or a script.
5. **Workloads stopped and didn't come back.** The project hit its cap. Raise it, then start the containers again yourself.

## Who this is NOT for

- **Unattended CI.** This setup needs a person to answer prompts. Use a pipeline with `HUBFLY_TOKEN` stored as a secret.
- **Teams that need a hard wall.** Use Claude Code's sandbox or a separate machine. Permission rules are a seatbelt, not a vault.

## FAQ

**Can an AI coding agent deploy to production safely?** Much more safely if it must ask before every deploy, is blocked from delete and secret commands, and works in a project with a budget cap. Keep production in its own project.

**Are deny rules enough to stop an agent deleting data?** No. A wrapped command gets a prompt instead of a block. Add the cap and a separate project, and read every prompt.

**Does `--yes` bypass Claude Code's permission prompt?** No. It only skips the CLI's own confirmation.

**What happens when the budget cap is reached?** Emails at 80% and 90%. At 100% the project's workloads stop and deploys are blocked until you raise the cap or the month resets.

**Is `hubfly deploy plan` read-only?** Not guaranteed. It can write a config file or create a project, so keep it behind a prompt.

**Does this work with Codex or Cursor?** The skill does, from `.agents/skills/`. Their approval settings use their own format, so copy the same allow, ask and deny split.

## Go further on Hubfly space

- Give each agent task its own locked-down container: [AI agent sandbox, one container per task](https://blog.hubfly.space/sandbox-ai-agents-container-per-task?utm_source=hashnode&utm_medium=crosspost&utm_campaign=coding-agent-deploy-safely-hubfly).
- Deploy from CI instead of a chat with [deploy on push using a GitHub Actions webhook](https://blog.hubfly.space/deploy-on-push-github-actions-webhook?utm_source=hashnode&utm_medium=crosspost&utm_campaign=coding-agent-deploy-safely-hubfly).
- Gate your deploy on a database migration with [a migration job in Docker Compose](https://blog.hubfly.space/docker-compose-migration-job-service-completed-successfully?utm_source=hashnode&utm_medium=crosspost&utm_campaign=coding-agent-deploy-safely-hubfly).

**360 free compute hours a month on the shared tier**; a one-time $5 deposit, kept as credit, unlocks new resources. Create a project with a $10 budget cap and let your agent ship its next preview. [Try it on Hubfly space →](https://dashboard.hubfly.space/?ref=coding-agent-deploy-safely-hubfly)

---

*By Octave · drafted with AI, reviewed by Octave · Last updated 10 November 2026*

