Documentation
7 documents, in the order a reader needs them: install the CLI, set up the cloud, choose the loop a run follows, configure the layers, run another model, connect a provider, and the generated command reference.
Guides
- Getting started
README.md#getting-startedThe quick start: what a reader needs installed, and the two steps from a checkout to a first run.
- GCP setup with fugaro init
docs/gcp-setup.mdThe cloud side, one confirmed step at a time, with the rollback and the offboarding at the end.
- Recipes: choose the task loop
docs/recipes.mdHow to choose the loop a run follows after the first implementation, per run or per repository.
- The project layer
docs/project-layer.mdProject-wide defaults and named workflow profiles, and which layer wins for a key.
- Running a non-Anthropic model (M10)
docs/multi-model.mdRunning a model served by OpenRouter through the gateway that prices and caps every call.
- Git providers
docs/git-providers.mdThe two providers Fugaro opens pull requests on, and the credentials each one is given.
- Fugaro CLI reference
website/content/cli-reference.mdEvery command and flag the binary ships, generated from the command tree and rendered below.
Fugaro CLI reference
Every command and flag fugaro ships, generated from the command tree
(internal/cli.NewRootCmd) by go run ./internal/clidoc. Cobra's own help
and completion commands, the root's -v, --version flag, and the
-h, --help flag of every command, are part of what fugaro --help lists,
so they are here too. Commands the CLI
hides are not listed: they are internal, and a hidden command is not user
documentation.
fugaro
Fleeting cloud workers for coding agents
Usage: fugaro
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for fugaro |
-v, --version |
bool | false |
no | version for fugaro |
Subcommands:
fugaro accounts-- List the named Claude accounts a repository may usefugaro allow-delete-- Record the Terraform addresses a run may delete or replace (the project's owner)fugaro artifacts-- List and download what an artifact run deliveredfugaro backends-- List the compute backends an installation can run its jobs onfugaro budget-- Show and change the project's model-spend caps and kill switchesfugaro cancel-- Cancel a run, letting the runner open a draft PR firstfugaro completion-- Generate the autocompletion script for the specified shellfugaro config-- Work with fugaro.yamlfugaro diagnose-- Explain how a run went: status, tests, review findings, the agent's last word, logsfugaro doctor-- Check that Fugaro is set up and ready, without changing anythingfugaro help-- Help about any commandfugaro image-- Build and inspect a workflow's derived container imagefugaro logs-- Print a run's logs from Cloud Loggingfugaro managed-- Act on a managed project (a project created by fugaro with the coding agent's refusal removed)fugaro plan-- Read a plan's graph artifactfugaro project-- The project's policy, its allow-list and the repositories enrolledfugaro recipes-- List, show, validate and publish recipes, the task loop a run follows after implementfugaro report-- Report what the project spent, by day, week, month, year, repository, model or personfugaro restore-- Rebuild a managed project from zero, into a new GCP project ID, and print what is not restoredfugaro run-- Launch a task in the cloud; it always ends with a PRfugaro runs-- List and inspect runsfugaro secrets-- Store and list a repository's secrets in Secret Managerfugaro setup-- Stand up or adopt the installation's, or a repository's, cloud resources through Terraformfugaro stats-- Aggregate one installation's run records into figures a page can publishfugaro update-- Re-converge the installation, or a checkout's repository, after a CLI upgradefugaro update-skills-- Pin the Fugaro plugin in the repository's .claude/settings.json to this releasefugaro upgrade-- Bring checkouts up to this fugaro: pin the plugin, install or update it in Claude Code, refresh the repository's imagesfugaro validate-- Check a fugaro.yaml against the schema and the repositoryfugaro verify-- Run and record this repository's build, test or lint command (inside a Fugaro run)fugaro version-- Print the fugaro versionfugaro watch-- Watch the project's spend, repositories and running agents live
fugaro accounts
List the named Claude accounts a repository may use
Usage: fugaro accounts
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for accounts |
Subcommands:
fugaro accounts ls-- List the named Claude accounts (claude_accounts in the local config) a repository may use with fugaro run --token
fugaro accounts ls
List the named Claude accounts (claude_accounts in the local config) a repository may use with fugaro run --token
List the names fugaro run --token NAME (and a repository's own agent.oauth_token) accept for a repository: "default" (the repository's own unnamed claude-oauth-token secret, always allowed) first, then every claude_accounts name in the local config whose allow_data_to lists the repository, sorted (config.AllowedClaudeAccounts, the one place that decides the question).
This is a local, read-only lookup, offline whenever a project config is already selected on this machine: it reads the local config file the CLI would otherwise select for a cloud command, and never calls Secret Manager, never reads or prints a token value, only names.
--json's "complete" is false when no project config could be selected for a reason other than an explicit --config/--project/$FUGARO_CONFIG/$FUGARO_PROJECT (several project configs with nothing to pick one, for example): "accounts" is then "default" alone, which may be short the repository's real claude_accounts, not a true answer that none are configured; "note" says why.
Usage: fugaro accounts ls
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for ls |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | repository as owner/name (default: this checkout's origin) |
Subcommands:
This command has no subcommands.
fugaro allow-delete
Record the Terraform addresses a run may delete or replace (the project's owner)
Record which Terraform addresses the project's owner approves for deletion or replacement, in a managed project's fugaro/allow-delete.json at the root of the runs bucket. An approval lives in that object and nowhere else: this command is Fugaro's only writer of it, with the operator's own credentials.
An address is the Terraform address a plan reports, as in google_cloud_run_v2_job.web or module.web.google_storage_bucket.data, and nothing else is recorded — no note and no reason: the object's own version history is the record of who approved what and when.
Run it in your own terminal, as an operator, with your own credentials. Pass the addresses to approve, and they replace the list: an invocation that leaves an address out removes that approval, so the command names the entries it would drop and asks for the project's name before writing such a list. With no addresses the command prints the list and writes nothing; it never empties the list, because an empty list is what an absent one already means.
What the object is for: a run's own credentials cannot write it, and the deployer account a managed apply impersonates will not be able to (D75, Task 1.5), so a managed apply can take its allow-list from the owner's object instead of from the command line of whatever session is applying: fugaro managed apply reads this object and takes no address flag of its own, so the session that applies cannot widen the list. (the converge still honours its own --allow-delete on its own command line, where the addresses go to tf.Guard directly.) What this does not do: a coding agent's session holds the operator's credentials, so it can write this object directly (gcloud storage cp) or unset its agent marker and run this command itself. The refusal below is a speed bump against an agent that uses the program, not a boundary against one that goes around it (SECURITY.md records the wider Owner/Editor bypass).
On a project that is not managed, this writes an object nothing reads: the check below is that the bucket is the project's own runs bucket, which every installation has, not that the project is Fugaro-managed.
The list is read fail-closed: an absent object, an empty one, one naming another project, one whose fields are not exactly the three this command writes, or one this package cannot read is no addresses — and no addresses refuses every delete and replacement rather than permitting them. The write is fail-closed too: if the current list cannot be read, nothing is written, and the write is conditioned on the object being unchanged since that read, so a concurrent write is never silently overwritten (run the command again).
Usage: fugaro allow-delete [ADDRESS...]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for allow-delete |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro artifacts
List and download what an artifact run delivered
Read and fetch the files a mode: artifact run put in the runs bucket.
Both subcommands read the run's result.json, never a bucket listing: ls prints
the record's own table, and get is the object — so an artifact the record names
and the bucket no longer holds (they expire with the run, runs_days) is a
recorded row that ls shows and a get that says exactly that.
The record was written by an untrusted, model-driven run, so get treats every name in it as hostile: it downloads into a fresh directory it creates (./<run>-artifacts/, with --out naming that directory's parent), refuses a name that is absolute, walks out of that directory or begins with a dot, refuses to overwrite an existing file without --force, and verifies the recorded size and sha256 as the bytes arrive, leaving nothing behind when they do not match. What it writes is never opened, executed or unpacked.
Usage: fugaro artifacts
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for artifacts |
Subcommands:
fugaro artifacts get-- Download a run's artifacts, verifying them against its recordfugaro artifacts ls-- List what a run's record says it delivered
fugaro artifacts get
Download a run's artifacts, verifying them against its record
Download one artifact NAME, or every artifact the record lists when NAME is omitted, verifying each one's size and sha256 against the run's result.json as the bytes arrive. A mismatch is an error naming both hashes, and nothing is written — not even the file the download streamed into.
The destination is a fresh directory this command creates, ./<run-id>-artifacts/ unless --out names another parent for it. A name in the record that is absolute, walks out of that directory, begins with a dot or holds a control character is refused — a refusal, never a flattened name. An existing file needs --force to be replaced.
Nothing downloaded is ever opened, executed or unpacked: the recorded content type, the size and the sha256 are printed, and that is all. The sha256 proves the bytes are the bytes the run uploaded; it is not tamper evidence.
Usage: fugaro artifacts get RUN [NAME]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--force |
bool | false |
no | replace a file that is already at a destination path |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for get |
--out |
string | "" | no | the directory to create the run's artifact directory in (default: the working directory) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | the repository RUN belongs to (owner/name; needed only for a bare run ID) |
Subcommands:
This command has no subcommands.
fugaro artifacts ls
List what a run's record says it delivered
List the artifacts RUN (<repo-slug>/<run-id>, or a bare run ID) recorded in
its result.json: name, recorded size, short sha256, recorded content type and
the probe's verdict. The record is shown as it is — a name get cannot
retrieve is listed with the reason, never filtered out, and a missing object is
not ls's to hide: ls is the record, get is the object.
--json prints the record's artifact list verbatim.
Usage: fugaro artifacts ls RUN
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for ls |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | the repository RUN belongs to (owner/name; needed only for a bare run ID) |
Subcommands:
This command has no subcommands.
fugaro backends
List the compute backends an installation can run its jobs on
Usage: fugaro backends
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for backends |
Subcommands:
fugaro backends ls-- List the compute backends this fugaro knows and which one the project uses
fugaro backends ls
List the compute backends this fugaro knows and which one the project uses
List the compute backends a project config's backend: key may name, and which one the selected project uses:
cloud-run Cloud Run jobs (the default, and the one every installation runs on today) cloud-batch Cloud Batch jobs, one VM per run (the VM backend)
A config that names no backend runs on cloud-run. A config that names cloud-batch is refused by this build ("not enabled yet"): the backend and its opener are built and tested, and nothing selects them until Fugaro has passed the live checklist for it.
This is a local, read-only lookup: it reads the project config and the backend names internal/backend defines, and it calls no cloud API. With --json it prints one object instead of two lines, carrying the list, the selected project and the name its config selects.
Usage: fugaro backends ls
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for ls |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro budget
Show and change the project's model-spend caps and kill switches
Look at and change the project's budget: the caps, today's counters, the kill switches and the runs in flight, kept in the project's Firebase Realtime Database (design §8). show needs the Viewer role on the Firebase project; set, kill and resume need the budget-admin role (the project's owners and editors, and terraform.budget_admins). preview needs the Viewer role too, and reads the project's recipes from the runs bucket as recipes ls does, which a plain project Viewer cannot (see docs/gcp-setup.md).
Usage: fugaro budget
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for budget |
Subcommands:
fugaro budget kill-- Halt every run of the project or of one repository (budget admins)fugaro budget preview-- Estimate a batch's worst-case model spend against today's capsfugaro budget prices-- Show the effective model price table, offlinefugaro budget resume-- Clear a kill switch (budget admins)fugaro budget set-- Set a cap, the lease limit or the mode (budget admins)fugaro budget show-- Show caps, today's counters, kill switches, headroom and the runs in flight
fugaro budget kill
Halt every run of the project or of one repository (budget admins)
Set the project's kill switch (--all) or one repository's (--repo [owner/name]), recording who, when and why. --repo with no value means the repository this checkout belongs to, as it does for set. show takes owner/name (its empty --repo means no repository filter, not a checkout), and preview already means this checkout's repository without the flag. Runs in flight halt within seconds (a run in its last stage finishes pushing its work first) and new runs refuse. --all asks you to type the project's name (or pass --yes); one repository needs no confirmation.
Usage: fugaro budget kill (--all | --repo [owner/name]) [--reason TEXT]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--all |
bool | false |
no | the whole project |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for kill |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--reason |
string | "" | no | why (recorded, shown by budget show and watch) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | one repository, given as owner/name (no value: this checkout's origin) |
--yes |
bool | false |
no | confirm without typing the project's name |
Subcommands:
This command has no subcommands.
fugaro budget preview
Estimate a batch's worst-case model spend against today's caps
Estimate what N runs of a recipe may cost at most, and how that compares with today's remaining daily caps. It is a ceiling, not a forecast: a run is bounded by the smaller of budget.per_run_usd and the recipe's most stages times the repository's agent.max_budget_usd.
That figure is the model ceiling and nothing else: a run also bills for the machine it asked for, and no budget key bounds compute at all -- the run's own timeout is the cap. So for every workflow the checkout defines the preview also prints a compute ceiling -- the workflow's own resources over its own timeouts.total, at this installation's compute prices -- and says out loud that it is NOT CAPPED, because for a run whose expensive half is a render on a big machine the model ceiling is not the worst case. The basis is timeouts.total and not a render step's own timeout: a render that overruns still burns the run's clock to the deadline. Without a price table for the installation's region the line names what is missing and prints no dollar figure, rather than $0.00.
When the repository's recorded runs of the last 30 days are at least 5, the preview also prints, clearly labelled typical:, what one run of the recipe usually costs: the mean recorded cost of each stage kind (on the model the checkout pins for it, with the recipe's role mapping applied as a run applies it), at the recipe's typical stage count -- one round of each loop the recipe and its round knobs leave in, the two fix stages sharing one mean -- over the runs of the window, whatever they ended as: a stage counts once it recorded a cost. A kind the window has no cost for on that model leaves the line out and names the model, rather than pricing the pinned model with what another one cost. Runs the figure cannot use are said to be left out, never counted as runs that cost nothing: a run on a subscription (agent.auth oauth), whose model_usd is notional rather than charged, a result.json that is missing or unreadable, and a record with no per-stage cost at all (one from before the runner kept it, or stages that all cost nothing).
The recipe resolves as it does for a run: the repository's .fugaro/recipes, the project's published recipes, then the catalog. The knobs come from the checkout's fugaro.yaml; without a checkout of the repository here, agent.max_budget_usd is unknown and only budget.per_run_usd bounds the figure, so with neither the preview says it is unbounded.
It reads the database's caps and today's counters (the Viewer role), and the repository's runs (the runs bucket, for the typical line). A recipe that is not in the checkout also reads the project's recipes from the runs bucket, as recipes ls does, which a plain project Viewer cannot read (the converge removes that access): not reading it costs the project layer, and the ceiling with it. The typical line's own read of the bucket is the one that costs the line and nothing else: a bucket it cannot read leaves the ceiling standing. It writes nothing.
Usage: fugaro budget preview --recipe NAME --runs N [--repo R]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for preview |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--recipe |
string | "" | yes | the recipe to preview (default, lint-fix, pick, premium, review-only, solo, standard, test-and-fix) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | the repository (owner/name); default: the checkout's origin |
--runs |
int | 0 |
yes | how many runs to estimate |
Subcommands:
This command has no subcommands.
fugaro budget prices
Show the effective model price table, offline
Show the model prices the budget accounts with: the table built into this fugaro, its source and the day it was last checked (a warning when that is over 90 days ago), with the selected project config's model_prices applied and marked local. A model a provider route claims is priced from the built-in provider price catalog instead: its CATALOG column says which tier and which end of that tier's range is charged, and the catalog has its own source, date and 30-day staleness warning. It never reaches the network.
Usage: fugaro budget prices
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for prices |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro budget resume
Clear a kill switch (budget admins)
Clear the project's kill switch (--all) or one repository's (--repo [owner/name]), recording who and when. --repo with no value means the repository this checkout belongs to, as it does for set. Asks you to type the project's name (or pass --yes): runs start again.
Usage: fugaro budget resume (--all | --repo [owner/name]) [--reason TEXT]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--all |
bool | false |
no | the whole project |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for resume |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--reason |
string | "" | no | why (recorded, shown by budget show and watch) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | one repository, given as owner/name (no value: this checkout's origin) |
--yes |
bool | false |
no | confirm without typing the project's name |
Subcommands:
This command has no subcommands.
fugaro budget set
Set a cap, the lease limit or the mode (budget admins)
Set caps in the project's budget database, with an ETag-guarded write that shows the old and the new value.
--global the project's daily and per-run caps; also takes --max-reserve and --mode --defaults the caps of every repository that has none of its own --repo [owner/name] one repository's caps; --repo with no value means the repository this checkout belongs to, which needs no owner/name at all
--max-reserve (the largest single lease) and --mode (observe, or enforce: caps bite) are project-wide, so they go with --global. Amounts are US dollars from 0 to 100000, and a per-run cap may not exceed the daily cap of the same scope. --clear removes the scope's caps.
--repo owner/name always works, from anywhere; the bare --repo is refused outside a checkout whose origin names a repository, and never stands for the project-wide caps. kill and resume take --repo the same way. preview needs no bare form: left out, --repo already means this checkout's repository. show is the one whose empty --repo is not the checkout (it means no repository filter), so it takes owner/name.
Raising a cap (setting one that was unset counts), or lowering the mode to observe, loosens what runs may spend, so it asks you to type the project's name (or pass --yes). Lowering needs no confirmation.
Usage: fugaro budget set (--global | --defaults | --repo [owner/name]) [--daily USD] [--per-run USD] [--max-reserve USD] [--mode observe|enforce] | --clear
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--clear |
bool | false |
no | remove the scope's caps |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--daily |
float64 | 0 |
no | the daily cap, in US dollars |
--defaults |
bool | false |
no | the default caps of repositories without their own |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
--global |
bool | false |
no | the project's own caps |
-h, --help |
bool | false |
no | help for set |
--max-reserve |
float64 | 0 |
no | the largest single lease, in US dollars (with --global) |
--mode |
string | "" | no | observe or enforce (with --global) |
--per-run |
float64 | 0 |
no | the per-run cap, in US dollars |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | one repository's caps, given as owner/name (no value: this checkout's origin) |
--yes |
bool | false |
no | confirm a raise without typing the project's name |
Subcommands:
This command has no subcommands.
fugaro budget show
Show caps, today's counters, kill switches, headroom and the runs in flight
Show the project's budget: the mode, the caps, today's (UTC) counted, spent and notional dollars, the headroom under the caps, the kill switches and the runs in flight. By default the global figures and the project config's repositories; --repo one repository; --all every repository the database knows. Notional is a subscription's list-price figure, never billed and never capped. Counted is spent plus what runs have reserved and not released.
Usage: fugaro budget show
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--all |
bool | false |
no | every repository in the database |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for show |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | only this repository (owner/name) |
Subcommands:
This command has no subcommands.
fugaro cancel
Cancel a run, letting the runner open a draft PR first
Cancel RUN (<repo-slug>/<run-id>, or a bare run ID).
cancel writes the run's cancel marker; the runner sees it, stops the current stage and finalizes a draft PR. If the execution is still in a stage after --grace, cancel stops it through Cloud Run. It never stops a run that is opening its PR (finalize) or writing back its cache: it waits up to 10 more minutes for finalize, and counts writeback as finalized. --grace is never shorter than the workflow's timeouts.finalize_reserve (5m when neither the run nor this checkout tells) plus 40s for the runner to notice the cancel. --now stops the execution at once (so it takes no --grace), without waiting for the draft PR, but still not mid-finalize.
Usage: fugaro cancel RUN
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
--grace |
duration | 3m0s |
no | how long to wait for the runner to finalize before cancelling the execution (at least the run's finalize reserve plus 40s) |
-h, --help |
bool | false |
no | help for cancel |
--json |
bool | false |
no | print the result as JSON |
--now |
bool | false |
no | cancel the execution at once, without waiting for a draft PR |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro completion
Generate the autocompletion script for the specified shell
Generate the autocompletion script for fugaro for the specified shell. See each sub-command's help for details on how to use the generated script.
Usage: fugaro completion
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for completion |
Subcommands:
fugaro completion bash-- Generate the autocompletion script for bashfugaro completion fish-- Generate the autocompletion script for fishfugaro completion powershell-- Generate the autocompletion script for powershellfugaro completion zsh-- Generate the autocompletion script for zsh
fugaro completion bash
Generate the autocompletion script for bash
Generate the autocompletion script for the bash shell.
This script depends on the 'bash-completion' package. If it is not installed already, you can install it via your OS's package manager.
To load completions in your current shell session:
source <(fugaro completion bash)To load completions for every new session, execute once:
Linux:
fugaro completion bash > /etc/bash_completion.d/fugaromacOS:
fugaro completion bash > $(brew --prefix)/etc/bash_completion.d/fugaroYou will need to start a new shell for this setup to take effect.
Usage: fugaro completion bash
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for bash |
--no-descriptions |
bool | false |
no | disable completion descriptions |
Subcommands:
This command has no subcommands.
fugaro completion fish
Generate the autocompletion script for fish
Generate the autocompletion script for the fish shell.
To load completions in your current shell session:
fugaro completion fish | sourceTo load completions for every new session, execute once:
fugaro completion fish > ~/.config/fish/completions/fugaro.fishYou will need to start a new shell for this setup to take effect.
Usage: fugaro completion fish
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for fish |
--no-descriptions |
bool | false |
no | disable completion descriptions |
Subcommands:
This command has no subcommands.
fugaro completion powershell
Generate the autocompletion script for powershell
Generate the autocompletion script for powershell.
To load completions in your current shell session:
fugaro completion powershell | Out-String | Invoke-ExpressionTo load completions for every new session, add the output of the above command to your powershell profile.
Usage: fugaro completion powershell
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for powershell |
--no-descriptions |
bool | false |
no | disable completion descriptions |
Subcommands:
This command has no subcommands.
fugaro completion zsh
Generate the autocompletion script for zsh
Generate the autocompletion script for the zsh shell.
If shell completion is not already enabled in your environment you will need to enable it. You can execute the following once:
echo "autoload -U compinit; compinit" >> ~/.zshrcTo load completions in your current shell session:
source <(fugaro completion zsh)To load completions for every new session, execute once:
Linux:
fugaro completion zsh > "${fpath[1]}/_fugaro"macOS:
fugaro completion zsh > $(brew --prefix)/share/zsh/site-functions/_fugaroYou will need to start a new shell for this setup to take effect.
Usage: fugaro completion zsh
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for zsh |
--no-descriptions |
bool | false |
no | disable completion descriptions |
Subcommands:
This command has no subcommands.
fugaro config
Work with fugaro.yaml
Usage: fugaro config
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for config |
Subcommands:
fugaro config example-- Print an annotated fugaro.yaml templatefugaro config init-- Write the minimal fugaro.yaml of a repository whose project publishes a project layerfugaro config layer-- Print the project layer published for this checkout's projectfugaro config list-- List the Fugaro installations this machine hasfugaro config publish-- Publish the project layer: defaults and profiles for every repository of the project (fugaro/project-layer.yaml in the runs bucket)fugaro config show-- Print the checkout's fugaro.yaml resolved over the project layer, with where each value comes from
fugaro config example
Print an annotated fugaro.yaml template
Usage: fugaro config example
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for example |
Subcommands:
This command has no subcommands.
fugaro config init
Write the minimal fugaro.yaml of a repository whose project publishes a project layer
Write the minimal fugaro.yaml (version, project, gcp_project) into this checkout, for a project that publishes a project layer. Non-interactive: without --yes it prints the file and exits 1 (a dry run), writing nothing. It never overwrites a fugaro.yaml, and writes nothing that does not resolve against the project layer. Unlike fugaro config publish, it never refuses in a coding-agent session: it writes a repository file, which still goes through a reviewed pull request, not a published, trusted object.
Usage: fugaro config init
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--base-branch |
string | "" | no | the repository's base branch, when it is not main |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for init |
--profile |
string | "" | no | the project layer's profile to use (default: its default_profile) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--yes |
bool | false |
no | write the file (without it, print it and exit 1 without writing) |
Subcommands:
This command has no subcommands.
fugaro config layer
Print the project layer published for this checkout's project
Usage: fugaro config layer
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for layer |
--json |
bool | false |
no | print machine-readable output |
Subcommands:
This command has no subcommands.
fugaro config list
List the Fugaro installations this machine has
List the project configs under $XDG_CONFIG_HOME/fugaro/projects (else ~/.config/fugaro/projects), with the GCP project and region of each and what is known about its published shared config.
This is a local read: it opens no bucket and needs no project selected, so it works outside a checkout and with no config at all (an empty list).
Usage: fugaro config list
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for list |
--json |
bool | false |
no | print machine-readable output |
Subcommands:
This command has no subcommands.
fugaro config publish
Publish the project layer: defaults and profiles for every repository of the project (fugaro/project-layer.yaml in the runs bucket)
Usage: fugaro config publish FILE
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--executable-changes |
bool | false |
no | allow a change to a profile's commands, image.apt or image.setup (they run as shell in every repository that takes the profile) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for publish |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro config show
Print the checkout's fugaro.yaml resolved over the project layer, with where each value comes from
Usage: fugaro config show
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for show |
--json |
bool | false |
no | print machine-readable output |
--offline |
bool | false |
no | never read the runs bucket: resolve against the cached project layer, if any |
--project-layer |
string | "" | no | resolve against this project layer file instead of the published one |
--workflow |
string | "" | no | show only this workflow's keys besides the top-level ones |
Subcommands:
This command has no subcommands.
fugaro diagnose
Explain how a run went: status, tests, review findings, the agent's last word, logs
Gather what is known about RUN (<repo-slug>/<run-id>, or a bare run ID): its status and reason, the last test run's failed and flaky tests, the last review's findings, the agent's final message, the newest log lines, its cost and its pull request. Everything printed is redacted of the credentials in this environment, on top of the runner's own redaction.
Usage: fugaro diagnose RUN
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for diagnose |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro doctor
Check that Fugaro is set up and ready, without changing anything
doctor only ever reads: the environment, Terraform, the local project config and its installation's billing and IAM policy (with a budget backend, who can sign sign-in tokens for it: warnings, never changes), the Fugaro plugin's wiring in .claude/settings.json, a checkout's fugaro.yaml and its stored secrets by name. With --check-github-app, in your own terminal, it also asks GitHub whether each GitHub App the config records is installed on its repository with the permissions Fugaro's runs ask for: that is the one thing that reads a secret's value (the App's private key, with your own credentials, held in memory only to sign, never printed), and it is refused in a coding agent's session. Otherwise it never prints a secret's value and never creates, enables or changes anything.
Inside a checkout whose project publishes a project layer (fugaro config publish), doctor also names which layer applies, flags a run that launched without it or on an older generation, a stale per-repository copy (the one Cloud Build and the daily image check read), and a workflow whose image was last built from settings it no longer resolves to: every one of these degrades with a note instead of failing when the bucket is unreachable.
--plugin checks only the plugin's wiring: offline, no credentials, safe for CI. --strict makes a stale, unpinned, foreign or unwired plugin fail the command; the informational states ("not installed", "cannot compare") never do, with or without --strict. A repository's CI runs fugaro doctor --plugin --strict.
With no local Fugaro installation configured, doctor says so and names fugaro setup as the fix, rather than guessing at a project.
Exit 1 when a check fails, with the one-line fix to run.
Usage: fugaro doctor [--json] [--plugin] [--strict]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--check-github-app |
bool | false |
no | also check each recorded GitHub App is installed with the permissions runs ask for: reads the App's private key from Secret Manager with your own credentials, in memory only, for one signed token (refused in a coding agent's session; GODEBUG=http2debug would print the token, so unset it) |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--dir |
string | . |
no | a directory in the checkout, for the plugin wiring |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for doctor |
--json |
bool | false |
no | print machine-readable output |
--plugin |
bool | false |
no | check only the plugin's wiring (offline, no credentials) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--strict |
bool | false |
no | fail on a stale, unpinned, foreign or unwired plugin (CI mode) |
Subcommands:
This command has no subcommands.
fugaro help
Help about any command
Help provides help for any command in the application. Simply type fugaro help [path to command] for full details.
Usage: fugaro help [command]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for help |
Subcommands:
This command has no subcommands.
fugaro image
Build and inspect a workflow's derived container image
Usage: fugaro image
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for image |
Subcommands:
fugaro image build-- Build the derived image with Cloud Build; --local builds it with local Docker and smoke-tests itfugaro image check-- Decide whether each workflow's image needs a rebuild (the daily check; locally it only prints the decision)fugaro image refresh-- Move a repository onto this release's base image: pin it, point the daily image check job at it, rebuild what is stalefugaro image render-- Print the Dockerfile that builds the workflow's derived imagefugaro image status-- Show each workflow's image: when it was built and from what, and its last daily check
fugaro image build
Build the derived image with Cloud Build; --local builds it with local Docker and smoke-tests it
Build the workflow's derived image.
Without --local, Cloud Build builds it from the repository's base branch as the repository's build account (cloning with its bitbucket-token, or a read-only token its GitHub App mints) and pushes it to the repository's own registry, which fugaro update --repo creates. It pushes a candidate, smoke-tests it without network, and only then points latest at it and records what it was built from, unless a newer build is already recorded. Run it from the repository's checkout: the checkout's fugaro.yaml and origin say what to build.
A Cloud Build is billable, so it asks for the project's name typed at a real terminal: --json, a pipe and a coding agent's session never confirm it (it prints the one line to run in your own terminal window and exits 1). --local builds with your own Docker and costs nothing in the cloud.
Usage: fugaro image build
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--base |
string | "" | no | base image (default: for a Cloud Build build the local config's base_images entry for the workflow's base, else the published fugaro-base matching this fugaro version) |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for build |
--json |
bool | false |
no | print machine-readable output (--local only: a Cloud Build is never submitted with --json, nobody can type its confirmation) |
--local |
bool | false |
no | build with the local Docker daemon from the checkout you are in |
--no-smoke |
bool | false |
no | skip the smoke test of the built image (on Cloud Build, latest is then promoted unsmoked) |
--no-wait |
bool | false |
no | submit the Cloud Build build and return without waiting for it |
--platform |
string | linux/amd64 |
no | image platform; Cloud Run runs linux/amd64 |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | owner/name of the repository to build with Cloud Build (default: the checkout's origin, which it must match) |
--tag |
string | "" | no | tag for the built image (default fugaro-<dir>-<workflow>:local) |
--workflow |
string | "" | no | workflow to build; optional when fugaro.yaml defines one |
Subcommands:
This command has no subcommands.
fugaro image check
Decide whether each workflow's image needs a rebuild (the daily check; locally it only prints the decision)
Evaluate the rebuild triggers of the repository's workflows against the head of its base branch: a blobless clone, the build record in the runs bucket, and the base image's digest.
Run from a checkout, it uses your own git access and ADC and only prints each workflow's decision: it never submits a build (--dry-run is accepted, and is what it always does). Start a rebuild with fugaro image build.
With --job, as the repository's daily check job runs it (it refuses to submit unless CLOUD_RUN_JOB or CLOUD_RUN_EXECUTION is set, as Cloud Run sets them, and in a coding agent's session; --dry-run is always allowed), it reads the job's spec from FUGARO_CHECK_SPEC, submits a Cloud Build rebuild when a trigger fires (not with --dry-run), writes builds/<slug>/<workflow>/check.json, and logs one JSON line per workflow. It exits 2 when the check itself failed.
Usage: fugaro image check
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--dry-run |
bool | false |
no | never submit a build (locally the check never does anyway) |
--force |
bool | false |
no | decide rebuild whatever the triggers say (with --job: a build is submitted) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for check |
--job |
bool | false |
no | run as the repository's daily check job (reads FUGARO_CHECK_SPEC; submits rebuilds) |
--json |
bool | false |
no | print machine-readable output (locally; the job always logs JSON) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--workflow |
string | "" | no | check only this workflow |
Subcommands:
This command has no subcommands.
fugaro image refresh
Move a repository onto this release's base image: pin it, point the daily image check job at it, rebuild what is stale
Run it in the checkout of an onboarded repository, in your own terminal window (or with --yes, unattended: see below).
It prints the whole plan first, then, each step with its own confirmation: (2) resolves this release's base image of each selected workflow's kind at its -pinned tag, verifies its cosign signature, reads the digest back through the installation's remote repository and pins base_images.<kind> to it, as fugaro update --base does (nothing is copied); (3) points the repository's daily image check job at it (its image and FUGARO_CHECK_SPEC's base images) through the Cloud Run Admin API, with no Terraform; (4) rebuilds each selected workflow whose build record says it was built from another base, or that has no build record or one that cannot be read (billable: the project's name typed for each, or --yes); (5) names fugaro update --anchor when fugaro.yaml lacks gcp_project.
A base_images entry that is neither this release's pin nor a release image an earlier fugaro copied (a development or hand-pushed image) stops it before anything changes, with or without --yes: remove the entry from the local config, then rerun. It never writes fugaro.yaml, never onboards a repository and never runs Terraform. A coding agent's session is refused, --yes included (there is still no --json or --plan-only to get around that). A run that stops says which steps finished and what to rerun, --yes included when it was given; a rerun skips what is done. Exit codes: 0 done, 1 a refusal or a confirmation not given, 2 a cloud failure.
Unattended use: pass --yes to run it from CI or a script, with no terminal. It confirms every step, the base pin, the check-job update and EACH billable build, with no cap on how many builds run: read the printed plan's build count first. --yes does not cover a coding agent's session (refused, same as without it) or a custom, dev or hand-pushed base image (still refused with the one-line fix); there is still no --json or --plan-only.
Usage: fugaro image refresh
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--expect-digest |
stringArray | [] |
no | cross-check the digest of a base image's release signature, KIND=sha256:<hex>, as for the converge (repeatable) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for refresh |
--image-source |
string | "" | no | the registry and owner the release base images come from, as for the converge (default ghcr.io/dimipaun) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | owner/name of the repository; it must be this checkout's origin (refresh reads fugaro.yaml from the checkout) |
--workflow |
stringArray | [] |
no | a workflow to refresh (repeatable; default: every workflow in fugaro.yaml) |
--yes |
bool | false |
no | confirm every step without asking (the base copy, the check-job update and each billable build, with no cap on how many run), and without a terminal: for CI or a script. The plan is still printed first. Never confirmed in a coding agent's session (CLAUDECODE and the like): nothing is applied there, --yes included. Without --yes nothing changes: a real terminal and the typed confirmations are still required, as always |
Subcommands:
This command has no subcommands.
fugaro image render
Print the Dockerfile that builds the workflow's derived image
Print the Dockerfile that builds the workflow's derived image.
Unlike other fugaro commands, this one has no --json form: its output is the Dockerfile itself, not a report about one.
Usage: fugaro image render
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for render |
--workflow |
string | "" | no | workflow to render; optional when fugaro.yaml defines one |
Subcommands:
This command has no subcommands.
fugaro image status
Show each workflow's image: when it was built and from what, and its last daily check
For each workflow of the local config's repositories (or --repo's), print what the runs bucket records: the image's build time and age, source commit and base digest (builds/<slug>/<workflow>/image.json), and the last daily check's time, decision and reasons, and the last rebuild's status (check.json).
Usage: fugaro image status
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for status |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | only this repository (owner/name, as the local config's repos has it) |
Subcommands:
This command has no subcommands.
fugaro logs
Print a run's logs from Cloud Logging
Print the logs of RUN (<repo-slug>/<run-id>, or a bare run ID), oldest first.
With -f, keep printing until the execution ends and its logs settle. Every line is redacted of the credentials in this environment, on top of the runner's own redaction.
Usage: fugaro logs RUN
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
-f, --follow |
bool | false |
no | keep printing new entries until the execution ends |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for logs |
--json |
bool | false |
no | print one JSON object per entry |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--url |
bool | false |
no | print the execution's Cloud console link instead of the logs |
Subcommands:
This command has no subcommands.
fugaro managed
Act on a managed project (a project created by fugaro with the coding agent's refusal removed)
Act on a managed project: one Fugaro created with the coding agent's confirmation refusal removed, where what may be applied is decided by a deterministic gate over the saved plan rather than by a prompt.
This is not fugaro project (the project's own configuration) and not fugaro setup (which creates and re-installs an installation): a managed project's agent-authored root is applied by fugaro managed apply.
Usage: fugaro managed
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for managed |
Subcommands:
fugaro managed apply-- Apply the agent-authored Terraform root of a managed project, as the deployer accountfugaro managed flag-- Flag an existing GCP project as managed (the project's owner)
fugaro managed apply
Apply the agent-authored Terraform root of a managed project, as the deployer account
Apply the agent-authored Terraform root ROOT of a managed project.
ROOT is a directory in this repository's checkout (the checkout whose fugaro.yaml names the project). Its files are copied into this command's own workdir — never run in place, so terraform's plan file, lock file and provider directory are not written beside the configuration under review — the state backend is set to the project's own managed state bucket, the root is planned into a saved plan file, the plan is gated against the project's managed allowlist and against the addresses the project's OWNER approved, and the saved plan file is applied as the project's deployer service account.
An address this command may delete or replace is never one of this command's arguments: an approval lives in the owner's object at gs://<runs bucket>/fugaro/allow-delete.json, written with the operator's own credentials by fugaro allow-delete. This command registers no flag for one, so there is no way to pass one.
The refusal this command's apply does not carry is the coding agent's: in a managed project a coding agent's session applies cloud changes with no human prompt, and what replaces the prompt is the gate (a refused plan is not applied), the marker (an unreadable one is not an apply), the owner's list (an address the owner did not approve is refused) and the deployer account (which holds no project-level IAM permission and cannot write the runs bucket). None of the four is a boundary against a session that goes around this program.
The prompt comes back whenever the whole-project inventory does not clear the project: before anything is planned, this command reads every resource of the GCP project (Cloud Asset, with the operator's own credential) and compares it with what the installation's Terraform states account for. A resource nothing accounts for, or an inventory that cannot be read, keeps this run's confirmation: a coding agent's session is refused and a person is asked, with the reason printed first. Nothing is halted and nothing is deleted.
Usage: fugaro managed apply ROOT
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for apply |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro managed flag
Flag an existing GCP project as managed (the project's owner)
Flag an existing GCP project PROJECT_ID as managed, recording the managed marker in that project's own runs bucket.
This is how a project Fugaro did not create becomes managed: the marker is what tells a later run that this project's applies may skip the typed confirmation, and it is normally written by the run that created the project (fugaro setup --create-project --managed). Flagging is the after-the-fact way, answered by the owner on 2026-10-16 (design D58).
Run it in your own terminal, as an operator, with your own credentials, and type the GCP project ID it asks for. A coding agent's session is refused, and nothing stands in for the typed ID — not --yes, not --non-interactive, not a pipe.
PROJECT_ID must be the exact GCP project ID of the installation selected by --project, --config or the checkout: one invocation names one project, and there is no bulk form, no wildcard and no prefix.
It records two things in gs://<runs bucket>/fugaro/managed.json: that this project is managed, and the monthly budget amount and currency the owner states with --budget and --budget-currency. The amount is required, with no default (D64), because the marker's amount is what the apply-time budget read opens the gate on: a marked project that records no amount is refused by every managed apply rather than applied without a budget control. The amount is the budget ALERT amount the installation's Terraform creates and nothing else — this command does not create or change a budget, and it makes no billing call.
It writes BOTH marks a managed project carries, in one step: that object and the label fugaro_managed=true on the GCP project itself (Task 3.0). The read requires both — the label is what a project can be narrowed by, and a project without it is not managed whatever its runs bucket holds — so writing the object alone would leave this project exactly as unmanaged as it was. The label is written on the project, by the account running this command, which is why the account needs resourcemanager.projects.update on it; the project's other labels are kept. A project that already carries that key with another value is refused rather than overwritten — the label someone else put there is a statement, not an empty slot — and the object written first is not taken back, so that refusal says which half is there and which is missing.
What flagging gives up, stated before it writes: the marker is what turns the typed confirmation off (D55), so from this project's next apply on, the deterministic gate, the whole-project inventory, the owner-written delete list (fugaro allow-delete) and the recorded budget are what stand in the confirmation's place — and a coding agent's session can apply a plan the gate admitted with no human prompt.
What it does not do: it is not a boundary against a session that goes around this program. A coding agent's session holds the operator's credentials, can write this object directly with gcloud storage cp, and can unset its own marker and run this command; SECURITY.md records the wider Owner/Editor bypass. The refusal below is a speed bump against an agent that uses the program, not a wall against one that goes around it.
A project that already records an amount is refused: the amount is the owner's decision at the time it was taken, and this command adds a budget rather than editing one. The one object it does replace is a version-1 creation fact — what fugaro setup --create-project without --managed leaves, and the state the managed apply refuses for having no amount recorded. What it replaced is said in the output, and the write is conditioned on the object it read, so nothing is overwritten blind.
Usage: fugaro managed flag PROJECT_ID
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--budget |
int64 | 0 |
no | the monthly budget alert amount to record, in whole units of --budget-currency (required) |
--budget-currency |
string | "" | no | the currency --budget is in, three uppercase letters such as USD (required) |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for flag |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro plan
Read a plan's graph artifact
Usage: fugaro plan
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for plan |
Subcommands:
fugaro plan graph-- Print a plan's graph: its tasks, their dependencies and their footprints
fugaro plan graph
Print a plan's graph: its tasks, their dependencies and their footprints
Print the graph artifact written beside a plan.
The artifact is <plan>.graph.json — for docs/plans/foo.md it is
docs/plans/foo.graph.json. With no --plan, the one graph artifact under
docs/plans/ is read; more than one is refused rather than guessed at.
A graph this build does not understand is refused rather than rendered: a future schema version, a malformed document, an edge to a node that is not there, or a cycle. This is a local read and it writes nothing.
Usage: fugaro plan graph
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for graph |
--json |
bool | false |
no | print machine-readable output |
--plan |
string | "" | no | the plan document the graph sits beside (default: the one graph artifact under docs/plans) |
Subcommands:
This command has no subcommands.
fugaro project
The project's policy, its allow-list and the repositories enrolled
Usage: fugaro project
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for project |
Subcommands:
fugaro project policy-- The project's published policy (config/policy/shared)fugaro project repos-- The project's allow-list: which repositories may runfugaro project show-- Show the effective project: caps, policy, allow-list, repositories running nowfugaro project sync-- Offer the GitHub App's installed repositories that the allow-list does not admit
fugaro project policy
The project's published policy (config/policy/shared)
Usage: fugaro project policy
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for policy |
Subcommands:
fugaro project policy publish-- Publish the project's policy from the operator's config (budget admins)fugaro project policy show-- Show the published policy
fugaro project policy publish
Publish the project's policy from the operator's config (budget admins)
Build the project's policy from this machine's project config — the budget block, the providers (their secrets by NAME, never a value), the model_prices overrides and the allow-list — and write it to config/policy/shared with an ETag-guarded write. The diff follows the write: it is printed once the node holds the policy, and a write that failed prints no diff — the node is as it was, and the command says so. From then on the node is the ceiling for every key it names, and a key it leaves out keeps the value the job's environment was deployed with.
Publishing refuses without the rules marker (config/limits/policyRules): a policy published before the rules are deployed is one the runs it bounds cannot read, so run fugaro update --firebase-project with a Fugaro that deploys them first. It also refuses a node written by a newer Fugaro.
allow_repos is seeded from this machine's repos: map and from the shared config's repository list, and only when the node is absent or --seed-repos is passed: a later publish never re-adds a name an operator removed. It is never seeded from the bucket's runs/<slug>/ prefixes, which every run of a profile can write.
--delete removes the policy (the children first, the shared node last, so a launch mid-delete still sees the policy and keeps its tighter ceiling) and puts the project back on the ceiling its jobs' environments carry. It goes through the same rules-marker gate as a publish, refuses without --yes while runs are in flight, and asks you to type the project's name otherwise. The config/policy/repos children are removed too, shared node or not: a delete that failed on the shared node leaves them behind, and this is what clears them.
Each repository an account a profile names admits also gets a child under config/policy/repos/$slug, holding the NAMES of its admitted accounts and nothing else: the accounts published are the ones some profile names, qualified by that profile's provider, so an account this config defines but no profile names admits nothing a run could read. The children are narrowed before the shared node and widened after it, so a publish that stops between the two writes leaves the installation tighter than the config asked, never looser. When the node this publish writes carries a member an older Fugaro refuses whole — a credentials block, or routing.claude.via: cascade — the diff warns: older launchers (and, for the cascade, older runner images) stop until they are upgraded.
routing.claude is written where the operator writes it: this config. A publish refuses to drop an active route the config does not account for, and refuses to turn the credentials cascade off — a node carrying routing.claude.via: cascade with a config that names no Claude switch is refused with its own sentence, because the cascade is not a route: it decides which credential carries a Claude call, never where the call goes, and it is what hands a run the project's other credentials. A config that writes a routing block naming no Claude switch in the same state is refused too. --remove-routing is how the operator says the block goes away on purpose.
Usage: fugaro project policy publish [--seed-repos] [--delete] [--yes] [--remove-routing]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--delete |
bool | false |
no | remove the published policy (project-centric mode off again) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for publish |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--remove-routing |
bool | false |
no | drop the published policy's routing block on purpose (an active route stops being taken) |
--seed-repos |
bool | false |
no | seed allow_repos from the operator's repositories again |
--yes |
bool | false |
no | confirm the deletion without typing the project's name |
Subcommands:
This command has no subcommands.
fugaro project policy show
Show the published policy
Usage: fugaro project policy show [--json]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for show |
--json |
bool | false |
no | machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro project repos
The project's allow-list: which repositories may run
Usage: fugaro project repos
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for repos |
Subcommands:
fugaro project repos add-- Enroll a repository: add it to the policy's allow-listfugaro project repos ls-- List the allow-list and the repositories that have run herefugaro project repos rm-- Un-enroll a repository: remove it from the allow-list
fugaro project repos add
Enroll a repository: add it to the policy's allow-list
Add a canonical repository (github/acme/app, bitbucket/acme/*) to the published policy's allow_repos, through the same ETag-guarded write the publisher uses, and print the change. A bare owner/name takes its provider from this machine's project config, and * is the list's own entry for every repository: it is written as it is. Only allow_repos changes.
Usage: fugaro project repos add <provider/owner/name | owner/name | *>
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for add |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro project repos ls
List the allow-list and the repositories that have run here
Usage: fugaro project repos ls
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for ls |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro project repos rm
Un-enroll a repository: remove it from the allow-list
Remove an entry from the published policy's allow_repos. Removing an allowed repository stops its runs — a run of a repository the list does not admit is refused before it mints a git token — unless another entry on the list still admits it, which is the case a pattern makes (github/acme/app stays admitted while github/acme/* is there); the confirmation says which of the two it is. Removing * refuses every repository the rest of the list does not admit. So it asks you to type the project's name, and while a run is in flight --yes alone is not enough.
Usage: fugaro project repos rm <provider/owner/name | owner/name | *>
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for rm |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--yes |
bool | false |
no | confirm the removal without typing the project's name (not while a run is in flight) |
Subcommands:
This command has no subcommands.
fugaro project show
Show the effective project: caps, policy, allow-list, repositories running now
Print the effective project: the caps the installation's nodes carry (global, defaults and per repository), the published policy, the allow-list with where each entry came from, and the repositories the run registry holds. The registry holds the runs in flight, so that list is what is running now — an empty one is nothing running, not nothing that has ever run. The last pair is what an operator needs: repositories that are running and are not on the allow-list (their next run is refused until 'fugaro project repos add'), and allow-list entries nothing is running now.
Usage: fugaro project show [--json]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for show |
--json |
bool | false |
no | machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro project sync
Offer the GitHub App's installed repositories that the allow-list does not admit
Ask GitHub which repositories the project's GitHub App is installed on (the
App API, with the App's own credentials) and offer the ones the published
allow_repos does not admit, as one list confirmed once. The accepted list is
written through the same ETag-guarded write project repos add uses; entries
are only ever added, so a sync never un-enrolls a repository — including one
the App is not installed on at all (another provider's, or one whose
installation was removed). A repository the list already admits, a pattern
included, is not offered: its runs are admitted already.
Reading the App's private key is --github-app-key: without it, nothing is read. Under it the key is read from the project's github-app-key secret with your own credentials and held in memory only to sign the App's 9-minute JWT (never printed, never passed as an argument, never in an error), and the flag is refused in a coding agent's session. The App ID is a number, not a secret: --github-app-id, or the one this machine's config already holds.
Usage: fugaro project sync [--github-app-id <id>] [--github-app-key] [--yes]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
--github-app-id |
string | "" | no | the GitHub App's ID (a number, not a secret); default: the one this machine's config holds |
--github-app-key |
bool | false |
no | read the project's GitHub App private key from Secret Manager to ask GitHub (your own credentials; refused in a coding agent's session) |
-h, --help |
bool | false |
no | help for sync |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--yes |
bool | false |
no | confirm the batch without typing the project's name |
Subcommands:
This command has no subcommands.
fugaro recipes
List, show, validate and publish recipes, the task loop a run follows after implement
A recipe is found by name in .fugaro/recipes/NAME.yaml in the repository, then in the project's fugaro/recipes/NAME.yaml in the runs bucket, then in the catalog (default, lint-fix, pick, premium, review-only, solo, standard, test-and-fix). See docs/recipes.md.
Usage: fugaro recipes
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for recipes |
Subcommands:
fugaro recipes ls-- List the recipes of this checkout, the project and the catalog, and which one wins for each namefugaro recipes publish-- Publish a recipe to the project, for every repository of it (fugaro/recipes/NAME.yaml in the runs bucket)fugaro recipes show-- Show the recipe a run would get for NAME, and the layer it comes fromfugaro recipes validate-- Check a recipe file (no cloud access)
fugaro recipes ls
List the recipes of this checkout, the project and the catalog, and which one wins for each name
Usage: fugaro recipes ls
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for ls |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--verbose |
bool | false |
no | also print each recipe's use_when and steps |
Subcommands:
This command has no subcommands.
fugaro recipes publish
Publish a recipe to the project, for every repository of it (fugaro/recipes/NAME.yaml in the runs bucket)
Usage: fugaro recipes publish FILE
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for publish |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro recipes show
Show the recipe a run would get for NAME, and the layer it comes from
Usage: fugaro recipes show NAME
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for show |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro recipes validate
Check a recipe file (no cloud access)
Usage: fugaro recipes validate FILE
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for validate |
--json |
bool | false |
no | print machine-readable output |
Subcommands:
This command has no subcommands.
fugaro report
Report what the project spent, by day, week, month, year, repository, model or person
Report model spend from the project's spend history.
Finished days are read from the spendDaily documents in the project's Firebase Firestore (you need roles/datastore.viewer on the Firebase project, which launchers, operators and budget admins have). Today, yesterday and any day the daily job has not archived yet are computed live from the budget database and marked (partial). --since and --until are UTC dates (YYYY-MM-DD); --since also takes Nd, the last N days up to --until (default 30d); --until defaults to today.
--by day|week|month|year groups in time; weeks are ISO weeks in UTC, starting on
Monday (2026-W40). --by repo|model|person groups across the range. Dollars are
exact (integer micro-dollars). Model $, NOTIONAL~ (a subscription's list-price
figure, never billed) and COMPUTE $ are separate columns and never summed;
compute reads n/a when no run's compute was estimated. A person is the stored
requester address; unknown is spend, and runs, with no requester recorded.
By model, a subscription model's dollars are notional (priced from its tokens,
so they can differ slightly from the run's recorded notional total).
--csv writes RFC 4180 with spreadsheet-safe cells (a cell starting with = + - @ is prefixed with '). --json prints {project, source, degraded, by, since, until, weeks, rows[{key, start, end, partial, model_micros, model_usd, notional_micros, notional_usd, compute_micros, compute_usd, compute_estimated, run_hours, runs, calls, tokens}], totals, warnings}; *_usd are exact decimal strings and null means n/a or not recorded for that breakdown.
A project without Firestore history says so and shows run-record totals instead (from the runs bucket, not budget history).
Usage: fugaro report
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--by |
string | day |
no | group by day, week, month, year, repo, model or person |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--csv |
bool | false |
no | print CSV (RFC 4180) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for report |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | only this repository (owner/name) |
--since |
string | 30d |
no | first day: YYYY-MM-DD (UTC) or Nd, the last N days |
--until |
string | "" | no | last day, YYYY-MM-DD (UTC; default today) |
Subcommands:
This command has no subcommands.
fugaro restore
Rebuild a managed project from zero, into a new GCP project ID, and print what is not restored
Rebuild a managed project from zero into a NEW GCP project ID.
A managed project is one fugaro created, with a marker and an owner-written delete list. When it is lost — deleted, or closed — its ID stays reserved for about thirty days, so this is a restore into a new project:
- NEW_PROJECT_ID is the GCP project the installation is rebuilt in. It is created through the same path fugaro setup --create-project --managed uses, which is also what re-marks the project as managed and re-creates the deployer account with the rest of the installation, so neither is a separate step here. The repository's gcp_project: line is moved to it, so teammates find the shared config again.
- ROOT is the repository's agent-authored Terraform root, in the checkout whose fugaro.yaml names the project. It is applied from zero through the SAME path fugaro managed apply runs — the managed allowlist, the deterministic gate over the saved plan, the owner's delete list, and the deployer account of D75 — into the dedicated state bucket the new project was created with. No prior state is read: the state lived in the project that was lost.
The OLD project's own creation fact is read whenever the old project can still be read: a project that is not managed is refused, whatever flags are given, and a managed one gives the monthly budget amount unless --budget and --budget-currency are given. When the old project cannot be read (deleted, closed, not yours to read) the restore proceeds only on --budget and --budget-currency. The billing account is always yours to give: the creation fact is not a credential and records none.
NEW_PROJECT_ID must not exist: an existing project is refused, never adopted. If the creation fails or does not end in a project this run created and marked, the local project config file is put back as it was and the restore can be run again; what the creation did in the cloud (the project, its billing link, its state bucket, the installation's resources, any secrets) is not undone, and the message says so.
Every step is money or permanent, so the project's name is typed at a real terminal, and there is no --yes, no --non-interactive and no address argument. The command is refused in a coding agent's session.
It ends by printing what was NOT restored, as a list: the runs that were in flight and their counters, the spend history and the kill-switch state, the Firestore and RTDB application data, the Firestore database's location (which is permanent and can never be changed), every secret value, the plan files that were never stored, and the owner-written delete list — fugaro/allow-delete.json is not carried across and nothing here re-creates it, so until the owner writes it again with fugaro allow-delete every delete and replace in the new project is refused (D74). The project layer and the project's recipes are not held by the repository and are not re-published: the command names them and the one command that publishes each. The deployer account is the one thing that is re-created rather than lost, and the output says so.
Usage: fugaro restore NEW_PROJECT_ID ROOT
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--billing-account |
string | "" | no | the billing account the new project is linked to (required: the creation fact records the amount and no account) |
--budget |
int64 | 0 |
no | the new project's monthly budget amount, in whole units of --budget-currency (default: the amount the OLD project's creation fact records) |
--budget-currency |
string | "" | no | the budget's currency, such as USD (travels with --budget) |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--display-name |
string | "" | no | with the creation: the new project's display name (default: its ID) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for restore |
--parent |
string | "" | no | with the creation: organizations/<number> or folders/<number> to create the project under (default: no parent; an organization is never guessed) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
Subcommands:
This command has no subcommands.
fugaro run
Launch a task in the cloud; it always ends with a PR
Launch a task in the cloud. The task is TEXT or --task-file (- for stdin).
A repeated --run-id reports the existing launch instead of starting another, so a caller that is unsure whether its launch went through can simply repeat it. --retry RUN launches a run whose task was stored but never started.
--pr N continues Fugaro's pull request N: the run acts on the PR's review comments by the authors fugaro.yaml's followup.trusted lists, on the PR's own branch, with the base branch and workflow of the runs before it. TEXT, or --task-file, is optional then, and adds instructions.
--recipe NAME --pr N, NAME naming a mode: review recipe such as review-only or pick, reviews any open pull request of the repository instead (not only Fugaro's own) and never pushes or opens one; repeat --pr (2 to 4 times) for pick, which compares them. TEXT, or --task-file, is optional then too, and adds instructions to the review.
--attempts N (2 to 4) launches N independent runs of the same task as a best-of-N batch, under one batch label (bestof-<first run id> unless --batch is given); once they have all opened a pull request, compare them with fugaro run --recipe pick. It takes no --pr, --run-id or --retry.
--title TEXT names the run: one line, at most 100 characters. It is what fugaro watch and runs ls list the run by, and the title (with the body's first heading) of the pull request the run opens when the agent writes no pr.md of its own. Without it the run is named by the task's first line, so briefs that start with the same preamble all read alike. A follow-up (--pr) keeps its run's title unless --title is given, and --retry takes none (the stored task keeps its own).
Usage: fugaro run [TEXT]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--attach |
stringArray | [] |
no | attach a file to the run: repeatable, uploaded to the run's own inputs/ and downloaded by a mode: artifact run into the checkout's inputs/ (needs a mode: artifact recipe; refused on a run ID that already has a task) |
--attempts |
int | 0 |
no | launch N (2 to 4) independent runs of the same task, workflow, ref and recipe as a best-of-N batch (bestof-<first run id> unless --batch is given); refused with --pr, --run-id, --retry or a review-mode recipe |
--batch |
string | "" | no | batch label, to group runs in fugaro runs ls |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for run |
--json |
bool | false |
no | print machine-readable output |
--no-budget-check |
bool | false |
no | skip the launch pre-check of the budget (kill switches, missing caps, no headroom); the run is held to the same limits when it starts |
--pr |
intSlice | [] |
no | continue Fugaro PR N: act on its trusted review comments (TEXT adds instructions); with a mode: review --recipe, review PR N instead (repeatable, 1 to 4, any open PR) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--recipe |
string | "" | no | the recipe (task loop) to run: .fugaro/recipes/NAME.yaml, the project's, or the catalog's (default, lint-fix, pick, premium, review-only, solo, standard, test-and-fix); default: agent.recipe in fugaro.yaml, else default; a follow-up (--pr) keeps its previous run's |
--ref |
string | "" | no | base branch or ref (default: the repo's base_branch) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | repository as owner/name (default: this checkout's origin) |
--retry |
string | "" | no | launch the stored task of RUN (<repo-slug>/<run-id> or a run ID) that never started |
--run-id |
string | "" | no | run ID to use; repeating one reports its launch instead of starting another |
--task-file |
string | "" | no | read the task from this file, or - for stdin |
--title |
string | "" | no | the run's title, one line: what fugaro watch and runs ls list the run by, and the pull request's title unless the agent wrote its own pr.md (default: the task's first line); a follow-up (--pr) keeps its run's title unless this is given |
--token |
string | "" | no | named Claude account (claude_accounts in the local config) this run uses, for a workflow whose agent.auth is oauth; default: agent.oauth_token in fugaro.yaml, else the repository's default account; a follow-up (--pr) keeps its previous run's account unless this is given explicitly, which overrides it (checked the same way as a first run's) |
--total-timeout |
string | "" | no | override the workflow's timeouts.total for this run, such as 45m |
--workflow |
string | "" | no | workflow to run (default: the repo's only workflow) |
Subcommands:
This command has no subcommands.
fugaro runs
List and inspect runs
Usage: fugaro runs
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for runs |
Subcommands:
fugaro runs ls-- List runs with their status, stage, cost and PRfugaro runs stats-- Aggregate run records by the person who started each run
fugaro runs ls
List runs with their status, stage, cost and PR
List runs, newest first, joining the runs bucket with what the backend knows.
By default ls shows the last 7 days of the local config's repositories (every repository in the bucket when the config lists none). A run shows as succeeded only when its result.json says so; an execution that ended without finalizing is an infra_error.
--pr N lists the runs on pull request N of one repository (the first run and its follow-ups), over the last 90d unless --since says otherwise; the totals line is then the PR's total cost.
Usage: fugaro runs ls
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--all |
bool | false |
no | every repository in the runs bucket |
--batch |
string | "" | no | only runs of this batch |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for ls |
--json |
bool | false |
no | print machine-readable output |
--mine |
bool | false |
no | only runs you requested |
--pr |
int | 0 |
no | only runs on this pull request (needs one repository; --since defaults to 90d) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | only this repository (owner/name) |
--since |
string | 7d |
no | only runs started within this long (7d, 36h, 90m; 0 for all) |
--watch |
bool | false |
no | redraw until every run has settled |
Subcommands:
This command has no subcommands.
fugaro runs stats
Aggregate run records by the person who started each run
Count the runs one installation's records hold, and what they cost, grouped by the person who started each one: how many jobs an identity began, how they ended, what they spent, and a total row.
The numbers come from the run records, not from the budget database: each run's launch.json carries the launcher it recorded at launch, and its result.json the outcome and the settled cost. Nothing else is read, no counter is consulted, and nothing is written.
Attribution, as the records themselves state it:
- A follow-up (fugaro run --pr) belongs to the launcher of that follow-up: the identity is the one the follow-up's own launch recorded.
- An automated launch -- a service account, a CI runner -- appears as its own identity, exactly as it recorded itself; it is never folded into a person's.
- A run whose launch recorded no launcher is grouped as 'unknown'. It is never guessed from the run's task, its record or the account it ran under.
- Dollars are never added across currencies: a row is one user and one currency, and a total covers one currency. Every cost recorded today is in USD.
- The window is UTC days like the rest of the CLI. A run is counted on the day the bucket's run IDs place its start, so the window and the runs in it agree with runs ls.
The money is model dollars, counted the way the budget screens count them. COUNTED $ is the model spend that counts toward the caps (a run on an API key or Vertex), and NOTIONAL $ the model spend of a run on a subscription (agent.auth oauth), which counts toward the plan's limits and is no one's bill: they are separate columns and are never summed. Compute is not attributed to a person: no run's compute is, and the budget database's own person view leaves it out too. AVG $/RUN is COUNTED $ over COUNTED RUNS, the runs that settled a real-dollar cost; a notional run, a run with no readable record and a record from before the cost breakdown existed are none of them averaged in as a run that cost nothing.
Who sees whom. An operator of the installation -- the identity the local config's user: (or git config user.email) names, listed in its terraform.operators, the list fugaro doctor's runs-bucket-iam check reads -- sees every user. Anyone else sees their own row alone, and --all-users asks for the whole table. An installation that names no operators (one from before the 0.7.0 hardening, say) places nobody, and the view then stays private: the default is never the wider one. Whose numbers a table shows is printed above it.
A private view is the caller's own row. A caller whose identity cannot be told at all -- the local config names nobody, and git config user.email answers nothing -- is refused, never quietly widened: the error says so, and names --all-users. An identity with no key of its own because nothing printable is left of it (a pasted zero-width character, say) is shown no row instead: the table is empty, and its view line says the CLI cannot tell who you are. A row keyed 'unknown' is every run of the window that recorded no launcher -- never one person's -- so it is not shown as the caller's own either, and a note says so.
The launcher text is what a launcher wrote and is read for nothing else: it is sanitised and size-capped before it is printed, and it authorises and admits nothing. Two identities that differ only in what the sanitising drops -- an invisible character a paste left in one of them, say -- or only past the cap are one key and one row: the row is the key, not the person. A private view is not read off that key. It holds the runs whose launch recorded your identity itself -- the identity fugaro run writes to launch.json at launch, not the requested_by that runs ls --mine compares -- so someone whose identity merely sanitises to the same text is never counted in it and your own row can be smaller than that key's row in the full table.
A window can hold every run of every repository in the bucket, so the read is bounded: at most --max-runs records are read per call, newest first, and a window holding more says so in the output rather than publishing figures over a part of itself silently. The bound is on the read, not on a person: the newest --max-runs runs are taken before any view is applied, so a private view can be over fewer of the caller's own runs than --max-runs suggests. A run with neither a launch nor a record -- never launched, cancelled before launch, or a stale claim -- never started and is counted in no figure. The count of those is the window's, over everyone's runs, and is no more the caller's own than the truncation is.
--json prints {project, by, view, you, operator, since, until, max_runs, truncated, rows[], totals[], unlaunched, notes}; rows and totals carry {user, currency, runs, succeeded, failed, halted, infra_error, other, no_record, counted_usd, notional_usd, counted_runs, avg_counted_usd}, and the counts add up: runs == succeeded + failed + halted + infra_error + other + no_record.
Usage: fugaro runs stats
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--all |
bool | false |
no | every repository in the runs bucket |
--all-users |
bool | false |
no | show every user's row, not only your own (the table names whose numbers it shows) |
--by |
string | user |
no | what to break the figures down by (user) |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for stats |
--json |
bool | false |
no | print machine-readable output |
--max-runs |
int | 5000 |
no | read at most this many runs, newest first (a bigger window is truncated and says so) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | only this repository (owner/name) |
--since |
string | 7d |
no | only runs started within this long (7d, 36h, 90m; 0 for all) |
Subcommands:
This command has no subcommands.
fugaro secrets
Store and list a repository's secrets in Secret Manager
Usage: fugaro secrets
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for secrets |
Subcommands:
fugaro secrets ls-- List the project's (or, with --repo, a repository's) secrets: names, scope and versions, never valuesfugaro secrets set-- Store a secret's value, read from stdin or a hidden prompt, as a new version
fugaro secrets ls
List the project's (or, with --repo, a repository's) secrets: names, scope and versions, never values
List secrets: their logical names, IDs, version counts and where each value comes from, never any value (this command has no access call at all).
The default listing is the installation's project-wide containers -- the scope secrets set stores to by default for a name that has one -- one row per name, with the repositories the local config allows to use each one (bitbucket-token is never stored there by default: a repository access token serves one repository, so it has only repository copies). --project-wide is accepted as a synonym, so existing scripts keep working.
--repo (or a bare --repo, for this checkout's origin) lists one repository instead: its own containers, each with SCOPE repo (the repository's own container), project (a project-wide container this repository may use and has no copy of), or "project, repo override stored" (both exist; the repository's own version wins). Nothing about a repository is listed without --repo: the project's containers are not one repository's.
In a --repo listing, MISSING marks a name a job of that repository needs and no enabled version resolves for: the answer to "which required secret is gone" after a restore. "Required" is what the jobs of the repository's workflows mount and cannot run without, worked out from the checkout's fugaro.yaml the way a deploy works it out: the git credential of its provider, the model credentials its agent.auth names (claude-oauth-token and each allowed claude_accounts token for oauth; each allowed model provider's key for api-key; none for vertex), and each workflows.<w>.secrets name. anthropic-api-key is never marked: the job mounts it only when it has a version and runs without it, and fugaro validate says when a pinned model needs it. A required name with nothing behind it gets a row of its own — a missing secret has no container to be listed from, so its SECRET, LATEST and CREATED read "-" (in --json its id is empty and it has no created). The same marks a container that exists with no enabled version behind it, which resolves to nothing as surely as no container at all. Run this from a checkout of the repository: only its fugaro.yaml says what is required, so elsewhere, or with a fugaro.yaml that does not parse, nothing is marked and a note on stderr says so.
The default (project-wide) listing has no MISSING column: a name absent there may be stored per repository and perfectly present.
Usage: fugaro secrets ls
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for ls |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--project-wide |
bool | false |
no | the default for a name that has a project-wide meaning, accepted as a synonym so existing scripts keep working (cannot be combined with --repo) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | work on one repository's own copy, given as owner/name (no value: this checkout's origin); without it, a name that has a project-wide meaning is stored and listed project-wide |
Subcommands:
This command has no subcommands.
fugaro secrets set
Store a secret's value, read from stdin or a hidden prompt, as a new version
Store the value of the repository's secret NAME as a new version in Secret Manager, creating the secret if it doesn't exist.
NAME is one of anthropic-api-key, bitbucket-token, claude-oauth-token, github-app-key, the secret of a model provider in the local config's providers block (for a repository that provider's allow_data_to lists), or a secret some workflow declares under secrets: in the repository's fugaro.yaml (run it from a checkout of the repository for those).
The value is read only from stdin: pipe or redirect it in (fugaro secrets set bitbucket-token < token-file), or, when stdin is a terminal, paste it at a hidden prompt. It is never taken from an argument, a flag or the environment, and never printed. One trailing newline (\n or \r\n) is dropped, and the command says so. Values must be 4 bytes to 64 KiB, on one line except for github-app-key (a PEM, which must be redirected from a file), and a one-line value may not start or end with whitespace (a copy-and-paste slip, so it is refused rather than stored). Ctrl-C at the prompt stores nothing and restores the terminal.
Scope: with neither flag, a NAME that has a project-wide meaning is stored once for the whole Fugaro project, in the project's own Secret Manager -- the API key, the GitHub App key, a model provider's own key (any provider, allow_data_to or not), a reserved secret your local config's project_secrets block allow-lists, or a named Claude account's token whose account allow-lists at least one repository. --project-wide is accepted as a synonym of that default, so existing scripts keep working. Inside a shared job there is no IAM boundary between repositories: the profile is the boundary, and the value reaches every enrolled repository. A workflow's own secret has no project-wide meaning and is stored in the repository's own container as before.
bitbucket-token is the exception, and has no project-wide default: a Bitbucket credential is a repository access token, issued for one repository and usable for no other, so it is always stored in this repository's own container and every repository is asked for its own value (docs/git-providers.md). Storing it for the project is refused unless project_secrets.bitbucket-token allow-lists the repositories it is meant for.
With --repo (owner/name, or with no value for this checkout's origin) the value is stored as the repository's own copy instead. That copy overrides the project copy from then on: disabling its last enabled version is the only way back.
Usage: fugaro secrets set NAME
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for set |
--json |
bool | false |
no | print machine-readable output |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--project-wide |
bool | false |
no | the default for a name that has a project-wide meaning, accepted as a synonym so existing scripts keep working (cannot be combined with --repo) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | work on one repository's own copy, given as owner/name (no value: this checkout's origin); without it, a name that has a project-wide meaning is stored and listed project-wide |
Subcommands:
This command has no subcommands.
fugaro setup
Stand up or adopt the installation's, or a repository's, cloud resources through Terraform
setup plans the installation's shared resources (the runs bucket, registries, custom roles, the scheduler account, log isolation, an optional budget) with Terraform, adopting what the bootstrap already made, and applies the plan it showed once you confirm by typing the project's name (or pass --yes). It then writes the project config from the installation's outputs. With no project config yet, --name, --gcp-project and --region say what to create: projects/<name>.yaml.
It enables the Cloud Resource Manager API when it is disabled (setup reads the project's number through it before Terraform can enable it), creates the Terraform state bucket first when it doesn't exist, and offers to remove project Viewers' read access to the runs bucket, each after its own confirmation. --plan-only never takes --yes: what the plan needs made first (the state bucket, the API) takes the project's name typed at a terminal, or the run stops and says so. A plan that would delete or replace anything is refused unless --allow-delete names the address.
A new project config grants the launcher and operator roles to you, the authenticated user (user:<your email> from the Application Default Credentials), so that fugaro run works; --launcher or --operator replaces that, an existing or adopted config is never changed by it, and with a service account's credentials it stops and names the two flags.
On a first run it asks its questions once, in this order, each with a suggestion Enter takes, and writes the local config, so later runs ask nothing: the GCP project's ID (--gcp-project; a new project named after this one, fugaro-<name>, which Enter takes — and, offered second when it differs, the project GOOGLE_CLOUD_PROJECT or the credentials' quota project names, the one you are already working in; never gcloud's default project), the region (--region; us-east5), whether to create the GCP project or adopt one that already exists (--create-project; "create", what Enter takes, is a new fugaro-<name> project, and "adopt" leaves one that is already there exactly as it is), and the project's name (--name; from the repository's owner, else this directory's). Every question has its flag, so only the confirmations below need a terminal at all: without one, or with --non-interactive, --yes or --json, the run names every missing flag in one error — every one but the project question, whose answer it does not need. A run nobody can ask does not create a project (it adopts, the answer that changes nothing in the cloud), and --create-project is how a scripted run says otherwise. Where the installation already exists and this machine has no local config for it, setup keeps it rather than offering a second one: it writes the config from the installation and applies nothing, says which roles to ask an owner for, and says in one line that the installation is already set up and that it converges as fugaro update does. Its name is the installation's own (from the runs bucket's marker), not the directory's, and there is nothing left to ask. The budget section (rtdb_url, firebase_project, firebase_api_key, token_signer: none a secret) is filled from the Firebase root's outputs, read only. A --name given for an installation that already exists must be the installation's own name. With several project configs, --name of a project that has none is a first run of that name, and a checkout whose origin repository exactly one project lists selects that project.
Before the first billable image build of a GitHub repository, setup asks GitHub (as the App, with the App's key read from Secret Manager into memory only) whether the App is installed on the repository with the permissions runs ask for (Contents: Write, Pull requests: Write, Issues: Read, Metadata: Read): if not, the build is left for you with each missing permission and its fix and nothing is billed. A repository the local config does not list is asked about first, at the start, before any plan.
setup runs as a converge of stages (preflight, installation, with --firebase-project the Firebase backend and the images, the secrets, the plugin wiring and the repository, and on a first run the project — the one stage that may create the GCP project, and it does that only when the first question's answer was to create: an answer of "adopt" reads nothing and creates nothing), each with its own confirmation, in order, and stops at the first that fails or needs you; a rerun resumes, and one with nothing to do says "No changes" and exits 0. Exit codes: 0 done (or only planned), 1 a refusal, or a step left for you (see left_for_you in --json), 2 a cloud failure; --json prints the stages, left_for_you and the failed stage on every outcome.
setup --anchor, run in the checkout of a repository the project lists, writes only the gcp_project: line of its fugaro.yaml (the line teammates find the shared config from), with no Terraform, no discovery, no publish and no image copy; plain fugaro setup writes the same line as its last stage, after the whole converge. Before it writes anything it checks, and reports together (one line per workflow, with its fix in order), that every workflow's build record in the runs bucket exists and was submitted by a fugaro release at or after the one that added the field, and that the base image the image was built FROM (the record's base_ref, whose fugaro binary the image holds) is such a release too: a missing record, a record that does not say its base, an older or development CLI, or an older, development or hand-pushed base fails. It also checks that each base image the local config sets for those workflows is this release's pin through the remote repository, or a release image an earlier fugaro copied, at or after that release, since the next build starts from it (a development or hand-pushed one is never replaced by fugaro setup --base or fugaro image refresh: remove its base_images entry first). The fix it names is: that removal when needed, fugaro image refresh --repo <owner/name> --workflow <name> in the checkout (it verifies the release's base image and pins it by digest, points the daily image check job at it and rebuilds the image), then fugaro setup --anchor. The image checks trust the build records (written by the builds, unsigned: the same trust as the shared config), and a hand-pushed image under a release-looking tag passes them. Then the diff; --yes writes, a terminal asks, and otherwise it prints the line and writes nothing. Exit codes: 0 written or already present and safe, 1 a check failed or nothing was written, 2 a build record could not be read from the cloud (missing credentials included). A coding agent's session may run it, --yes included: it edits only a local file.
setup --firebase-project <firebase-project-id> builds the budget backend in a Firebase project you created and linked to billing, and it is the advanced case: the run's Firebase project is the installation's own --gcp-project by default (one id for both, D7), so this flag is for a project of its own — and it is also what adds the backend to the run, so a setup without it builds none. It creates nothing and links nothing (a project is created or billing linked only with --create-project and --link-billing, and it refuses one that is missing, has no billing, or whose database holds data and no Fugaro mark). It runs three applies, each with its own plan and confirmation: the installation (the history account), the Firebase root (the database, a restricted sign-in key, the token signer, and the budget admins: the GCP project's owners and editors who are users or groups, plus --budget-admin), and the installation again (the history job, once its image exists). Between the last two it deploys the database's rules, mark, project name, mode (--budget-mode; an absent one is seeded observe) and largest lease, after a confirmation of their own, then writes the local config. The same step creates the Firestore database for the spend history (fugaro report) if the project has none: its location, us-east5, is permanent (chosen once, never changed or deleted by Fugaro), so setup asks you to type the location to confirm it, at a real terminal (--yes, --non-interactive, --json and a pipe never confirm it: the step is then left for you), and it refuses to adopt a database that holds data or is in another location; it also deploys deny-everything Firestore rules and the Fugaro mark. --plan-only stops after the installation's plan. Each repository then needs fugaro setup --repo to pick up the jobs' environment.
setup --repo [PATH] onboards the repository of the checkout at PATH (default: the current directory), whose fugaro.yaml says what it needs, into the installation fugaro setup applied. It adopts what the bootstrap made for it (checking each resource's marks and live grants first), creates the rest, and deploys each workflow's job once its secrets are stored and its image is built. It offers each workflow's first image build (billable: the project's name typed at a real terminal, never --yes), then deploys the built image and unpauses the daily check. It prints the fugaro secrets set commands still needed, and adds the repository to the local config. A repository the local config does not list takes the same opt-in as the converge's stages (below): its owner/name typed at your own terminal, or --onboard-repo.
One confirmation per run, in a project Fugaro owns. A project is Fugaro's own when this run created it (--create-project) or its runs bucket carries Fugaro's mark (fugaro/project.json naming this project and this GCP project, in a bucket named fugaro-runs-<gcp project> that belongs to that project; read-only check: a custom runs bucket never qualifies). There, at a terminal, the ordinary steps (the Terraform applies of the installation, the Firebase root, the history job and the repository, the state bucket, the Cloud Resource Manager API, the Viewer-read removal, image copies and base-image pins that only add tags, the Firestore marks and rules, the local config) share one review screen and ONE typed project name, asked when the first of them has something to change (so a rerun with nothing to do asks nothing). Each step still prints its own exact plan. It never covers creating a project, linking billing, the Firestore database's permanent location, a Cloud Build, replacing a registry tag (--replace-image), an unlisted repository or a secret: each keeps its own typed confirmation. The state bucket and the API enable are fixed, announced, free steps; every Terraform plan is shown as it runs and is covered only if it is creates and in-place updates of the installation's own resource kinds, granting only the modules' roles to the listed launchers, operators and budget admins (the review prints them, with where each came from) or to Fugaro's own service accounts: its attributes are the modules' (images in this project's registry, jobs of this project, logs to this project, private buckets), and a Firebase project other than the installation's is covered only if verified as Fugaro's; any other plan (a destroy or replace, an IAM binding or policy, an unlisted member, a widened role) stops that step, which asks its own typed name. A wrong name applies nothing. The confirmation is per run and never stored. Any other project (adopted, unmarked, or a mark that fails to read) keeps a typed name at each step; --yes covers the ordinary steps as ever and takes no review; --non-interactive, --json, a pipe and a coding agent never take it; --plan-only shows the review and applies nothing.
What --yes covers: the ordinary steps, which are the installation's and the Firebase root's Terraform applies, the images' copy, the local config's writes, the plugin wiring and a known repository's steps. It never covers creating a project or linking billing, a secret, a repository the project does not list, the Firestore database's permanent location, a billable first image build, or replacing a tag in your registry (--replace-image KIND names the intent; the project's name is typed at a real terminal): with --yes, --non-interactive, --json or a pipe each of those is left for you, with the one line to run. In a coding agent's environment (CLAUDECODE, CLAUDE_CODE_ENTRYPOINT, CLAUDE_CODE_SSE_PORT, CLAUDE_CODE_REMOTE, CURSOR_AGENT or AI_AGENT is set) setup applies nothing, --yes included, and says to run it in your own terminal window; --plan-only and the read-only checks still work, and so does setup --anchor (with --yes), which edits only the checkout's fugaro.yaml. That is a mitigation, not a barrier: an agent can unset its own environment. A run that adopted an existing installation changes nothing in the cloud in the same run (the local config and, in a checkout, the plugin wiring in .claude/settings.json are the only files it writes).
In a checkout of a repository of this project, the converge's secrets stage asks, at hidden prompts, for the secrets its jobs mount (the git credential, the Claude credential agent.auth names, none for vertex, the allowed model providers' keys, the workflows' own), and skips what is already stored. It prompts only in your own terminal: never with --yes, --non-interactive or --json (--json never prompts; the stage then exits 1 with the one-line fugaro secrets set commands), never when stdin, stdout or stderr is not a terminal (a pipe is never read), and never when a coding agent's variable is set (CLAUDECODE and the like; CLAUDE_CODE_SSE_PORT is also set by the Claude Code IDE extension in VS Code and JetBrains terminals, so a person's own IDE terminal can be refused: its refusal tells you what to do about it). A pasted private key may have at most 120 lines. It creates each secret's container, before the repository stage, with the labels setup --repo's Terraform adopts (fugaro, fugaro_repo, fugaro_secret).
--create-project is the flag that answers the wizard's first question, and the only way to answer it without a terminal (a run with no terminal takes the other answer, adoption); the question itself decides nothing more than which of the two the project stage acts on. --create-project --gcp-project <id> creates that GCP project and adds Firebase to it, as you, after you type its ID at a terminal; --link-billing <account> then links that billing account (it may incur charges), after you type the account's ID. Each is its own typed confirmation, never given by --yes, --non-interactive or --json, and the ID is never the gcloud default project. Without --link-billing, setup prints the one gcloud command that links billing and stops. An existing project you can read is adopted; one that is held by someone else, or pending deletion, is refused; its existing billing link is never changed.
The plugin-wiring stage merges the Fugaro marketplace and plugin into the checkout's .claude/settings.json, pinned to this release's tag, after showing the diff and asking (--yes confirms it); see update-skills. The repository stage runs setup --repo for the checkout, after the secrets, when its origin's default branch (origin/HEAD, main or master, as last fetched) has a fugaro.yaml naming this project (else it is skipped and says why); it asks once for the GitHub App's ID of a GitHub repository (or take --github-app-id) and keeps its own confirmations, the first image build's included.
Both stages act only on a repository the project's local config already lists, or one you opt in: a repository not listed yet needs its owner/name typed at your own terminal (naming the checkout's path), or --onboard-repo owner/name, which must equal the origin (setup --repo takes both too); --yes, --non-interactive and a coding agent's environment never cover it (the flag is refused there), so a cloned third-party repository cannot onboard itself. The secrets stage is behind the same gate.
Usage: fugaro setup [--repo [PATH]]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--alert-email |
string | "" | no | where failed image checks and rebuilds are reported (default: the local config's) |
--allow-delete |
stringArray | [] |
no | a resource address the plan may delete or replace (repeatable) |
--allow-fork |
bool | false |
no | let the plugin-wiring stage move the ref of a fugaro marketplace in .claude/settings.json that names a repository other than dimipaun/fugaro (a fork you host); never done otherwise |
--allow-job-delete |
bool | false |
no | with --repo: lower the jobs' deletion protection, for offboarding |
--anchor |
bool | false |
no | in a checkout of an onboarded repository, only write the gcp_project line into its fugaro.yaml, after checking that every workflow's job image was submitted by fugaro 0.4.0 or later and built FROM a release base image of 0.4.0 or later, and that no base image the local config sets is a development or older one (no Terraform, no publish, no image copy; the diff, then --yes writes or a terminal asks) |
--base |
stringSlice | [] |
no | copy the release's base image (the only kind: base) into the project's registry now, besides what the checkout's fugaro.yaml needs (comma-separated or repeated) |
--base-image |
stringArray | [] |
no | a base image the image checks run and builds start from, recorded in the local config under its base kind (repeatable; KIND=IMAGE, or just IMAGE when its repository is named fugaro-<kind>; the kinds you don't name keep theirs) |
--billing-account |
string | "" | no | the billing account the budget is on |
--budget |
int64 | 0 |
no | a monthly budget on the project, in whole units of --budget-currency |
--budget-admin |
stringArray | [] |
no | with --firebase-project: an IAM member who may change caps and kill switches besides the GCP project's owners and editors (repeatable; default: the local config's terraform.budget_admins) |
--budget-currency |
string | "" | no | the budget's currency, such as USD |
--budget-mode |
string | "" | no | with --firebase-project: off, observe or enforce: the jobs' budget mode in the project config, and for observe and enforce the project-wide mode in the database (an absent one is seeded observe) |
--check-github-app |
bool | false |
no | let the GitHub App pre-check read the App's private key from Secret Manager with your own credentials (held in memory only, for one signed token; refused in a coding agent's session; GODEBUG=http2debug would print the token, so unset it); without it setup checks only with the key you typed in this run |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--config-only |
bool | false |
no | only write the local config, from the installation's outputs (else the flags) |
--create-project |
bool | false |
no | create the GCP project --gcp-project names and add Firebase to it, as you, after you type its ID at a terminal (never with --yes, --non-interactive or --json). An ID that exists and you can read is adopted; one held by someone else is refused. Billing is not linked unless --link-billing is also given; without it setup prints the one gcloud command that links it |
--display-name |
string | "" | no | with --create-project: the project's display name (default: its ID) |
--expect-digest |
stringArray | [] |
no | pin the digest of a release image, KIND=sha256:<hex> (KIND is base or history; repeatable): the digest of the source tag's manifest (the index), obtained out of band such as from the release notes. A base kind is cross-checked against it: its digest is verified against the release's cosign signature either way, and the two must agree. For history it is the trust anchor: without it setup trusts what the release tag in ghcr.io resolves to now, which is whoever can write that tag |
--firebase-project |
string | "" | no | build the budget backend in this Firebase project: the run's Firebase project is the installation's own --gcp-project by default (one id for both, D7), so this is the advanced flag, for a Firebase project of its own (one you created and linked to billing, or created with --create-project). It is also the flag that asks for the backend — a run without it builds none — and that backend is three confirmed applies: the database's rules and mark, the Firestore history database (permanent us-east5 location, typed confirmation) and the config |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
--github-app-id |
string | "" | no | the GitHub App's ID, for a GitHub repository (not a secret; recorded in the local config; setup asks once at a terminal, and --non-interactive needs it) |
-h, --help |
bool | false |
no | help for setup |
--image-source |
string | "" | no | the registry and owner the release images come from: a base kind is resolved and signature-verified there and pinned through the installation's remote repository, a history image is copied from it (default ghcr.io/dimipaun; a fork names its own, such as ghcr.io/acme) |
--json |
bool | false |
no | print the result as JSON on stdout (progress goes to stderr) |
--launcher |
stringArray | [] |
no | an IAM member who launches and watches runs (repeatable; default: the local config's, and for a new config you, the authenticated user) |
--link-billing |
string | "" | no | with --create-project: link this billing account (an ID such as 0123AB-4567CD-89EF01) to the project, after you type the account's ID at a terminal. This may incur charges on that account; never with --yes. It never changes a project's existing billing link |
--managed |
bool | false |
no | with --create-project: create a Fugaro-managed project. The monthly budget amount is required — --budget, --budget-currency and --billing-account together, with no default and no suggestion taken for you — and the amount and the currency are recorded in the project's creation fact (gs://fugaro-runs-<gcp-project>/fugaro/managed.json), where a later run and a restore read what was chosen. It removes no confirmation: the project's creation still types its ID, and the installation's ordinary steps share the run's one review. Flagging a project that already exists as managed is fugaro managed flag's, run by the owner at a terminal, and never setup's |
--name |
string | "" | no | the project's name: for a project config setup creates, and what names an installation that has no name yet (with a config, it must be its name; an installation's name never changes; with several project configs it names the one to create or use; adopting an installation defaults it to the installation's) |
--no-build |
bool | false |
no | with --repo: don't offer the first image builds |
--no-log-isolation |
bool | false |
no | leave Fugaro job logs in _Default instead of their own log bucket |
--non-interactive |
bool | false |
no | never prompt, and never read stdin: a step that needs you is listed under left_for_you (exit 1), and applying needs --yes, else the run only plans (a fresh state bucket needs its typed confirmation even then, so that plan exits 1); --yes never covers the typed-only steps (see --yes). With --config-only it only stops them prompting: their confirmations then need --yes |
--onboard-repo |
string | "" | no | owner/name of the checkout's origin repository (compared case-insensitively, without .git): the one non-interactive opt-in to wire and onboard a repository the project does not list yet, on github.com or bitbucket.org with an origin git config does not rewrite (--yes never covers it, and a coding agent's environment refuses it; any other origin takes the typed confirmation) |
--operator |
stringArray | [] |
no | an IAM member who onboards repositories (repeatable; default: the local config's, and for a new config you, the authenticated user) |
--parent |
string | "" | no | with --create-project: organizations/<number> or folders/<number> to create the project under (default: no parent; an organization is never guessed) |
--plan-only |
bool | false |
no | stop after showing the plan (never takes --yes: it creates nothing on a flag's word) |
--print-vars |
bool | false |
no | print the Terraform variables and exit, with no cloud calls and no Terraform (ungated: no discovery, and with --repo no readiness gates) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--provision-batch |
bool | false |
no | after the installation's ordinary steps, provision the Batch compute backend into a state of its own (design docs/design/compute-backend.md §8.1 task 6): the Compute and Batch APIs, the run accounts' IAM, the launcher's, reaper's and preload accounts and roles, a Cloud NAT and router, and a preloaded boot image rebuilt on a schedule. It is money (a billable build, a NAT's hours) and permanent, so --yes never covers it and it is typed at a real terminal; nothing runs it by default, and no run can use the backend until the enable task. It excludes --repo and the flags that only read or only stop (--forget, --print-vars, --config-only, --publish-config, --anchor) |
--publish-config |
bool | false |
no | publish the shared config to the runs bucket and stop (setup does it after it writes the local config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--registry-cleanup |
string | "" | no | Artifact Registry cleanup: dry-run (the default), on or off |
--replace-image |
stringArray | [] |
no | KIND (history; repeatable): let the converge replace that image's tag in your registry when it names another image, a release tag or history:latest (never done otherwise, so a hand-pushed history:latest needs it once). A base kind is refused: it is pinned by digest through the remote repository, so nothing of it is ever copied over. It names the intent only: replacing is confirmed by typing the project's name at a real terminal, never by --yes, --non-interactive or --json |
--repo |
bool | false |
no | onboard the repository of the checkout at PATH (default: the current directory) instead of the installation |
--retire |
bool | false |
no | with --repo: run the retirement this config change needs (a workflow or a named account removed, a secret no longer mounted): remove the protected addresses from Terraform's state (destroying nothing), apply, then delete the orphaned Cloud Run jobs through the API. The project's name is typed twice at a real terminal, and --yes, --non-interactive, --json, a pipe and a coding agent cover neither. Excludes --plan-only, --print-vars and --forget, which read or forget rather than apply |
--runs-bucket |
string | "" | no | the runs bucket (default: the project config's, else fugaro-runs-<gcp-project>) |
--scheduler-region |
string | "" | no | Cloud Scheduler region of the daily image checks (default: the region, or the nearest one Scheduler offers) |
--state-bucket |
string | "" | no | the Terraform state bucket (default: the project config's, else fugaro-tfstate-<gcp-project>) |
--yes |
bool | false |
no | confirm the ordinary steps without asking (only after reading what they do). Never covers creating a project, billing, a secret, an unlisted repository, the Firestore location, a billable first image build or replacing an image tag (typed at a real terminal). Under a coding agent's environment variable (CLAUDECODE and the like) setup applies nothing, --yes included (except setup --anchor, which only edits the checkout's fugaro.yaml and honours --yes there); that is a mitigation, not a barrier: an agent that unsets its own variables is not stopped, and the real controls are the typed confirmations and the skills' lint |
Subcommands:
This command has no subcommands.
fugaro stats
Aggregate one installation's run records into figures a page can publish
Usage: fugaro stats
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for stats |
Subcommands:
fugaro stats runs-- Publish per-recipe duration and cost percentiles over a window, and nothing else
fugaro stats runs
Publish per-recipe duration and cost percentiles over a window, and nothing else
Aggregate one named installation's own run records into the figures the caps-and-costs guide publishes: the minimum, the median and the 90th percentile of a run's wall-clock duration and of its total cost, grouped by recipe.
The records are read read-only, over --since's window, from the installation --project names -- and result.json alone is read: the task a run was given is never read, so no task text can reach the output. Nothing a reader cannot look up is printed: the groups are recipe names and the window, every figure is a number or a count, and no field carries a repository, run ID, branch, pull request, task, person or commit.
--project is required and has no default, the sandbox included: an aggregation is about one named installation, and this command never guesses one. There is no --all. The command is refused in a coding agent's session: the records are an installation's own data, and reading them is the owner's step.
A recipe with fewer than --min-runs runs in the window is not published at all -- a range from four runs reads as a promise precisely because it is a range -- and a run whose recipe this binary does not ship, or whose record carries no finished duration or no cost breakdown, or whose result.json cannot be read at all, is counted and not grouped: one bad object never makes the figures unproducible.
--json prints {project, since, until, min_runs, recipes[{recipe, runs, compute_not_estimated, duration_s{min, median, p90}, cost_usd{min, median, p90}}], totals{runs, recipes, runs_below_min_runs, runs_unknown_recipe, runs_not_estimated, runs_without_a_figure}, not_a_promise}.
The closing line is the disclaimer the figures travel with: a cap is a ceiling rather than an estimate, a range is what one window of one installation's runs did rather than a promise, and every figure prints the number of runs behind it.
Usage: fugaro stats runs
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for runs |
--json |
bool | false |
no | print machine-readable output |
--min-runs |
int | 20 |
no | the least runs a recipe may carry a range from (a thinner group is not published) |
--project |
string | "" | yes | the installation whose run records are read (required: this command never guesses one, and the sandbox is named like any other) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--since |
string | 90d |
no | the window: Nd days back from today, or a Go duration (90d) |
Subcommands:
This command has no subcommands.
fugaro update
Re-converge the installation, or a checkout's repository, after a CLI upgrade
update re-converges an installation that already exists against this release: the same Terraform roots, the same stages, the same confirmations and the same exit codes as fugaro setup, for a project that is set up already (or, with --repo, for the repository of the checkout at PATH). Run it after upgrading the CLI: it applies what the release changed, and one with nothing to do says "No changes" and exits 0.
It creates nothing. The flags that do — --create-project, --display-name, --parent, --managed, --link-billing and --provision-batch — are fugaro setup's, and update refuses each by name rather than ignoring it, so a re-converge cannot create a GCP project, link a billing account or provision the Batch backend by accident. A first installation is fugaro setup.
--forget is update's own: it is the rollback, and it turns log isolation and registry cleanup off with a guarded apply before it removes every address from Terraform's state — in a checkout, the repository's addresses with them — destroying nothing else.
Everything else is setup's help word for word, because it is the same converge: the review screen and the one typed project name in a project Fugaro owns; the steps that keep their own typed confirmation (a project's creation and the billing link are setup's, and here they cannot arise at all, but the Firestore database's permanent location, a billable first image build, replacing a registry tag, an unlisted repository and the secrets are not); the secrets stage's hidden prompts and the one line of fugaro secrets set commands it leaves instead; the plugin wiring; --anchor, which writes the checkout's gcp_project line and nothing else; --plan-only, --print-vars, --config-only and --publish-config; and --json, which prints the same result object. Exit codes: 0 done (or only planned), 1 a refusal or a step left for you, 2 a cloud failure.
Usage: fugaro update [--repo [PATH]]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--alert-email |
string | "" | no | where failed image checks and rebuilds are reported (default: the local config's) |
--allow-delete |
stringArray | [] |
no | a resource address the plan may delete or replace (repeatable) |
--allow-fork |
bool | false |
no | let the plugin-wiring stage move the ref of a fugaro marketplace in .claude/settings.json that names a repository other than dimipaun/fugaro (a fork you host); never done otherwise |
--allow-job-delete |
bool | false |
no | with --repo: lower the jobs' deletion protection, for offboarding |
--anchor |
bool | false |
no | in a checkout of an onboarded repository, only write the gcp_project line into its fugaro.yaml, after checking that every workflow's job image was submitted by fugaro 0.4.0 or later and built FROM a release base image of 0.4.0 or later, and that no base image the local config sets is a development or older one (no Terraform, no publish, no image copy; the diff, then --yes writes or a terminal asks) |
--base |
stringSlice | [] |
no | copy the release's base image (the only kind: base) into the project's registry now, besides what the checkout's fugaro.yaml needs (comma-separated or repeated) |
--base-image |
stringArray | [] |
no | a base image the image checks run and builds start from, recorded in the local config under its base kind (repeatable; KIND=IMAGE, or just IMAGE when its repository is named fugaro-<kind>; the kinds you don't name keep theirs) |
--billing-account |
string | "" | no | the billing account the budget is on |
--budget |
int64 | 0 |
no | a monthly budget on the project, in whole units of --budget-currency |
--budget-admin |
stringArray | [] |
no | with --firebase-project: an IAM member who may change caps and kill switches besides the GCP project's owners and editors (repeatable; default: the local config's terraform.budget_admins) |
--budget-currency |
string | "" | no | the budget's currency, such as USD |
--budget-mode |
string | "" | no | with --firebase-project: off, observe or enforce: the jobs' budget mode in the project config, and for observe and enforce the project-wide mode in the database (an absent one is seeded observe) |
--check-github-app |
bool | false |
no | let the GitHub App pre-check read the App's private key from Secret Manager with your own credentials (held in memory only, for one signed token; refused in a coding agent's session; GODEBUG=http2debug would print the token, so unset it); without it update checks only with the key you typed in this run |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--config-only |
bool | false |
no | only write the local config, from the installation's outputs (else the flags) |
--expect-digest |
stringArray | [] |
no | pin the digest of a release image, KIND=sha256:<hex> (KIND is base or history; repeatable): the digest of the source tag's manifest (the index), obtained out of band such as from the release notes. A base kind is cross-checked against it: its digest is verified against the release's cosign signature either way, and the two must agree. For history it is the trust anchor: without it update trusts what the release tag in ghcr.io resolves to now, which is whoever can write that tag |
--firebase-project |
string | "" | no | build the budget backend in this Firebase project: the run's Firebase project is the installation's own --gcp-project by default (one id for both, D7), so this is the advanced flag, for a Firebase project of its own (one you created and linked to billing, or created with --create-project). It is also the flag that asks for the backend — a run without it builds none — and that backend is three confirmed applies: the database's rules and mark, the Firestore history database (permanent us-east5 location, typed confirmation) and the config |
--forget |
bool | false |
no | roll back: turn log isolation and registry cleanup off, then remove every address from Terraform's state |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
--github-app-id |
string | "" | no | the GitHub App's ID, for a GitHub repository (not a secret; recorded in the local config; update asks once at a terminal, and --non-interactive needs it) |
-h, --help |
bool | false |
no | help for update |
--image-source |
string | "" | no | the registry and owner the release images come from: a base kind is resolved and signature-verified there and pinned through the installation's remote repository, a history image is copied from it (default ghcr.io/dimipaun; a fork names its own, such as ghcr.io/acme) |
--json |
bool | false |
no | print the result as JSON on stdout (progress goes to stderr) |
--launcher |
stringArray | [] |
no | an IAM member who launches and watches runs (repeatable; default: the local config's, and for a new config you, the authenticated user) |
--name |
string | "" | no | the project's name: for a project config update creates, and what names an installation that has no name yet (with a config, it must be its name; an installation's name never changes; with several project configs it names the one to create or use; adopting an installation defaults it to the installation's) |
--no-build |
bool | false |
no | with --repo: don't offer the first image builds |
--no-log-isolation |
bool | false |
no | leave Fugaro job logs in _Default instead of their own log bucket |
--non-interactive |
bool | false |
no | never prompt, and never read stdin: a step that needs you is listed under left_for_you (exit 1), and applying needs --yes, else the run only plans (a fresh state bucket needs its typed confirmation even then, so that plan exits 1); --yes never covers the typed-only steps (see --yes). With --forget and --config-only it only stops them prompting: their confirmations then need --yes |
--onboard-repo |
string | "" | no | owner/name of the checkout's origin repository (compared case-insensitively, without .git): the one non-interactive opt-in to wire and onboard a repository the project does not list yet, on github.com or bitbucket.org with an origin git config does not rewrite (--yes never covers it, and a coding agent's environment refuses it; any other origin takes the typed confirmation) |
--operator |
stringArray | [] |
no | an IAM member who onboards repositories (repeatable; default: the local config's, and for a new config you, the authenticated user) |
--plan-only |
bool | false |
no | stop after showing the plan (never takes --yes: it creates nothing on a flag's word) |
--print-vars |
bool | false |
no | print the Terraform variables and exit, with no cloud calls and no Terraform (ungated: no discovery, and with --repo no readiness gates) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--publish-config |
bool | false |
no | publish the shared config to the runs bucket and stop (update does it after it writes the local config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--registry-cleanup |
string | "" | no | Artifact Registry cleanup: dry-run (the default), on or off |
--replace-image |
stringArray | [] |
no | KIND (history; repeatable): let the converge replace that image's tag in your registry when it names another image, a release tag or history:latest (never done otherwise, so a hand-pushed history:latest needs it once). A base kind is refused: it is pinned by digest through the remote repository, so nothing of it is ever copied over. It names the intent only: replacing is confirmed by typing the project's name at a real terminal, never by --yes, --non-interactive or --json |
--repo |
bool | false |
no | onboard the repository of the checkout at PATH (default: the current directory) instead of the installation |
--retire |
bool | false |
no | with --repo: run the retirement this config change needs (a workflow or a named account removed, a secret no longer mounted): remove the protected addresses from Terraform's state (destroying nothing), apply, then delete the orphaned Cloud Run jobs through the API. The project's name is typed twice at a real terminal, and --yes, --non-interactive, --json, a pipe and a coding agent cover neither. Excludes --plan-only, --print-vars and --forget, which read or forget rather than apply |
--runs-bucket |
string | "" | no | the runs bucket (default: the project config's, else fugaro-runs-<gcp-project>) |
--scheduler-region |
string | "" | no | Cloud Scheduler region of the daily image checks (default: the region, or the nearest one Scheduler offers) |
--state-bucket |
string | "" | no | the Terraform state bucket (default: the project config's, else fugaro-tfstate-<gcp-project>) |
--yes |
bool | false |
no | confirm the ordinary steps without asking (only after reading what they do). Never covers creating a project, billing, a secret, an unlisted repository, the Firestore location, a billable first image build or replacing an image tag (typed at a real terminal). Under a coding agent's environment variable (CLAUDECODE and the like) update applies nothing, --yes included (except update --anchor, which only edits the checkout's fugaro.yaml and honours --yes there); that is a mitigation, not a barrier: an agent that unsets its own variables is not stopped, and the real controls are the typed confirmations and the skills' lint |
Subcommands:
This command has no subcommands.
fugaro update-skills
Pin the Fugaro plugin in the repository's .claude/settings.json to this release
update-skills merges the Fugaro plugin's marketplace and its enablement into the checkout's .claude/settings.json, pinned to this binary's release tag (a dev build writes no pin). Every other key is kept; a fork's marketplace repository is kept and only its ref moves; a file that is not valid JSON is never rewritten; a changed file is re-indented to two spaces. A marketplace that names another repository than dimipaun/fugaro is reported with a warning and left alone unless --allow-fork says it is yours (then only its ref moves); a plugin the repository sets to false stays disabled. It shows the diff and writes the file; it never commits: review it with git diff. It needs no credentials, no network and no Terraform. Outside a checkout it prints the settings to add.
--check writes nothing: it prints how the pin compares with this binary (and with the plugin installed on this machine when Claude Code's record is readable) and exits 1 on any warning state (outdated, newer, unpinned, foreign, not wired, installed differs); "not installed" and "cannot compare" are informational.
Usage: fugaro update-skills [--check] [--dir D] [--json]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--allow-fork |
bool | false |
no | move the ref of a marketplace repository other than dimipaun/fugaro (a fork you host) to this release's tag |
--check |
bool | false |
no | print the state and exit 1 unless it is ok (informational states pass); write nothing |
--dir |
string | . |
no | a directory in the checkout |
-h, --help |
bool | false |
no | help for update-skills |
--json |
bool | false |
no | print machine-readable output |
Subcommands:
This command has no subcommands.
fugaro upgrade
Bring checkouts up to this fugaro: pin the plugin, install or update it in Claude Code, refresh the repository's images
upgrade brings each checkout (PATH, default the current directory; several are processed one after the other, each on its own) up to this fugaro, in three steps, stopping that checkout at the first step that fails:
pin what fugaro update-skills does: the Fugaro plugin in the checkout's .claude/settings.json pinned to this release's tag, shown as a diff and never committed; a fork's marketplace moves only with --allow-fork; a file that is not valid JSON is never rewritten; a pin newer than this fugaro is never moved down. plugin the plugin installed (user scope) or updated (each install that applies to the checkout, at its own scope) in Claude Code through the claude CLI on PATH: a fixed set of claude plugin commands, never with -y. Without claude it prints the slash commands to type in Claude Code. Running Claude Code sessions apply it after a restart. cloud what fugaro image refresh does for the checkout's repository: this release's base image, the daily image check job, the builds. It asks at each step, or with --yes confirms every step itself, each billable build included, with no cap. Skipped where there is nothing to refresh from here: no fugaro.yaml, no local project config (a teammate), a repository not onboarded. After a real refresh it also compares the deployed job's whole copy of the local project config (providers, model_prices, budget settings, the region's compute price override and the GitHub App ID; multi-model.md) with what the local config would write now: a version upgrade never refreshes that copy, so a mismatch prints a note naming the fields and the one command that does, fugaro update --repo . (never run here: its Terraform confirmations stay yours). --check makes no cloud call, so it cannot tell and says so instead. It checks each workflow's default-account job; named-account jobs are updated by the same fugaro update --repo .
It never upgrades fugaro itself: brew upgrade dimipaun/tap/fugaro && fugaro upgrade is the whole sequence.
--local runs pin and plugin only. Under --local and in a coding agent's session (CLAUDECODE and the like) the cloud step is skipped before it reads anything, never attempted, with the command to run in your own terminal, so the exit code is 0 when the local steps succeeded. --check writes nothing, runs no claude command and makes no cloud call: it reads the settings file, Claude Code's record of installed plugins and the local project config, prints what each step would do and exits 1 when anything is stale (build records are not read). Without --yes, --local or --check it needs a real terminal. There is no --json.
Exit codes: 0 every checkout finished or had nothing to do; 1 a refusal, a failed local step, a cloud step that cannot start from the checkout's files (a bad fugaro.yaml or origin, an unreadable config; with --check too) or (with --check) something stale; otherwise a failed cloud step exits with the refresh's own code, 2 for a cloud call that failed. The summary names each checkout's steps and, for one that stopped, the line to rerun.
Usage: fugaro upgrade [PATH...]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--allow-fork |
bool | false |
no | move the ref of a marketplace repository other than dimipaun/fugaro (a fork you host) to this release's tag, and add it to Claude Code |
--check |
bool | false |
no | write nothing, run no claude command, make no cloud call: print what each step would do and exit 1 when anything is stale |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--expect-digest |
stringArray | [] |
no | cross-check the digest of a base image's release signature, KIND=sha256:<hex> (repeatable; one PATH only) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for upgrade |
--image-source |
string | "" | no | the registry and owner the release base images come from: a base kind is resolved and signature-verified there and pinned through the installation's remote repository (default ghcr.io/dimipaun) |
--local |
bool | false |
no | run the pin and plugin steps only (the only mode that does everything it can inside a coding agent's session) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | owner/name of the repository; it must be the checkout's origin (one PATH only) |
--workflow |
stringArray | [] |
no | a workflow to refresh (repeatable; default: every workflow in fugaro.yaml; one PATH only) |
--yes |
bool | false |
no | confirm every step of the cloud step without asking (the base copy, the check-job update and each billable build, with no cap), and without a terminal; never in a coding agent's session |
Subcommands:
This command has no subcommands.
fugaro validate
Check a fugaro.yaml against the schema and the repository
Usage: fugaro validate [path]
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for validate |
--json |
bool | false |
no | print machine-readable output |
--offline |
bool | false |
no | never read the runs bucket: resolve against the cached project layer, if any |
--project-layer |
string | "" | no | resolve against this project layer file instead of the published one (also checks the file; for CI without bucket access, and before fugaro config publish) |
Subcommands:
This command has no subcommands.
fugaro verify
Run and record this repository's build, test or lint command (inside a Fugaro run)
Usage: fugaro verify build|test|lint
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for verify |
--rerun-failed |
bool | false |
no | rerun only the tests that failed in the previous test run, to detect flaky tests |
Subcommands:
This command has no subcommands.
fugaro version
Print the fugaro version
Usage: fugaro version
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
-h, --help |
bool | false |
no | help for version |
Subcommands:
This command has no subcommands.
fugaro watch
Watch the project's spend, repositories and running agents live
Watch the project's budget backend live: the project's total against its caps, one block per repository (spend against its cap, burn rate, kill state) and one row per running agent (stage, round, age, spend, silent, lost and near-deadline flags). It reads the project's Firebase Realtime Database as you (the Viewer role), like fugaro budget show.
At a terminal watch opens the interactive screen. With --plain, --json or --once, or when stdin or stdout is not a terminal, it prints text frames (at most one per --interval, 10s) or, with --json, one JSON document per change (at most one a second); --once prints one snapshot and exits. Those modes have no kill keys: fugaro budget kill and resume are the script path.
A project with no budget backend shows its run records only (as fugaro runs ls does, for the last 24 hours) and says so; fugaro runs ls --watch stays for the question "did my runs finish".
A finished run stays shown for --keep (default 6h) or among the most recent --keep-count (default 15), whichever is stricter; a failed one stays until it is acknowledged (x in the interactive screen) or a day passes. --all shows every finished run (the a key toggles this without relaunching). --json is always unfiltered: it carries every finished run and, among them, the ones ready for review.
The "Ready for your review" list drops a pull request that is already merged or closed. The state is asked of your own gh (when it is installed and logged in), by pull request number and repository, never through a shell and never with the run's title or any other run text; the answer is cached, and anything that goes wrong — no gh, no login, a rate limit, a failure, a timeout — leaves the pull request listed as it is today, with one note saying so. --no-pr-state turns the lookup off entirely (nothing is executed), and --json is unaffected: its ready[] is the runs bucket's own record.
Usage: fugaro watch
Flags:
| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--all |
bool | false |
no | show every finished run, not just the active and recent ones |
--ascii |
bool | false |
no | use ASCII instead of ⚠ ▓░ ▸ |
--config |
string | "" | no | the project config file to use (default: the project's $XDG_CONFIG_HOME/fugaro/projects/<name>.yaml) |
--gcp-project |
string | "" | no | the GCP project ID; it must be the selected project config's gcp_project |
-h, --help |
bool | false |
no | help for watch |
--interval |
duration | 0s |
no | the least time between plain frames (default 10s) and the polling period (default 5s) |
--json |
bool | false |
no | print one JSON document per change instead of a screen |
--keep |
duration | 6h0m0s |
no | how long a finished run stays shown (with --keep-count, whichever is stricter) |
--keep-count |
int | 15 |
no | how many finished runs stay shown (with --keep, whichever is stricter) |
--no-color |
bool | false |
no | no colour (NO_COLOR and TERM=dumb do the same) |
--no-pr-state |
bool | false |
no | do not ask gh about the ready PRs: list every one of them, run nothing |
--once |
bool | false |
no | print one snapshot and exit (with --json or plain text) |
--plain |
bool | false |
no | print text frames instead of the interactive screen |
--poll |
bool | false |
no | read by polling instead of streaming (for proxies that buffer) |
--project |
string | "" | no | the Fugaro project to act on (default: the checkout's fugaro.yaml project:, else $FUGARO_PROJECT, else the only project config) |
--region |
string | "" | no | GCP region (overrides the project config's) |
--repo |
string | "" | no | only this repository (owner/name) |
Subcommands:
This command has no subcommands.