{
  "name": "agent-deploy",
  "title": "Headless Deploy with Agent API Tokens",
  "description": "Authenticate an autonomous agent, script, or CI job to Gipity with a long-lived agent API token (gip_at_*) instead of interactive login, then run the full build → deploy loop unattended",
  "guid": "sk_plat_atok",
  "category": "App development",
  "requiredTools": [],
  "content": "# Headless Deploy with Agent API Tokens\n\nThe normal `gipity login` is interactive: it emails a 6-digit code that a human reads and pastes back. An autonomous agent, a cron job, or a CI runner has no inbox to check - and a fresh/ephemeral container has no saved session on disk. For those, use a long-lived **agent API token** (`gip_at_*`) instead. It authenticates from an environment variable, so it survives fresh containers, never expires unless you set `--expires`, bills to your account like any other usage, and can be revoked instantly.\n\nThis is the path for **self-hosted coding agents (e.g. Hermes, OpenClaw), scripts, and CI** that want to build, deploy, and operate Gipity apps without a human in the loop.\n\n## When to use this\n\n- You're an agent/script running unattended - no human to read an email code.\n- You run in an ephemeral or rebuilt container (no persistent `~/.gipity/auth.json`).\n- You're wiring Gipity into CI/CD or a scheduled job.\n\nIf a human is present at a terminal, plain `gipity login` is simpler - see [getting-started](getting-started.md). Use a token when login can't be completed interactively.\n\n## 1. Mint a token (one time, needs an interactive session)\n\nFrom a machine where you're already logged in - your own CLI **or** the web CLI in the browser:\n\n```bash\ngipity token create --name \"Hermes on my VPS\"        # name is a label you choose\ngipity token create --name \"CI deploy\" --expires 90  # optional expiry, in days\ngipity token create --name \"ci\" --expires 90 --json  # machine-readable\n```\n\nIt prints the token **once** - copy it immediately, it can't be retrieved later:\n\n```\ngip_at_eygYHKVRkBP8UXY5dfQzZV_xMH6t1x4Bynnhv4GD128\n```\n\nOnly a hash is stored server-side, so a lost token can't be recovered - only revoked and replaced. With `--json` the output is `{ \"token\": \"gip_at_…\", \"shortGuid\": \"at_…\", \"expiresAt\": \"…\"|null }`.\n\n## 2. Use it: set GIPITY_TOKEN\n\nPut the token in the agent's environment. The CLI picks it up automatically, skips login entirely, and acts as your account:\n\n```bash\nexport GIPITY_TOKEN=gip_at_eygYHKVRkBP8UXY5dfQzZV_xMH6t1x4Bynnhv4GD128\n```\n\nThat's the whole auth step. `GIPITY_TOKEN` takes precedence over any saved session, so the same command works identically in a fresh container with no `auth.json` and on a logged-in workstation. Every CLI command now works unattended:\n\n```bash\ngipity status                       # confirms authenticated, no login prompt\ngipity init                         # link the cwd as a project (or `gipity add <template>` in an empty dir)\ngipity deploy dev                   # → https://dev.gipity.ai/<account>/<project>/\ngipity page inspect <url>           # headless verify: console errors, failed resources\n```\n\nThe full build loop - `gipity add` → edit files → `gipity deploy dev` → `gipity page inspect` → fix → repeat (see [deploy](deploy.md)) - runs with no interactive step anywhere.\n\n> **Keep deploys on dev.** Never run `gipity deploy prod` unattended unless the job is explicitly a production release - `prod` publishes to the user's live URL.\n\n## 3. Manage and revoke\n\n```bash\ngipity token list              # active tokens: name, created, expires, last-used\ngipity token revoke <id>       # e.g. gipity token revoke at_espgamjb - instant, irreversible\n```\n\nRevocation takes effect immediately. The active token count also appears on the Plan tab in Monitor.\n\n## Security notes\n\n- **Treat a token like a password.** It acts as your full account and bills to you.\n- **Never commit it.** Inject it through the platform's secret store / environment, not a tracked file. Don't echo it into logs.\n- **Scope its lifetime** with `--expires <days>` for CI or short-lived agents; omit it only for long-running trusted agents.\n- **Rotate on suspicion.** If a token may have leaked, `gipity token revoke <id>` and mint a fresh one - there's no in-place rotation.\n- **One token per consumer.** Give each agent/CI job its own named token so you can revoke one without disrupting the others, and `last-used` tells you which is which.\n\n## How it works (reference)\n\n| Piece | Detail |\n|---|---|\n| Token format | `gip_at_` + random secret; shown once at creation |\n| Env var | `GIPITY_TOKEN` - read by the CLI on every command, ahead of any saved login |\n| Sent as | `Authorization: Bearer gip_at_…` to the Gipity API |\n| Stored as | A one-way hash server-side - never the plaintext |\n| Lifetime | Never expires unless `--expires <days>` is set; revoke is instant |\n| Mint / list / revoke | `POST` / `GET` / `DELETE` `…/auth/agent-tokens` (via `gipity token …`) |\n\n## Related skills\n\n- [getting-started](getting-started.md) - accounts, the interactive `gipity login`, credits\n- [deploy](deploy.md) - the deploy pipeline and `gipity.yaml` the token-authed agent drives\n- [web-app-basics](web-app-basics.md) - building the app you deploy\n"
}
