Skip to main content
The workspace image ships languages, runtimes and the agent CLIs (see Preinstalled Toolchain). Everything else — Fly, Infisical, Doppler, Vercel, Supabase, a cloud SDK — follows one pattern. There is no per-vendor switch to flip.
  1. Install the CLI in setup, into ~/.local/bin.
  2. Give it a token as a project environment variable. Every mainstream CLI reads its token from the environment without an interactive login.
  3. Wrap services that need it in terminals.

Where things live

  • ~/.local/bin is on the PATH of the agent, of setup and setup_on_boot, and of every terminals entry, so the agent calls the CLI by name. It is inside your home directory, which is the project volume: a seed build that ran setup once keeps the install for every later boot that skips setup. Nothing under it needs root.
  • /usr/local and other system paths are the VM’s root filesystem, which is not kept across boots that skip setup. An installer that defaults to /usr/local/bin must be pointed at your home directory instead — most take an install directory as an environment variable or a flag.
  • Project environment variables are injected before setup_on_boot, before terminals start and before the agent starts, so all three see the token.

Example: Fly and Infisical

.aether/environment.json:
Two details of that file matter. The Fly installer is a curl … | sh pipeline, so it runs under bash -o pipefail: a failed download fails setup instead of letting the seed cache a workspace without Fly. And infisical run does not exchange a machine identity’s client credentials for a token itself, so the terminal does the exchange first with infisical login --method=universal-auth and only starts the dev server once it has a token — a wrong identity fails the login, and the service does not start. Tokens, set once per project:
Omitting --value prompts for the value, so it never lands in your shell history. From the next task on, fly deploy, fly logs, fly ssh console and infisical secrets work for the agent as they would for you, and the dev server starts with the dev environment’s secrets in its process environment.

Tokens other CLIs read

GitHub needs none of this: every task already carries a repository-scoped token and a configured gh (see GitHub integration).

What the agent can do with the token

A token in the project environment is readable by the agent and by anything it runs. The CLI makes that power concrete: a Fly deploy token means the agent can deploy; an Infisical identity with write access means it can change secrets. Scope tokens to exactly what a task should be able to do — a Fly token to one app, an Infisical machine identity to one project and one environment — and give them an expiry. Values are masked in setup output and never shown by aether env list.

Notes

  • Installing a CLI needs no secrets, so it belongs in setup, which the seed caches. Changing .aether/environment.json invalidates the seed, and the next boot runs setup again.
  • A CLI that insists on an interactive login is not usable in a task. All of the CLIs above accept a token from the environment; prefer that path.
  • Pin versions where it matters to you (@infisical/cli@x.y.z); the seed otherwise captures whatever the installer fetched when it last ran.