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#

CodeMeaningTypical causes
0SuccessThe command did what it was asked. --help and --version also exit 0.
1General errorA 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.
2Usage errorAn 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.
3Not foundNo agent with that name; no adapter.toml at the --manifest path.
4Invalid stateThe 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).
5UnsupportedThe 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.
6Timed outsend 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 ;;
esac

Commands 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#

VariableEffect
HEKMA_STATE_DIRUse this state directory instead of the default. Must be an absolute path; a relative path fails with exit code 1.
KTESIO_STATE_DIRThe 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_CHECKSet to any value other than empty, 0, false, no or off to turn off the update check.
KTESIO_NO_UPDATE_CHECKThe older name for HEKMA_NO_UPDATE_CHECK, still honoured.
CIWhen set (to anything but empty, 0, false, no or off), the update check is off.
XDG_DATA_HOMEOn Linux, moves the default state directory to $XDG_DATA_HOME/ktesio.
XDG_CACHE_HOMEWhere the update check keeps its cache file (ktesio/update-check.json). Defaults to ~/Library/Caches on macOS, ~/.cache on Linux and %LOCALAPPDATA% on Windows.
COLUMNSThe 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:NAMERead 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:

SourceWhat the agent receives
Manifest [lifecycle.start] envThose variables, as written.
agent.NAME config keysAn environment variable named NAME with the value. See pass-through keys.
Known config keys such as modelWhatever 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 meteringThe proxy address http://127.0.0.1:<port>, through the adapter's mapping of metering.base_url.
secret:NAME valuesThe resolved secret, in place of the reference.

The built-in kinds map these keys:

Kindmodelmemory.dirmetering.base_url
acpnot mappedHERMES_HOMEOPENAI_BASE_URL
hermes (deprecated)not mappedHERMES_HOMEnot mapped
mockMODELKTESIO_MEMORY_DIRnot 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.