fundaia
The command line for the Fundaia deployment platform: projects,
services, variables, deployments, logs and metrics, from a terminal. It talks to any instance of the
platform — --url and profiles are first-class, so one binary reaches production, staging and a
laptop.
What the platform does, and every command grouped by topic, is in the product documentation: infrastructure.fundaia.com/docs/cli. This README covers installing, scripting, updating and working on the crate.
Install
The crate is public on crates.io; that is the route that works for everybody. Each cli-v* release
of the repository also carries prebuilt binaries for x86_64-unknown-linux-gnu,
aarch64-unknown-linux-gnu, x86_64-apple-darwin and aarch64-apple-darwin, but the repository is
private, so they are fetched authenticated:
cli/install.sh downloads the same assets without credentials, so it answers 404 until the
repository is public. Nothing here uses sudo or edits a shell profile.
Sign in
A terminal cannot present a passkey, so the credential is minted in the browser: the command prints a
short code, opens the approval page and waits. It works over SSH (--no-browser prints the address).
The token lives in ~/.config/fundaia/config.toml (directory 0700, file 0600). logout only
forgets it locally; revoke it from Línea de comandos in the web interface.
Projects and services are named by id, slug or display name; an ambiguous name is an error, not a guess.
Scripting and AI agents
-
--json(orFUNDAIA_JSON=1) prints one compact JSON value on stdout — the server's own DTOs.logs -fandwatchprint one object per line;deploy --jsonwaits and prints one result. The diagnosis commands (attention,health,diagnose,grep,deps,compare,probe,security…) print the same object the matching MCP tool returns. -
A failure is one object on stderr:
{"error":{"code","message","exit","retryable",…}}, with the server's error code. Colour is off in JSON mode. -
The exit code is the class, and the numbers never move:
Exit Meaning Retryable 0 success — 1 a bug in the CLI yes 2 bad arguments (clap) no 3 not_foundno 4 validation_failedno 5 unauthorized— runfundaia loginno 6 forbiddenno 7 conflictno 8 rate_limitedyes 9 external_service_failedyes 10 the instance is unreachable yes 11 the deployment failed no -
fundaia schema --jsondescribes every command, argument and exit code, and whether a commandreads,writes,starts,destroysor islocal.fundaia guideprints the platform's briefing for agents (AGENT.md, the same truths the instance serves at/agent.md). Both work offline. -
Completions:
fundaia completions bash|zsh|fish.
A Claude Code skill
fundaia skill install writes ~/.claude/skills/fundaia/SKILL.md (--project writes it into
.claude/skills/ of the current directory). It is generated from this binary's own commands and
the guide, so it lists exactly what the installed version can do; run it again after an upgrade.
fundaia skill prints it without writing anything.
CI and profiles
Every global option reads an environment variable (FUNDAIA_URL, FUNDAIA_TOKEN, FUNDAIA_PROFILE):
env:
FUNDAIA_URL: https://infrastructure.fundaia.com
FUNDAIA_TOKEN: ${{ secrets.FUNDAIA_TOKEN }}
run: fundaia deploy shop api
A saved token never travels to another host: --url pointing elsewhere than the profile needs
--token too. Plain http:// is refused except on loopback (FUNDAIA_INSECURE_HTTP=1 overrides).
Updates
The tool updates itself. Once a day it asks crates.io for a newer release (alongside the command,
never before it), and installs it: the release binary when it can be downloaded — its sha256 is
mandatory — and cargo install otherwise, which is what happens today because the assets are
private. The swap is a rename, so the running command finishes on the version it started with.
Notices go to stderr; nothing here can make a command that worked exit non-zero.
Inside CI (CI set) |
Notice only, never installs |
FUNDAIA_NO_SELF_UPDATE=1 |
Notice only — your package manager owns the binary |
FUNDAIA_NO_UPDATE_CHECK=1 |
No check at all |
fundaia upgrade [--check] |
Update now, ignoring the daily cache |
fundaia changelog [<version>|--since <v>|--all] |
What each version brought, compiled into the binary |
fundaia changelog --history |
Which versions have run on this machine (~/.config/fundaia/versions.toml) |
Working on it
FUNDAIA_PERF_BUDGET_MS=150
cli.yml runs formatting, clippy and the tests on every change under cli/; the performance
budgets and the 8 MiB release-binary ceiling run on main, before anything is published.
A new command is finished when it has its --json shape and its row in EFFECT_OF
(src/commands/schema.rs); the platform side — service, REST route, MCP tool — is described in
.claude/rules/surfaces.md.
Releasing
Nobody edits the version by hand. The repository's post-commit hook raises Cargo.toml from the
commit type when a commit touches cli/ (feat minor, ! or BREAKING CHANGE major, anything else
a patch) and stamps CHANGELOG.md, whose entries are written by a person.
A push to main that touches cli/** runs .github/workflows/cli.yml: if the tag
cli-v<version> does not exist yet, it tags, creates the GitHub release, builds the four binaries
with their checksums and publishes the crate. A version already on crates.io is skipped, so a run can
be repeated safely; gh workflow run cli.yml --ref cli-v<version> rebuilds a release from its tag.
Publishing uses CARGO_REGISTRY_TOKEN, scoped to publish-new and publish-update on this crate,
with no expiry. If it is missing the publish step says so and ends green; mint a replacement under
Account settings → API tokens on crates.io and add it to the repository under Settings →
Secrets and variables → Actions. When GitHub Actions cannot
run at all, bun run ship publishes the crate from a laptop (see deploy/README.md).
Licence
MIT.