docs · reference
Exit codes and environment#
Every hekma command exits with one of seven codes, so a script can branch on the kind of failure without reading stderr. This page lists the codes with every condition that produces each, then the environment variables Hekma reads and the ones it passes to agents.
Exit codes#
| Code | Meaning | Typical causes |
|---|---|---|
0 | Success | The command did what it was asked. --help and --version also exit 0. |
1 | General error | A launch failure (the agent is now failed), including the mock kind (no launch command) and an acp agent without acp.command; an invalid or unreadable adapter.toml; a manifest whose contract major version this Hekma does not speak; an adapter with no capabilities or no metering source; an invalid value for a budget, breach action or price key; a secret:NAME that cannot be resolved; a secrets.toml readable by other users; an engine-observed agent that cannot start its proxy; a filesystem or state database error; the state database staying busy for 5 seconds because another command holds it (retry); a failed self-update. Any error not listed elsewhere also exits 1. |
2 | Usage error | An unknown flag or a missing argument; an invalid agent name; an unknown --kind (adapter or memory backing); an unknown config key outside agent.; config get of a key with no value; a name that is already registered. |
3 | Not found | No agent with that name; no adapter.toml at the --manifest path. |
4 | Invalid state | The agent is not in a state that allows the command: start on a running agent, stop on a stopped one, send to an agent that is not running; remove of a running agent without --force; memory attach or detach while the agent is not registered, stopped or failed; attaching a different memory kind over an existing one; a stop that could not confirm the process died; a second send to an acp agent while a prompt turn is in progress; another command changed the agent's state first (retry); a memory attach or detach raced a start (nothing launched; retry). |
5 | Unsupported | The agent's capability declaration rules the command out on this OS (pause or send declared unsupported); resume of a paused agent whose declaration now reads unsupported; send to a running agent when this command holds no input pipe for it, which in 0.11.0 is every such send from the CLI (see send); start --detach of an engine-observed agent. |
6 | Timed out | send to an agent that did not read its input in time. |
The codes are a stable interface, covered by the same compatibility rule as the JSON documents: a code's meaning changes only in a major release, announced ahead in the release notes.
A script branches on the code directly:
hekma agent show worker --json > status.json
case $? in
0) ;; # status.json is valid
3) hekma agent register worker --manifest "$HOME/agents/worker" ;;
4) echo "worker is in the wrong state for that" >&2 ;;
*) echo "unexpected failure" >&2; exit 1 ;;
esacCommands that print to stdout stop cleanly when the reader goes away, so hekma agent logs NAME --json | head -5 exits 0.
Environment variables Hekma reads#
| Variable | Effect |
|---|---|
HEKMA_STATE_DIR | Use this state directory instead of the default. Must be an absolute path; a relative path fails with exit code 1. |
KTESIO_STATE_DIR | The older name for HEKMA_STATE_DIR, still honoured. If both are set they must name the same path, or every command fails with exit code 1. |
HEKMA_NO_UPDATE_CHECK | Set to any value other than empty, 0, false, no or off to turn off the update check. |
KTESIO_NO_UPDATE_CHECK | The older name for HEKMA_NO_UPDATE_CHECK, still honoured. |
CI | When set (to anything but empty, 0, false, no or off), the update check is off. |
XDG_DATA_HOME | On Linux, moves the default state directory to $XDG_DATA_HOME/ktesio. |
XDG_CACHE_HOME | Where the update check keeps its cache file (ktesio/update-check.json). Defaults to ~/Library/Caches on macOS, ~/.cache on Linux and %LOCALAPPDATA% on Windows. |
COLUMNS | The width tables are fitted to, between 40 and 132 characters. Without it Hekma asks the terminal. |
HEKMA_LOGS_BACKLOG_LINES (Unreleased: after 0.11.0) | How many lines written between commands hekma agent logs --follow prints first. Default 200. |
The name in any secret:NAME | Read at start, and by config get --reveal, to resolve the secret. See secrets. |
Without an override, the state directory is the platform data directory for an app named ktesio: ~/Library/Application Support/ktesio on macOS, ~/.local/share/ktesio on Linux, and %APPDATA%\ktesio\data on Windows.
An agent started by Hekma inherits the environment of the command that started it. This matters for detached agents: the variables in your shell when you run hekma agent start --detach are the ones the agent keeps.
Update checks#
Every command except self-update may check GitHub for a newer Hekma release. It checks at most once an hour, caching the answer, and when a newer release exists prints one line on stderr suggesting hekma self-update. It never changes stdout. The check is off when HEKMA_NO_UPDATE_CHECK, KTESIO_NO_UPDATE_CHECK or CI is set to a true value.
What Hekma passes to agents#
Hekma does not add fixed variables of its own to an agent's environment. Everything it passes comes from the adapter, the agent's config, or one of two engine-set values, and it reaches the agent only where the adapter maps it:
| Source | What the agent receives |
|---|---|
Manifest [lifecycle.start] env | Those variables, as written. |
agent.NAME config keys | An environment variable named NAME with the value. See pass-through keys. |
Known config keys such as model | Whatever the adapter maps them to: an environment variable, a command-line flag or a file in the Agent Home. |
Memory backing (filesystem) | The memory/ folder's path, through the adapter's mapping of memory.dir. |
engine-observed metering | The proxy address http://127.0.0.1:<port>, through the adapter's mapping of metering.base_url. |
secret:NAME values | The resolved secret, in place of the reference. |
The built-in kinds map these keys:
| Kind | model | memory.dir | metering.base_url |
|---|---|---|---|
acp | not mapped | HERMES_HOME | OPENAI_BASE_URL |
hermes (deprecated) | not mapped | HERMES_HOME | not mapped |
mock | MODEL | KTESIO_MEMORY_DIR | not mapped |
So an acp agent with a filesystem memory backing gets HERMES_HOME pointing at its memory folder, whatever agent it is. Without a backing, no HERMES_HOME is set and the agent uses its own default.
The agent's working directory is its Agent Home. Its stdout and stderr are captured to log files there. Its stdin is a pipe only when the agent declares interaction support and was started without --detach; otherwise stdin is closed.
KTESIO_USAGE is not an environment variable. It is the prefix of the line an agent prints to report its own usage; see Meter token usage.
Read next#
- CLI reference: each command's errors in context.
- JSON output: the documents to parse when a command succeeds.
- Config keys: the keys that become agent environment variables.
- Troubleshooting: what to do about common failures.