iugu is the command-line surface of the iugu Platform 2 Console for developers and the AI coding
agents that work with them: log in once, create and configure Console apps, get workspace-restricted
credentials without ever seeing them in a chat window, test authorization, publish. Every command has
--json, meaningful exit codes and a human-approval loop for sensitive operations (change sets).
The CLI talks to the Lifecycle API (https://api.console.iugu.com/v1; the OpenAPI 3.1 contract is
published at https://developer.iugu.com/console/api-v1.yaml) with OAuth 2.1 tokens issued by Console's authorization server
(https://identity.iugu.com). It does not embed an MCP server: iugu agent setup points each harness at
Iugu for AI, the remote MCP server https://mcp.console.iugu.com/mcp, which exposes the same operations as MCP tools
(clients connect through OAuth — Claude Code, Codex, Cursor, VS Code, ChatGPT — no CLI needed there).
Documentation (pt-BR): https://developer.iugu.com/console/cli — and the whole developer path, from the first app to billing and agents, at https://developer.iugu.com/console/development.
brew install iugu/tap/iugu # macOS / Linux
curl -fsSL https://raw.githubusercontent.com/iugu/cli/main/install.sh | sh # any unix
scoop bucket add iugu https://github.com/iugu/scoop-bucket && scoop install iugu # Windows
npx @iugu/cli --help # npm shimReleases are built by goreleaser, signed with cosign (keyless) and ship an SBOM; install.sh, the
Homebrew cask and the npm shim verify the archive against the signed checksums.txt.
iugu login # browser: Console login + agent consent (scopes × workspaces)
iugu me # who am I, which workspaces are consented
iugu app init --name "Acme Invoices" --workspace <dev-workspace-id>
# → creates the app (private draft), installs it in the workspace, requests a workspace-restricted
# credential (needs one human approval: exit 5 with approval.url), writes iugu.toml
iugu changeset wait <id> --write-env .env.local # blocks until approved; secret → .env.local (0600)
iugu app permissions set --implemented invoice.create,invoice.read --grant-scopes informations
iugu test-principal create --name qa # temp principal with roles ⊆ yours, 1 h
iugu verify --principal temp:… --action acme-invoices:invoice.create
iugu app env --format fly # non-secret environment for your deploy target
iugu changeset create --op 'oauth.update:{"url":"https://acme.example","callbacks":["https://acme.example/oauth/callback"]}' \
--op 'listing.publish:{"public":true,"draft":false}' --submit --waitAgents: run iugu docs (or iugu docs --llms) — the embedded skill explains the golden path, what
needs a human, how to wait, and how to handle secrets. iugu agent setup --all writes the remote MCP
entry and the skill for Claude Code, Codex, OpenCode, Cursor and VS Code.
| Situation | What happens |
|---|---|
| Human with a browser | iugu login: authorization code + PKCE (S256), redirect to a one-shot http://127.0.0.1:<random>/callback, state and iss validated. The browser runs the normal Console login (MFA, SSO) and the agent consent page (scopes × workspaces). |
| Headless / SSH | iugu login --device: RFC 8628 device flow; prints the URL and a code. |
Agent (non-TTY, CI, CLAUDECODE, CODEX_*, OPENCODE*, CURSOR_*) |
iugu login is non-blocking: prints verification_uri_complete, user_code and next_step (iugu login --complete <handle> --wait) and exits 0. Override with --agent yes|no|auto. |
| CI / unattended | IUGU_TOKEN=<deploy token> wins over any stored login and never touches disk. |
| Several accounts or Consoles | --profile/IUGU_PROFILE (e.g. iugu --profile dev login --api https://api.console.<host> for a staging Console; the default profile stays on production); iugu workspace use <id>; iugu login --workspace <id> re-consents and merges a workspace into the grant. A profile's workspace is forgotten when a login no longer covers it. |
The refresh token is stored in the OS keychain (macOS Keychain, Secret Service, Windows Credential
Manager). When the keychain is unavailable — headless Linux, containers, a $HOME without a login
keychain — the CLI warns once and uses ~/.config/iugu/credentials.json (0600). --credentials-store ephemeral keeps it in memory only. On Windows the files live under %USERPROFILE%\.config\iugu; there are no
POSIX mode bits, the profile's ACLs (private to your account) protect them. iugu auth status --json always exits 0 and tells the truth in
logged_in (it checks the grant online; --offline to skip); iugu logout revokes the grant server-side.
One grant per credential holder. Every config dir (~/.config/iugu, a --profile, or a project-local
IUGU_CONFIG_DIR=.iugu) is a holder with its own stable device_id: Console keeps a separate grant for
each, lists them by label ("iugu CLI on mbp (.iugu in acme)") on the Connected agents page, and logging one
out never affects another. Sandboxed agents (Codex workspace-write) should keep their own login in the
project: IUGU_CONFIG_DIR=.iugu iugu login (auto-gitignored). The CLI never rotates a refresh token it
cannot persist (store_not_writable), so a read-only sandbox cannot burn the human's login.
--jsonon every command: stable JSON on stdout, diagnostics on stderr, nothing else.--jq <expr>filters the result (strings print raw). Long waits stream NDJSON events ({"event":…}).- Exit codes:
0ok ·1error ·2usage/cancelled ·4login required ·5approval required (the payload carriesapproval.url,change_set_id,next_step) ·6stale/conflict (re-read, retry) ·7the human must act on the grant first — verify their identity (elevation_required, 15-minute window) or widen the authorization (insufficient_scope,workspace_not_consented) on the URL in the payload, then re-run. At a terminal the CLI opens that page itself, waits for the grant to change and retries; the token never changes. - Tier 0 operations execute immediately; Tier 1 (credentials, OAuth settings, certificates, IP whitelist,
publish, third-party installs, discard, deploy tokens, GIA roles/policies/members/invites) become a change set that a human
approves in Console. Batch them:
iugu changeset create --op … --op … --submit --wait. - Secrets are delivered once, to the requesting CLI, within one hour of approval, through
--write-env <file>(0600,.gitignored),--exec "<cmd> {secret}"(in-process substitution, no shell, redacted in output) or--show-secret.iugu app credentials listshows prefixes only. - Project context lives in
iugu.toml(app id, name, tag, publisher workspace, development workspace/credential);--app <id>overrides it. --idempotency-keyfor mutating requests;--yesfor confirmations;--quietsilences stderr.
login [--device|--non-interactive|--complete <h> --wait] [--scopes …] [--workspace <id>] [--no-browser]
logout · auth status|token · me · workspace list|use <id>
app init --name … --workspace <id> [--wait] · app list|get|update|discard|publish [--billable]
app permissions get|set · app oauth set · app credentials list|create|rotate|revoke
app certificates list|add|revoke · app ip-whitelist set|test <ip> · app entitlements set
app actions list [--refresh] · app actions call <name> --input '{…}' [--arg k=v] [--token <jwt>] (the app's iugu.actions/v1 manifest as Console reads it; test an action as the app itself)
call <app id|tag> <action> [--arg k=v …] [--input '{…}'] [--workspace <id>] (an action of a provider app, as you, through Console's bridge — Billing: `iugu call billing get_plan|set_prices|preview_pricing|publish_version|get_revenue|list_invoices …`; elevated actions are confirmed by the person on a Console page)
app agreements list|publish · app images list|upload|highlight|remove · app deploy-tokens list|create|revoke
app install|uninstall|resync --workspace <id> · app token [--credential <id>] [--scope …] · app env --format dotenv|fly|netlify|vercel|json
changeset create --op <type>:<json>… [--submit] [--wait] · changeset list|show|submit|wait|secrets|withdraw <id>
approvals list|open|wait <id> · verify --principal … --action … · test-principal create|list|delete
gia roles|policies|members|invites (reads) · gia roles|policies create|update|delete · gia members set-roles|remove <id|email> · gia invites create|resend (Tier 1, scope console:gia.write)
catalog actions [--q text]
agent setup [--claude|--codex|--opencode|--cursor|--vscode|--all] · docs [topic] [--llms] · completion <shell>
make build # bin/iugu
make test # go test ./... (IUGU_TEST_KEYCHAIN=1 also exercises the OS keychain)
make lint # go vet + staticcheck
make snapshot # goreleaser snapshot (no publish, no signing)Point the CLI at another Console (a staging or development instance) with IUGU_API=https://api.console.<host> and
IUGU_CLIENT_ID=<that Console's CLI client id>.
The AS is discovered from the API (/.well-known/oauth-protected-resource → /.well-known/oauth-authorization-server).
MIT.