Skip to Content
Krad ADE
Agents API

Authentication

The bus and lead tokens, the callers and their rights, the KRAD_ADE variables, the api.json discovery file and the security model.

Tokens

The app makes two random 128-bit tokens, written as 32 hex digits, each time it starts, and compares them in constant time.

TokenWho gets it
The bus tokenEvery terminal the app opens, as KRAD_ADE_TOKEN or, on SSH hosts, as an owner-only file named by KRAD_ADE_TOKEN_FILE; it is also written to api.json
The lead tokenKept by the app. An envelope whose from is {"Lead":...} must carry it; with the bus token it is refused with unauthorized ("only a lead the user named can call as a lead"). No terminal receives it: a lead calls as its own terminal and the app recognises it.

The tokens are never logged: the types that hold them print [REDACTED].

Callers

from names the caller, and the app answers according to it.

fromWhoScope and rights
"Client"A program outside the app's terminalsHello, List and ListAll across every open environment, and SubscribeAgents. Anything else is refused with forbidden.
{"Terminal":{"environment":E,"terminal":N}}A terminal or chat of environment E; the app sets KRAD_ADE_TERMINAL=E:NIts own environment and group. Every request except those that direct Workers.
The same, when terminal N is a session's lead chatA leadFor Spawn, Send, Close, CloseSession and PickVariant, and for Read and Wait on its own Workers, the app treats it as the lead of that session. Leads are the only callers allowed to direct Workers; anyone else gets forbidden.
{"Git":"main"}The app's own git credential promptsInternal; only the askpass request

The CLI fills from from KRAD_ADE_TERMINAL inside the app, and with "Client" when it found the endpoint through api.json.

Inside the app's terminals

The app sets these variables in every terminal and chat process it starts:

VariableValue
KRAD_ADE_ENDPOINT127.0.0.1:<port>; on an SSH host, the forwarded address there
KRAD_ADE_TOKENThe bus token, on this computer
KRAD_ADE_TOKEN_FILEThe owner-only file holding the token, on SSH hosts, instead of KRAD_ADE_TOKEN
KRAD_ADE_TERMINALThe caller handle, environment:terminal
PATHPrefixed with the app's own folder, where krad and krad-ade-agents live

The API discovery file

Outside the app's terminals, programs find the API through api.json, which the app leaves in its config folder while it runs: $XDG_CONFIG_HOME/krad-ade, else ~/.config/krad-ade, else %APPDATA%\krad-ade.

api.json
{
  "api_version": 1,
  "endpoint": "127.0.0.1:52144",
  "token": "6f1c0d9e2b7a4c58e3f09a1d7b6c2e40",
  "pid": 48211,
  "started_at": "2026-11-10T09:12:00.000Z"
}
  • It is written atomically, a temporary file renamed into place, and owner-only (0600 on Unix).
  • It is replaced each time the app starts, and removed when the app exits cleanly, but only by the process whose pid it names.
  • Settings › General › "Let other programs find the agents API" turns it on and off. It is on by default, and turning it off removes the file at once.
  • The variables win over the file: the CLI reads api.json only when KRAD_ADE_ENDPOINT and KRAD_ADE_TERMINAL are not set.
  • The static Linux build of the CLI that runs on SSH hosts has no discovery file and only uses the variables.

Stale files

A file left by a crash can name a dead endpoint, or a port another program now holds.

The file isWhen
LiveHello at its endpoint answers with the same pid
StaleNothing answers, or another process does

krad api info makes that check and exits with 2 on a stale file. It prints where the API is and how it was found; --show-token adds the token, and --json prints {"endpoint","api_version","build","discovery_file","token"}, the last two only when they apply.

Terminal
krad api info --json

Security model

The caller is declared, not proven

from is what the client says it is. The token proves the client runs as the user, since it could read the file or a terminal's environment; it does not prove which terminal sent the request. A program holding the token could name any terminal of any environment, a lead's included. The lead token keeps the Lead caller itself out of reach, but the rights the app gives a lead's own terminal follow from the name.

  • Loopback only. Nothing outside this computer can connect, except through the SSH forwards the app itself opens to the hosts of its environments.
  • A token per run. Every request needs the bus token. It reaches only the app's terminals and the owner-only api.json, it changes each time the app starts, and it is never logged.
  • Narrow rights outside. A "Client" caller can only list and watch agents. Turning the discovery file off leaves the API to the app's own terminals.
  • No contents on the wire by default. Agent events and app events carry ids, titles and states, never terminal contents. Reading a screen (Read) or a group's patch (Changes) needs a terminal caller of that environment.

The trade-off is convenience over isolation from other processes of the same user: anything that runs as you can already read your files and your terminals' environments, and the API does not try to protect the app from it. It protects the app from other users and other machines.

On this page