Coding agents
Govern Claude Code, Codex and Kiro on developer machines with Titan's titand daemon, managed hooks and signed local tool rules, and what this does not cover.
On this page
Titan governs coding agents that run on your developers' Linux machines (including WSL2): Claude Code, Codex CLI and Kiro CLI. A small daemon, titand, binds each machine to your Titan deployment and answers the agent's hooks before each tool call. Developers start their agent the usual way.
During the private preview, Hexel Studio provides titand and your organization's attach descriptor (the file or URL that names your Titan deployment).
What Titan checks on the machine
Before each tool call, the coding agent's hook asks titand. A call is allowed only when all of these hold:
- The machine is enrolled and has a live Titan session.
- The session is not suspended, revoked, quarantined or killed (see Kill switch).
titandhas heard from Titan recently. Offline, it keeps deciding for up to 15 minutes by default (at most 4 hours), then denies.- For Claude Code and Codex, the call passes your signed local tool rules, if you publish any.
If titand isn't running, the agent's tool calls are denied.
Titan's own tools, offered to the agent through the Titan MCP server, are decided by Titan centrally like any other governed action. From a developer machine, only read-only capabilities are offered.
Install
| Agent | Install | Managed (recommended) |
|---|---|---|
| Claude Code | titand claude install --org <descriptor> | sudo titand claude install-managed |
| Codex CLI | titand codex install --org <descriptor> | sudo titand codex install-managed |
| Kiro CLI | titand attach --org <descriptor> | — |
Each install enrolls the machine for that agent with its own key, puts a titand shim ahead of the real binary on PATH (recording the real binary's digest), writes the agent's hook configuration, and registers the Titan MCP server. titand status shows the deployment the machine is bound to.
Managed hooks
Use managed hooks. They are the only mode in which a developer can't simply switch the hooks off.
- Claude Code:
install-managedwrites a drop-in under/etc/claude-code/managed-settings.d/withallowManagedHooksOnly. Your organization's ownmanaged-settings.jsonisn't rewritten. If you deliver Claude Code settings from a server or MDM, those take precedence over the files, so add the same hooks there. - Codex CLI:
install-managedwrites the hooks into/etc/codex/requirements.tomlwithallow_managed_hooks_only = true. - User-level hooks (
installwithout the managed step) live in the developer's own settings, which they can edit or disable. Titan labels this mode as easy to bypass.
To remove the integration, run titand claude uninstall or titand codex uninstall (and sudo titand <agent> uninstall-managed for managed hooks).
Signed local tool rules
Local tool rules let you deny specific built-in tool calls of Claude Code and Codex, such as rm -rf or reading ~/.ssh. Titan signs them, and titand checks the signature and evaluates them on the machine after the checks above. A rule can only turn an allowed call into a denied one. It never overrides a kill or a suspension.
Write the rules
PUT /v1/titan/management/deployments/{id}/local-tool-rules replaces the whole rule set (permission titan:policy:publish; reading needs titan:policy:read):
curl -X PUT https://api.hexelstudio.com/v1/titan/management/deployments/$TITAN_DEPLOYMENT_ID/local-tool-rules \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"default_effect": "allow",
"rules": [
{ "id": "no-rm-rf", "tool_class": "shell", "executable": "rm", "arg_tokens": ["-rf"],
"effect": "deny_with_message", "message": "Deleting recursively is not allowed here." },
{ "id": "no-force-push", "tool_class": "shell", "executable": "git", "arg_tokens": ["push", "--force"], "effect": "deny" },
{ "id": "no-ssh-keys", "tool_class": "file_read", "path_prefix": { "prefix": "~/.ssh", "scope": "outside_workspace" }, "effect": "deny" }
]
}'| Field | Values |
|---|---|
default_effect | allow or deny, for a call no rule matches. Required. |
tool_class | shell, file_write, file_read, network_fetch or mcp |
executable | shell only: the exact program name, such as git |
arg_tokens | shell only: exact arguments that must all be present in the same command |
path_prefix | file_read and file_write only: a prefix with scope inside_workspace (relative path) or outside_workspace (absolute or ~/ path) |
effect | allow, deny, or deny_with_message with a message the agent sees |
A rule matches when the tool class is the same and every matcher it has matches. There are no regular expressions over the raw command text, because quoting and substitution would defeat them. An invalid set is refused with 400 LOCAL_TOOL_RULES_INVALID. At most 256 rules.
Deliver them to machines
- After the
PUT, read the rules withGETuntil the response has abundle. Itsverification_keysare the keys machines must trust. - Add those keys to your attach descriptor as
local_tool_rules_keys, and run the agent'sinstallagain on each machine.
From then on, titand fetches new versions within about a minute after Titan signs them. A signed bundle lasts one day and Titan renews it automatically. A machine that pins keys but has no valid bundle, or whose bundle has expired, denies every built-in tool call.
The Agent Ledger records each rule decision with only the rule id, the bundle generation and the decision. It doesn't record the command, the path or the arguments.
What this does not cover
Coding-agent governance works through the agents' hooks. It is a guardrail, not endpoint protection.
- It doesn't see anything a developer or a process does outside the agent: their own shell, editor, clipboard, network or existing credentials.
- An agent started without its hooks isn't governed: the real binary run by its full path, another profile or configuration without the Titan hooks, or user-level hooks the developer turned off. Codex's
--dangerously-bypass-hook-trustis another such path. - Codex's hosted tools, such as web search, run outside hooks and are never seen by Titan.
- On WSL,
/etc/claude-codecan be writable by the user, so managed hooks there don't resist a user who can write to it. - Local tool rules can't rewrite a call or ask a person to approve it; they only allow or deny. Approvals happen through Titan's own tools, never inside a hook.
What makes going around Titan low-value is that governed tools hold no credentials on the machine: an agent without Titan has nothing to act with on the systems Titan governs.