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.
memnox daemon # hold the rules in one processMethod
evaluateholdrecordpingA 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.
memnox mcp wrap # keeps a backup of each config it rewrites
memnox mcp unwrap # puts them back byte for bytewrap 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
initializetools/listtools/callEverything 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
MEMNOX_TOOLS_ALLOW='^(get_|list_|search_)' # only these are exposed
MEMNOX_TOOLS_DENY='delete|force|purge' # these are hidden and deniedA 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:
memnox-mcp-proxy --name github -- npx -y @modelcontextprotocol/server-githubPart
--name <server-name>MEMNOX_POLICIES3. 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.
memnox protect --interceptors
memnox run -- claude # puts that directory first on PATH for the childOnly 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 --jsonmemnox doctor --jsonmemnox timeline --export jsonlmemnox why --jsonExit 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-capablememnox policy checkmemnox policy test '<action>'memnox check '<intent>'
