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
The server runs formatting, clippy, the tests, the performance budgets and the 8 MiB release-binary
ceiling (deploy/cli/build.sh) 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.
There is no GitHub Actions. The home server's orchestrator-cli.timer notices a head of main
whose version has no cli-v<version> tag, builds the two Linux binaries with their checksums
(x86_64 natively, arm64 with cargo zigbuild), publishes the GitHub release, which creates the tag,
and then publishes the crate. There are no macOS binaries: on a Mac, cargo install fundaia. A version already on crates.io is skipped, so a release can be repeated
safely; details in deploy/README.md.
Publishing to crates.io reads ~/.orchestrator/crates-io.token on the server, a token scoped to
publish-new and publish-update on this crate. If it is missing the release still happens and the
log says the crate was not published; mint one under Account settings → API tokens on
crates.io.
Licence
MIT.