ReferenceReferenceRuntime seams

Runtime seams

The runtime is a CLI, a Unix socket and files under ~/.memnox/. It listens on no port, issues no token and exposes no HTTP route, and that is a design decision rather than a gap: a governance daemon reachable over the network is a governance daemon somebody else can reach.

There are four ways something talks to it, and all four are local.

1. The local socket

~/.memnox/memnox.sock, owner only, line-delimited JSON. One line in, one line out. It exists because an interceptor runs on every command an agent types, so the cost of asking has to be a connect and a single write.

bash
memnox daemon        # hold the rules in one process

Method

evaluate

Rule on one action. The hot path, and the only one with a latency budget. Takes action, optional target, optional argsDigest.

hold

Ask a person, through whatever terminal the daemon owns.

record

Record what happened, so one piece of work reads as one session.

ping

Liveness. This is what memnox doctor uses to tell a socket file from a running daemon.

A request carries { id, method } and the fields that method needs; a response carries { id, ok } and, for evaluate, the effect, the reason and the alternative when the rule named one.

The daemon is optional for a verdict. An interceptor that cannot reach it evaluates in process against the same files, so stopping the daemon changes latency and no decision. What stops with it is the keeping: on a machine setup reached, the daemon is what hooks an agent installed later and puts a new MCP server through the proxy. See The daemon keeps the boundary.

2. The MCP proxy

Every MCP server can be repointed through Memnox, which then sees tools/list and every tools/call before the server does. It is the seam to reach for first, because every client speaks it.

bash
memnox mcp wrap      # keeps a backup of each config it rewrites
memnox mcp unwrap    # puts them back byte for byte

wrap rewrites each client's MCP config so the server it launches is the proxy, and the proxy launches the real server. Claude Code, Cursor and Codex are handled by name; anything with a standard .mcp.json is handled generically.

What it sees

Method

initialize

Forwarded unchanged. The handshake is the server's, not ours.

tools/list

The manifest is cached and every tool is classified: read, write, destructive, communication or unknown. A hidden tool is filtered out here, so the agent never learns it exists.

tools/call

Ruled on before it reaches the server. Allow forwards it unchanged; ask holds it for a person; deny returns an error the agent can act on.

Everything else, including resources and notifications, is forwarded transparently. The proxy is a gate, not a translation layer.

What a denial looks like

A denied call comes back as a protocol-level error the client already understands, carrying the policy that decided, the reason, and one alternative where the rule named one.

That last part is the difference between an agent that abandons the task and one that takes the other route. A refusal with no way forward gets the gate removed.

Hiding tools

bash
MEMNOX_TOOLS_ALLOW='^(get_|list_|search_)'    # only these are exposed
MEMNOX_TOOLS_DENY='delete|force|purge'        # these are hidden and denied

A hidden tool is filtered out of tools/list and denied if called anyway. Hiding alone would be a lock on a door with the wall missing.

Running it by hand

You normally do not, because memnox mcp wrap points your config at it. When you need to:

bash
memnox-mcp-proxy --name github -- npx -y @modelcontextprotocol/server-github

Part

--name <server-name>

What this server is called in rules and in the timeline. Rules are written as mcp.<server>.<tool>.

MEMNOX_POLICIES

Policy files, comma separated. Without rules the proxy forwards everything, which looks exactly like being protected and is not.

3. The PATH interceptors

A directory of small wrappers at ~/.memnox/bin, one per binary, each two lines that hand off to the real thing once a verdict allows it.

bash
memnox protect --interceptors
memnox run -- claude          # puts that directory first on PATH for the child

Only binaries this machine actually has are wrapped. A wrapper for an absent aws would answer command -v aws and send every script that checks for it down the wrong branch.

4. JSON on the way out

Every command that reports takes --json, and that output is the contract while the human wording is not.

Command

memnox scan --json

The whole capability inventory: agents, servers, tools with their classes, credentials by path and kind, filesystem reach, network posture.

memnox doctor --json

The findings, each with the one change that closes it.

memnox timeline --export jsonl

One event per line, in the frozen event schema. --export bundle signs it.

memnox why --json

The verdict as it was recorded, including the rule and the evidence.

Exit codes

Several commands are meant for a script or a CI step, and say so with an exit code rather than only in prose.

Command

memnox scan --fail-on write-capable

Non-zero when something widened since the last saved scan.

memnox policy check

Non-zero when a rule file exists and will not parse.

memnox policy test '<action>'

Non-zero when the verdict is anything but allow.

memnox check '<intent>'

Non-zero when any action the intent resolves to would stop.