Connecting to a workspace
Everything else in the runtime works with no account, no network and no key,
memnox setup included. This page is the exception, and it does nothing at all
until you run memnox login, which is the one deliberate step towards the cloud.
Memnox on your machine governs the agent. Memnox Cloud governs the team around it. The workspace is added to a protected machine, never required by one, and the rules already on the disk keep being enforced while the workspace is unreachable.
What you get for it
One workspace publishes one set of rules, and every machine in it pulls the same set. That is the whole reason to connect: rules on thirty laptops that stay in step without thirty people editing thirty files.
$memnox login$memnox logout$memnox whoami$memnox sync nowFlag on login
--url <base>--enforce--no-openThe other half of it, in the console
memnox login prints a code and opens the workspace's approval page. Somebody
with admin access there sees the hostname the machine reported and how long the
code is good for, and approves or refuses it. The person who approves becomes
the machine's owner; an operator token approves one as unowned, which is what a
CI runner wants.
After that the machine appears under Machines, and that page is the answer to "what is actually governed here":
Column
Machine
Rules applied
Mode
The same page carries held calls: an agent on a machine nobody is sitting at has nowhere to ask, so its question travels up on the heartbeat and the answer travels back on the next one. That is what makes "ask me only when necessary" true of a VPS and not only of a laptop somebody is sitting at.
Two kinds of enrolment, and they cover different amounts
memnox login enrols the host. memnox setup protects it and needs no
account: it puts the seams in the path, writes a baseline rule set and hands the
daemon to the machine. Run in that order, login and then setup, and setup also
names each agent in the workspace and puts it there. Either way the runtime is
on the machine and an agent running there cannot go around it. That is the one to install
wherever a shell is available.
Where nobody can install into the host, a hosted harness or a container somebody deployed in one click, an agent is enrolled on its own instead and reaches the workspace over MCP. That one is advisory: it asks, and whatever it does without asking is not covered. The fleet records which of the two an agent came in on, because a number that counted a cooperating agent as a gated one is the number nobody should trust.
$memnox agents onboard [agent]The whole of it is on Enrolling an agent: what is written, in what order, and how to undo it.
In the console both start from Machines, and the dialog asks which agent before it asks how you reach it, because the answer to the second decides whether the stronger path is even on offer.
Moving one machine along the ramp
A machine is graduated from the console rather than by somebody reaching every box: off, observe, advise, enforce. Observe records what each rule would have stopped and stops nothing, advise tells the caller the verdict and lets it proceed, and moving to enforce is what somebody does after reading a week of the first.
Both directions, on purpose. Going up is the point; going down is the valve somebody needs when a rule set breaks the build at two in the morning, and it is recorded with who did it, which the alternative of uninstalling is not.
What login writes
~/.memnox/account.json, owner only: the workspace, a machine id, a token scoped
to this machine, and an Ed25519 private key generated here.
The private key never leaves. It signs the batches this machine sends, which is what lets the control plane tell one machine's report from another's without any machine holding a credential that works anywhere else.
Anything that can read that file can act as this machine. That is why it is
0600, and why logout exists.
What is pulled
A rule bundle, written to ~/.memnox/org.policies.json and
~/.memnox/org-conditions.json, where the engine already looks. An unchanged
bundle costs one 304.
It is applied whole or not at all: written to a temporary file, read back through the same loader the gate uses, and renamed into place only once it has parsed. A half-applied rule set is one nobody wrote.
None of this is on the decision path. The gate reads the file the pull wrote, minutes or hours later, with no network anywhere near it. A control plane that is down changes nothing about whether your agent is governed right now.
What authenticates it
TLS and the machine token. The bundle carries no signature of its own, which
is why https is required: --url refuses anything else, loopback aside, and the
check sits in the transport so a hand-edited account file cannot get past it.
What makes that sufficient rather than merely acceptable is the engine. Rules compose most-restrictive-wins, so a pulled rule can only ever tighten what this machine already enforces. A control plane cannot grant your agent anything it did not already have. The worst a bad bundle can do is deny too much, and that is visible the moment somebody tries to work.
Exactly what is sent
Per action, in signed batches of at most 500:
| Field | What it is |
|---|---|
dedupKey, subjectId | the event id, so a resend is deduplicated rather than doubled |
occurredAt, agentSessionId | when, and which session |
surface, operation, classes | shell, git.push-force, destructive |
effect, reason, ruleId | what was decided, and which rule decided it |
resourceRef | what it acted on: a path, a host, a branch |
argsDigest | a hash of the arguments, never the arguments |
exitCode, startedAt | how it ended, and how long it took |
policyHash | the rule set in force at the time |
On the heartbeat, about once a minute: the hash of the bundle this machine has applied. That is what lets a workspace answer "which machines are on which rules" without diffing anything.
What is never sent
Never leaves the machine
The arguments themselves
Transcripts
File contents, credential values
The signing key
The payload is an explicit allow-list in the source rather than the event minus a blocklist. That is the difference that matters over time: a field added to the ledger next year does not start travelling because nobody remembered to exclude it.
When it cannot reach the control plane
Nothing stops. The gate has already answered and the row is already written by the time any of this runs, so a failed send loses a send and never a verdict. The rows stay, and the next pass retries them; the loop backs off from a minute to fifteen while the control plane is unreachable.
A revoked credential stops the loop rather than retrying it, and says so.

