Connect an agent

Run these commands on the machine where your agent runs.{% if not new_token %} Replace kw_YOUR_AGENT_TOKEN with your saved token.{% endif %}

Any agent: the kw command (recommended)

Works from any shell, waits out phone approvals, and scopes "this session" approvals per conversation. Install the client, store the token, set the agent up:

pipx install keywright
kw login {{ mcp_url | shellquote }} --paste   # then paste the token on its own line
kw setup claude-code      # or: kw setup codex
kw setup check

Agents then run kw resources, kw run <host> -r "why" -- <command>, kw put, kw get and kw tool. kw guide prints the full agent guide.

Codex over MCP

Export the token, then register Keywright:

export KEYWRIGHT_TOKEN={{ (new_token or 'kw_YOUR_AGENT_TOKEN') | shellquote }}
codex mcp add keywright \
  --url {{ mcp_url | shellquote }} \
  --bearer-token-env-var KEYWRIGHT_TOKEN

In ~/.codex/config.toml, set tool_timeout_sec = 180 in the Keywright section to leave time for phone approvals. The section should look like this:

[mcp_servers.keywright]
url = {{ mcp_url | tojson }}
bearer_token_env_var = "KEYWRIGHT_TOKEN"
tool_timeout_sec = 180

Start Codex from the shell where KEYWRIGHT_TOKEN is exported. Set it again in new shells, or supply it through your environment manager. For the IDE extension, the variable must be available to the IDE process. Use /mcp in Codex to check the connection.

Codex MCP documentation ↗

Claude Code over MCP
claude mcp add --transport http keywright \
  {{ mcp_url | shellquote }} \
  --header {{ ('Authorization: Bearer ' ~ (new_token or 'kw_YOUR_AGENT_TOKEN')) | shellquote }}
{% if gateways %}
LLM calls through Keywright (no provider key on the agent's machine)

Point the SDK or the agent at a gateway with the same token; every call names a model, and the model is what you approve. kw llm <gateway> prints these lines from a stored profile.

{% for g in gateways %}
# {{ g.name }}: {{ (g.config.models or []) | join(', ') or 'no models listed yet' }}
export ANTHROPIC_BASE_URL={{ (public_url ~ '/llm/' ~ g.name) | shellquote }}
export ANTHROPIC_AUTH_TOKEN={{ (new_token or 'kw_YOUR_AGENT_TOKEN') | shellquote }}
export OPENAI_BASE_URL={{ (public_url ~ '/llm/' ~ g.name ~ '/v1') | shellquote }}
export OPENAI_API_KEY={{ (new_token or 'kw_YOUR_AGENT_TOKEN') | shellquote }}
{% endfor %}

Unset the real ANTHROPIC_API_KEY / OPENAI_API_KEY there, and rotate them: a key that was ever on the agent's machine is spent.

{% endif %}
Other MCP clients

Use streamable HTTP at {{ mcp_url }} with an Authorization: Bearer <agent token> header.