Point the CLI at a deployment
Four things decide what a command reaches:
- the server it calls,
- the credential it presents,
- the Redis behind that deployment,
- the axl-config bundle it reads agents, skills, and document sets from.
Typing all four on every command is unworkable, and getting one wrong is worse than typing it. A profile is those four under a name.
The resolution chain
Every one of the four resolves the same way, and the first source that has an answer wins:
flag → environment variable → the profile in use → fallback
axl config showprints each resolved value with the source that supplied it, which shows why each value is set the way it is, without guessing:
Profile
Name: prod (from axl config use)
File: /Users/you/.axl/profiles/prod.json
Resolved settings
api-url: https://axl.internal/api/v1 (profile 'prod')
token: eyJ0eXAi…Gk0fZg (profile 'prod')
redis-url: redis://10.0.0.4:6379 ($REDIS_URL)
config-dir: /Users/you/src/axl/axl-config (discovered)Only one has a default
--api-url falls back to http://localhost:5000/api/v1. The other two destinations have no
built-in default at all.
A wrong API URL fails loudly: nothing answers, and you find out immediately. A wrong Redis
does not. It connects, reads an empty keyspace, writes into it, and reports success - so a
default of redis://localhost:6379 on a machine running Redis on several ports is a way to
ingest a corpus into the wrong database and not notice. The same is true of a config bundle:
point at the wrong one and every command works, against the wrong agents.
So an unset Redis URL or bundle is an error that names every way to set it:
no redis-url is set: pass --redis-url, set REDIS_URL, or store one with
`axl config set redis-url <value> --profile prod`Locating the bundle
The config bundle has one source no default could provide: if nothing names it, the CLI walks
up from the working directory looking for an axl-config directory.
Standing in a checkout selects that checkout's bundle. Nothing is stored, nothing has to be
kept in sync, and several worktrees of the same repository each get their own - which is what
makes axl rag ingest safe to run from whichever tree you happen to be in.
Create and select a profile
# Creates `prod` and stores a server in it
axl config set api-url https://axl.internal/api/v1 --profile prod
axl config set redis-url redis://10.0.0.4:6379 --profile prod
# Mint a credential into it
axl config init --profile prod --user-id you@example.com --role admin \
--jwt-private-key ~/.axl/keys/jwt_private.pem
# Use it for every later command
axl config use prodconfig set and config init are the only commands that may name a profile that does not
exist yet - they are how one comes into existence. For every other command a name that
resolves to nothing is an error, because the alternative is running against the fallback
server and reporting whatever was found there as the profile's truth.
axl config list # every profile, with its server; active and in-use marked
axl config unset redis-url # back to flag or environment
axl config remove stagingWhere it all lives
| Path | Contents |
|---|---|
~/.axl/credentials.json | the profile named default |
~/.axl/profiles/<name>.json | a named profile |
~/.axl/settings.json | which profile axl config use selected |
~/.axl/keys/ | signing and JWT keypairs |
AXL_HOME moves that directory. It is deliberately not AXL_CONFIG_DIR: one names where
your bearer token is kept, the other names a checkout of agents and documents, and a single
variable meaning both is how you end up looking for credentials inside a config bundle.
Profiles hold a bearer token, so they are written owner-only (0600) inside an owner-only
directory. A profile name becomes a file name and is validated as one - letters, digits, -,
_, . - so a name can never place a credential outside that directory.
Several deployments, several checkouts
The two axes are independent:
- Which deployment is a profile decision - a flag,
AXL_PROFILE, oraxl config use. - Which bundle is a directory decision - wherever you are standing.
So a laptop that talks to dev, staging, and prod holds three profiles and switches with one command, while a repository with eight worktrees needs no configuration at all for each to operate on its own bundle.
export AXL_PROFILE=staging # for this shell
axl --profile prod agents list # for this commandPiping the token
axl config token writes the bearer credential alone on stdout. Everything else the CLI
prints goes to stderr, which is what makes this work:
TOKEN=$(axl config token)
curl -H "Authorization: Bearer $TOKEN" http://localhost:5000/api/v1/agentsNext
- Get a credential - keypairs, roles, scopes, and API keys.
- - every
configsubcommand and flag. - Open the diagnostics console -
axl consolehands a profile's credential to the browser.