A project's repositories can now share Cloud Run jobs, and a project can name several Claude accounts so a person's own subscription serves the project's runs from its own job. A run's budget token is sealed so no other run can use it, spend can be reported per person, and the watch screen names who launched each run.
Highlights
- A run's budget token is sealed: the launcher writes it at
tokens/<slug>/<run>/budget-token encrypted under a key generated for that one launch, which travels in the run's own environment and nowhere else, so a peer run of a shared job that reads the object gets ciphertext it cannot use. - A project runs its repositories on shared Cloud Run jobs: a profile names one provider and the Claude accounts it serves,
fugaro init deploys one job and one job service account per (profile, provider, account), and a checkout: clone workflow launches onto them instead of onto a job of its own. - A project can name several Claude accounts (
claude_accounts), so a person's own subscription serves the project's runs from its own job: each account's token is mounted only on that account's job, and a launch is admitted only for the repositories the account's published list covers. fugaro runs stats --by user reports spend and jobs per person over a window, and fugaro runs ls and fugaro watch name who launched each run in a BY column.- The desktop console accepts this release's documents:
job, profile, provider, account and launched_by no longer make it refuse a watch --json or runs ls --json document whole, so the Live screen draws the run rather than a skew screen — in a console built from this release, which is a separate download (an older console still shows the skew screen). - The desktop console is published for this release as its own download,
console-v0.9.0: a signed, notarised and stapled macOS app, installed separately from the command line.
For operators
The order matters, steps 2 and 6 are one command split in two, and step 7 is step 3 again: an image built from this release refuses a policy node published by an older one, and an older image refuses this release's node, so the policy is republished before any image moves, and the shared jobs move last.
1. Per machine — upgrade the CLI: brew upgrade dimipaun/tap/fugaro.
2. Per repo checkout — run fugaro upgrade --local, so the plugin pin follows the CLI without a cloud call. Its cloud step (the base image's pin, the daily check job and each workflow's build) is step 6, and it is deliberately not run here.
3. Per installation, in your own terminal, outside any repository checkout — run fugaro init --firebase <gcp-project> (in a checkout it would also pin this release's base image and move the shared jobs onto it before step 5). It deploys one job and one job service account per (profile, provider, account), replaces the launchers' bucket binding with the one that reaches tokens/ as well as runs/ (the old binding is replaced, never deleted) and writes each shared job account's read-only grant on tokens/. fugaro doctor names a launcher still holding the pre-0.9.0 runs/-only condition and says this init is the fix.
4. Per repo checkout, in your own terminal — run fugaro init --repo .. It writes each job account's read-only grant on tokens/<slug>/, beside the repository's own job. fugaro doctor names a repository that has not been re-applied; until it is, that repository's runs with a budget token stop at bootstrap, reading the token as a missing object.
5. Per installation — republish the policy, and read the list out first, because the publish that follows rebuilds it: run fugaro project policy show and keep what it prints, then fugaro project policy publish --delete, then fugaro project policy publish, then read the diff the publish prints and repair the list with fugaro project repos add <owner/name> and fugaro project repos rm <owner/name>. A repository you had added by hand is dropped, and one you had removed comes back while the config still names it. Runs on a shared job halt in between, which is the fail-safe direction.
6. Per repo checkout — rebuild the images with fugaro upgrade (its cloud step) or fugaro image refresh. This release's base image is resolved at its -pinned tag, its cosign signature is verified, and the digest is read back through the installation's own remote repository and pinned in base_images — nothing is copied and nothing is pushed — then the daily image check job is pointed at it and each workflow's image is rebuilt on it. A 0.9.0 policy read by an older runner image is refused, and the fix is the image, not the policy.
7. Per installation, in your own terminal, on a machine where step 6 ran — run fugaro init --firebase <gcp-project> again. The shared jobs run the installation's base image, and neither fugaro upgrade nor fugaro image refresh touches them: only this re-apply of the installation moves them onto the base image step 6 pinned (this machine's base_images). Until it runs, a shared job's runs stop at bootstrap, because the older runner refuses the policy step 5 published, and neither the launch check nor fugaro doctor says so, since both read the pin rather than the deployed job.
Then run fugaro project policy show again, per installation, and read it back: it prints the profiles and, for each account a profile names, the repositories its token may be used by.
Known limits
- Managed projects stay disabled, exactly as in 0.8.6 and 0.8.7. The groundwork is in this release and out of reach: the second mark the managed read now requires beside the creation marker (the
fugaro_managed=true label on the project itself), fugaro managed flag, the inventory-aware fugaro managed apply, and the bounded form every value it quotes from elsewhere is printed in. Every command that would create a managed project or act as its deployer refuses with a plain message before any cloud call — fugaro init --create-project --managed, fugaro init --managed, fugaro managed flag, fugaro managed apply and fugaro restore — so no managed apply runs at all, nothing writes the project label or the marker, and nothing skips the typed confirmation it would have skipped. What holds all of it off is the deployer's scoped role: the installation module's managed_deployer_scoped defaults to false and fugaro init never sets it, because the fmgd- fence its one conditioned binding carries is an IAM condition GCP does not accept as written (9 clauses joined by 17 logical operators where 12 are allowed; resource.name.contains(), which it does not support; and resource.name on Artifact Registry repositories, Cloud Run jobs, Cloud Scheduler jobs, IAM service accounts and API keys, where it is not supported). The deployer account, its create-and-read role and your impersonation grant are created as before, and the fence is still to be redesigned and measured against a live project. fugaro doctor reports the scoped role's absence as an info line, not a warning, and --strict does not fail on it. - The Batch backend is still disabled.
fugaro init --provision-batch refuses with a plain message before any cloud call, as it has since 0.8.6: its reaper role names batch.jobs.cancel, which is not a permission Google has, and the reaper is still to be redesigned. This and managed projects are the two things 0.8.6's notes said would return in 0.9.0, and neither returns here. - Only
checkout: clone workflows reach a shared job, and only on GitHub. A baked workflow keeps its per-repository job, and no shared job serves Bitbucket: fugaro init deploys none for a Bitbucket profile, so such a repository keeps its per-repository job. A shared job also carries less than a per-repository one — no FUGARO_CHECKOUT (a full clone rather than a blobless one, and no mise install), no owner-configured model provider, no local compute-price override, the default budget grace, and no repository-level workflows.<n>.secrets — all of which are listed under "Which runs work on a shared job today" in docs/project-layer.md. - A shared job's service account can read every repository's
tokens/ objects. That reach is what the seal is for: what it reads there is ciphertext whose key it does not hold. The installation-wide reach and the reasoning are stated in full in SECURITY.md. - No per-account budget dimension. The budget is keyed by model, repository, project and person, never by credential: an OAuth run adds to the notional (subscription, unbilled) counters, and a named account's own limits are Anthropic's, not Fugaro's.
fugaro project export is not in this release. The project-centric plan's phase 6 (a project's record written into a repository or a folder of one) is still to come, as are the project-level phases that would let a project be created and managed from a repository rather than from an installation. The credentials service, and the mobile and voice work, are not part of this release either.- The live checks have not been run, and only you can run them. These are owner-run, sandbox-only, and every one of them is still NOT RUN: Check 60 of
docs/gcp-live-checklist.md, the sealed budget token end to end (a sealed run works, the tokens/ object is ciphertext, and the widened launcher condition and the job's read-only grant are read off the live policy); Check 53, a shared project job end to end (reserved by the project-centric plan's Task 3.7, its section not yet written into the checklist); the named-account path, for which no live check has yet proved an account-gated shared-job run end to end; and the managed checks (67a, 67b and 68, reserved in the managed-projects plan) — which cannot run in this release at all, since every managed command refuses, so the project label, the inventory-aware apply and the applying identity remain unmeasured. Check 38, the clone workflows, passed on 2026-10-17 and its record is still to be written up, which is why checkout: clone ships here rather than earlier.