<header> <h1>Hermes Box Lite</h1> <p class="dek">A practical guide to creating, using, backing up, restoring, and repairing isolated agent boxes.</p></header> <div class="callout note"> <span class="ico" aria-hidden="true">i</span> <div class="body"> <div class="title">The operating model</div> <p>Tools are replaceable; state is precious. Claude Code, Codex, Hermes, Executor, and Neovim live in an isolated smolvm VM. User state lives under <code>/data</code> and travels through encrypted backups.</p> </div></div> <div class="page-layout"> <aside class="section-nav" aria-label="On this page"> <p class="label">On this page</p> <nav> <ul> <li><a href="#quick-start">Quick start</a></li> <li><a href="#daily-use">Daily use</a></li> <li><a href="#backup-restore">Backup and restore</a></li> <li><a href="#health-repair">Health and repair</a></li> <li><a href="#configuration">Configuration</a></li> <li><a href="#security">Security model</a></li> <li><a href="#troubleshooting">Troubleshooting</a></li> </ul> </nav> </aside> <div class="page-content"> <section id="quick-start"> <h2>Quick start</h2> <p>Run these commands from the <code>hermes-box-lite</code> repository on macOS, or on x86_64/arm64 Linux with KVM available and your user allowed to access <code>/dev/kvm</code>. Install <code>smolvm</code>, GPG, curl, jq, tar, awk, and standard Bash command-line tools first.</p> <p>On Linux, verify virtualization access before creating a box:</p> <pre><code>test -r /dev/kvm -a -w /dev/kvmsmolvm machine ls</code></pre> <h3>1. Create and verify a box</h3> <pre><code>./box new alpha./box doctor alpha</code></pre> <p>Creation boots Ubuntu with configurable CPU, memory, and a 64 GiB default overlay, installs the toolchain and the latest Hermes release through its official installer, starts Executor, registers its authenticated HTTP MCP endpoint with Claude and Codex, and runs health checks. Hermes begins durably disabled until setup or a migration cutover is complete.</p> <h3>2. Enter and authenticate</h3> <pre><code>./box enter alpha</code></pre> <p>You enter as <code>agent</code> in a persistent tmux session under <code>~/workspace</code>. Authenticate the tools you intend to use:</p> <pre><code>hermes setup --portalclaudecodex</code></pre> <h3>3. Open Executor and save the state</h3> <pre><code>./box open alpha./box save alpha</code></pre> <p><code>box open</code> waits for the authenticated forwarded endpoint, then launches the Executor UI without printing its bearer token. <code>box save</code> quiesces Hermes and Executor, checkpoints and verifies SQLite, excludes transient/native caches and locks, validates and encrypts the archive, then selectively restores the prior service state.</p> </section> <section id="daily-use"> <h2>Daily use</h2> <p>The full command reference (every <code>box</code> subcommand and what it does) lives in <a href="../README.md#commands">the README's Commands table</a> — kept there as the single source of truth so it can't drift out of sync with this page.</p> <h3>Inside the box</h3> <pre><code>hb statushb versionshb doctorhb logs executorhb logs hermeshb verify-statehb acknowledge-active-pathshb cutover-ready</code></pre> <p>The workload supervises Executor and the Hermes gateway without duplicate processes. Doctor is read-only and treats deliberate quiescence as policy, while start and repair remain explicit mutations. Gateway enable requires the full single-writer confirmation phrase printed by <code>hb gateway-enable</code>.</p> </section> <section id="backup-restore"> <h2>Backup and restore</h2> <p>The exact guarantees each of these commands makes — what gets quiesced, validated, excluded, and verified, step by step — are documented once, in <a href="../README.md#backup-and-restore-guarantees">README's Backup and restore guarantees</a>, so they can't quietly drift out of sync with this walkthrough. What follows here is the practical "what do I actually type" version.</p> <h3>Create a backup</h3> <pre><code>./box save alpha</code></pre> <p>By default, this creates <code>backups/alpha-<timestamp>.tar.gz.gpg</code> and refuses to overwrite an existing destination. Set a passphrase in the environment for unattended use:</p> <pre><code>BOX_PASSPHRASE='your-local-secret' ./box save alpha</code></pre> <h3>Restore into a new box</h3> <pre><code>./box load backups/alpha-20260625-120000.tar.gz.gpg beta</code></pre> <p>The archive is decrypted and validated before a VM is even created. The Hermes gateway stays disabled afterward, so a restore rehearsal can never accidentally claim a live messaging identity.</p> <h3>Import from Eventide or another Hermes host</h3> <pre><code>./box import-hermes alpha hermes-backup.zip --map /Users/davis=/data/home/agent</code></pre> <p>Validates and atomically imports native Hermes state with the gateway left disabled. Review the import manifest, run <code>hb acknowledge-active-paths</code>, then require <code>hb cutover-ready</code> before enabling the gateway — see the README link above for exactly what the import does and skips.</p> <h3>Inspect a backup without a VM</h3> <pre><code>./box extract backups/alpha-20260625-120000.tar.gz.gpg</code></pre> <p>Extraction validates the archive and writes to a new directory under <code>backups/</code>. Treat extracted contents as sensitive: they can contain credentials, sessions, private work, and Executor data.</p> <div class="callout warn"> <span class="ico" aria-hidden="true">!</span> <div class="body"> <div class="title">Backups preserve state, not an exact machine</div> <p>Hermes and the other tools are installed independently of box state and can change between image builds. This remains a state backup, not an offline VM image.</p> </div> </div> </section> <section id="health-repair"> <h2>Health and repair</h2> <p>Start with the doctor whenever a box feels partly broken:</p> <pre><code>./box doctor alpha</code></pre> <p>Doctor performs a bounded, authenticated MCP handshake through the guest-local endpoint and, when web exposure is enabled, the forwarded host endpoint. It uses jq to validate the HTTP 200 JSON <code>initialize</code> result, negotiated protocol version, response content type, and session ID, sends the initialized notification, then closes the session best-effort. A bare listener, malformed result, 404, or HTTP 500 response fails health. Without an exposed port, doctor reports the host check as skipped.</p> <p>If managed tools, profiles, or MCP wiring need repair, re-run provisioning:</p> <pre><code>./box repair alpha</code></pre> <p>Repair quiesces Hermes and Executor, refreshes packages and repository-owned guest assets, preserves the installed Hermes layout, resumes the prior service policy, repairs MCP wiring, and runs the doctor.</p> <h3>Remove a box safely</h3> <pre><code>./box rm alpha</code></pre> <p>The command reports whether it can find a recent backup and requires the exact box name as confirmation. For intentional non-interactive deletion:</p> <pre><code>./box rm alpha --force</code></pre> </section> <section id="configuration"> <h2>Configuration</h2> <p>Edit <code>box.env</code> before creating or repairing a box.</p> <div class="table-wrap" role="region" aria-label="Hermes Box Lite configuration" tabindex="0"> <table> <caption>Where each setting lives</caption> <thead> <tr><th scope="col">Topic</th><th scope="col">See</th></tr> </thead> <tbody> <tr><th scope="row">Every setting and its effect</th><td><code>box.env</code> itself — each key has an inline comment, and it's the literal source of truth this page would otherwise just be restating.</td></tr> <tr><th scope="row">Tool installation paths and durable state</th><td><a href="../README.md#tool-installation-and-state">README's Tool installation and state table</a>.</td></tr> </tbody> </table> </div> <p>Provisioning installs a root-owned copy at <code>/etc/hermes-box.env</code>, so guest helpers use the same settings as the host workflow.</p> </section> <section id="security"> <h2>Security model</h2> <ul> <li>The VM has no host filesystem mounts.</li> <li>Executor's forwarded web port is host-loopback-only.</li> <li>Hermes API forwarding is disabled by default and host-loopback-only when enabled.</li> <li>Networking is always enabled for provisioning and agent tools.</li> <li>Claude, Codex, Hermes, Executor, and plugins share one guest account and credential set.</li> <li>The <code>agent</code> user has passwordless sudo inside the guest.</li> <li>Encrypted backups and extracted state should be handled as secret material.</li> </ul> <p>The VM is the host-protection boundary. Tools inside a box are not isolated from one another. A compromised tool, plugin, MCP source, or prompt-injected agent may access the other tools' credentials and workspace.</p> </section> <section id="troubleshooting"> <h2>Troubleshooting</h2> <h3>Executor or MCP is unhealthy</h3> <pre><code>./box doctor alpha./box repair alpha</code></pre> <p>Inside the box, inspect <code>hb status</code> and <code>hb logs executor</code>. Run <code>hb wire-mcp</code> to replace stale legacy stdio wiring with the authenticated HTTP configuration.</p> <h3><code>box open</code> reports success but no browser appears</h3> <p>This is expected on a headless host reached over SSH or Tailscale rather than at its console — see <a href="../README.md#executor-and-mcp">README's Executor and MCP section</a> for how to reach the UI from a separate client machine instead.</p> <h3>An operation says the box is locked</h3> <p>Another mutation may be running. Locks contain an owning PID and stale locks are recovered automatically after that process exits. Do not manually remove a lock while a save, load, repair, or delete is active.</p> <h3>A restore fails before VM creation</h3> <p>The passphrase may be incorrect, or the decrypted archive may be corrupt or unsafe. This failure intentionally occurs before provisioning so it does not leave an orphan VM.</p> <h3><code>box new</code> fails while installing Hermes</h3> <p>Provisioning uses Hermes's current official installer. Check the installer output and upstream release status, then retry once any upstream or network failure is resolved.</p> <h3>Validate the repository</h3> <pre><code>make check</code></pre> <p>This requires ShellCheck, Python 3, and jq, then runs Bash/Python syntax checks, static contracts, protocol-health regressions, encrypted archive round trips, native Hermes ZIP/import safety tests, validation-before-VM tests, cleanup checks, and mock failure rollback.</p> </section> </div></div>
<header>
<h1>Hermes Box Lite</h1>
<p class="dek">A practical guide to creating, using, backing up, restoring, and repairing isolated agent boxes.</p>
</header>
<div class="callout note">
<span class="ico" aria-hidden="true">i</span>
<div class="body">
<div class="title">The operating model</div>
<p>Tools are replaceable; state is precious. Claude Code, Codex, Hermes, Executor, and Neovim live in an isolated smolvm VM. User state lives under <code>/data</code> and travels through encrypted backups.</p>
</div>
</div>
<div class="page-layout">
<aside class="section-nav" aria-label="On this page">
<p class="label">On this page</p>
<nav>
<ul>
<li><a href="#quick-start">Quick start</a></li>
<li><a href="#daily-use">Daily use</a></li>
<li><a href="#backup-restore">Backup and restore</a></li>
<li><a href="#health-repair">Health and repair</a></li>
<li><a href="#configuration">Configuration</a></li>
<li><a href="#security">Security model</a></li>
<li><a href="#troubleshooting">Troubleshooting</a></li>
</ul>
</nav>
</aside>
<div class="page-content">
<section id="quick-start">
<h2>Quick start</h2>
<p>Run these commands from the <code>hermes-box-lite</code> repository on macOS, or on x86_64/arm64 Linux with KVM available and your user allowed to access <code>/dev/kvm</code>. Install <code>smolvm</code>, GPG, curl, jq, tar, awk, and standard Bash command-line tools first.</p>
<p>On Linux, verify virtualization access before creating a box:</p>
<pre><code>test -r /dev/kvm -a -w /dev/kvm
smolvm machine ls</code></pre>
<h3>1. Create and verify a box</h3>
<pre><code>./box new alpha
./box doctor alpha</code></pre>
<p>Creation boots Ubuntu with configurable CPU, memory, and a 64 GiB default overlay, installs the toolchain and the latest Hermes release through its official installer, starts Executor, registers its authenticated HTTP MCP endpoint with Claude and Codex, and runs health checks. Hermes begins durably disabled until setup or a migration cutover is complete.</p>
<h3>2. Enter and authenticate</h3>
<pre><code>./box enter alpha</code></pre>
<p>You enter as <code>agent</code> in a persistent tmux session under <code>~/workspace</code>. Authenticate the tools you intend to use:</p>
<pre><code>hermes setup --portal
claude
codex</code></pre>
<h3>3. Open Executor and save the state</h3>
<pre><code>./box open alpha
./box save alpha</code></pre>
<p><code>box open</code> waits for the authenticated forwarded endpoint, then launches the Executor UI without printing its bearer token. <code>box save</code> quiesces Hermes and Executor, checkpoints and verifies SQLite, excludes transient/native caches and locks, validates and encrypts the archive, then selectively restores the prior service state.</p>
</section>
<section id="daily-use">
<h2>Daily use</h2>
<p>The full command reference (every <code>box</code> subcommand and what it does) lives in
<a href="../README.md#commands">the README's Commands table</a> — kept there as the single
source of truth so it can't drift out of sync with this page.</p>
<h3>Inside the box</h3>
<pre><code>hb status
hb versions
hb doctor
hb logs executor
hb logs hermes
hb verify-state
hb acknowledge-active-paths
hb cutover-ready</code></pre>
<p>The workload supervises Executor and the Hermes gateway without duplicate processes. Doctor is read-only and treats deliberate quiescence as policy, while start and repair remain explicit mutations. Gateway enable requires the full single-writer confirmation phrase printed by <code>hb gateway-enable</code>.</p>
</section>
<section id="backup-restore">
<h2>Backup and restore</h2>
<p>The exact guarantees each of these commands makes — what gets quiesced, validated,
excluded, and verified, step by step — are documented once, in
<a href="../README.md#backup-and-restore-guarantees">README's Backup and restore guarantees</a>,
so they can't quietly drift out of sync with this walkthrough. What follows here is the
practical "what do I actually type" version.</p>
<h3>Create a backup</h3>
<pre><code>./box save alpha</code></pre>
<p>By default, this creates <code>backups/alpha-<timestamp>.tar.gz.gpg</code> and refuses to overwrite an existing destination. Set a passphrase in the environment for unattended use:</p>
<pre><code>BOX_PASSPHRASE='your-local-secret' ./box save alpha</code></pre>
<h3>Restore into a new box</h3>
<pre><code>./box load backups/alpha-20260625-120000.tar.gz.gpg beta</code></pre>
<p>The archive is decrypted and validated before a VM is even created. The Hermes gateway stays disabled afterward, so a restore rehearsal can never accidentally claim a live messaging identity.</p>
<h3>Import from Eventide or another Hermes host</h3>
<pre><code>./box import-hermes alpha hermes-backup.zip --map /Users/davis=/data/home/agent</code></pre>
<p>Validates and atomically imports native Hermes state with the gateway left disabled. Review the
import manifest, run <code>hb acknowledge-active-paths</code>, then require <code>hb cutover-ready</code>
before enabling the gateway — see the README link above for exactly what the import does and skips.</p>
<h3>Inspect a backup without a VM</h3>
<pre><code>./box extract backups/alpha-20260625-120000.tar.gz.gpg</code></pre>
<p>Extraction validates the archive and writes to a new directory under <code>backups/</code>. Treat extracted contents as sensitive: they can contain credentials, sessions, private work, and Executor data.</p>
<div class="callout warn">
<span class="ico" aria-hidden="true">!</span>
<div class="body">
<div class="title">Backups preserve state, not an exact machine</div>
<p>Hermes and the other tools are installed independently of box state and can change between image builds. This remains a state backup, not an offline VM image.</p>
</div>
</div>
</section>
<section id="health-repair">
<h2>Health and repair</h2>
<p>Start with the doctor whenever a box feels partly broken:</p>
<pre><code>./box doctor alpha</code></pre>
<p>Doctor performs a bounded, authenticated MCP handshake through the guest-local endpoint and, when web exposure is enabled, the forwarded host endpoint. It uses jq to validate the HTTP 200 JSON <code>initialize</code> result, negotiated protocol version, response content type, and session ID, sends the initialized notification, then closes the session best-effort. A bare listener, malformed result, 404, or HTTP 500 response fails health. Without an exposed port, doctor reports the host check as skipped.</p>
<p>If managed tools, profiles, or MCP wiring need repair, re-run provisioning:</p>
<pre><code>./box repair alpha</code></pre>
<p>Repair quiesces Hermes and Executor, refreshes packages and repository-owned guest assets, preserves the installed Hermes layout, resumes the prior service policy, repairs MCP wiring, and runs the doctor.</p>
<h3>Remove a box safely</h3>
<pre><code>./box rm alpha</code></pre>
<p>The command reports whether it can find a recent backup and requires the exact box name as confirmation. For intentional non-interactive deletion:</p>
<pre><code>./box rm alpha --force</code></pre>
</section>
<section id="configuration">
<h2>Configuration</h2>
<p>Edit <code>box.env</code> before creating or repairing a box.</p>
<div class="table-wrap" role="region" aria-label="Hermes Box Lite configuration" tabindex="0">
<table>
<caption>Where each setting lives</caption>
<thead>
<tr><th scope="col">Topic</th><th scope="col">See</th></tr>
</thead>
<tbody>
<tr><th scope="row">Every setting and its effect</th><td><code>box.env</code> itself — each key has an inline comment, and it's the literal source of truth this page would otherwise just be restating.</td></tr>
<tr><th scope="row">Tool installation paths and durable state</th><td><a href="../README.md#tool-installation-and-state">README's Tool installation and state table</a>.</td></tr>
</tbody>
</table>
</div>
<p>Provisioning installs a root-owned copy at <code>/etc/hermes-box.env</code>, so guest helpers use the same settings as the host workflow.</p>
</section>
<section id="security">
<h2>Security model</h2>
<ul>
<li>The VM has no host filesystem mounts.</li>
<li>Executor's forwarded web port is host-loopback-only.</li>
<li>Hermes API forwarding is disabled by default and host-loopback-only when enabled.</li>
<li>Networking is always enabled for provisioning and agent tools.</li>
<li>Claude, Codex, Hermes, Executor, and plugins share one guest account and credential set.</li>
<li>The <code>agent</code> user has passwordless sudo inside the guest.</li>
<li>Encrypted backups and extracted state should be handled as secret material.</li>
</ul>
<p>The VM is the host-protection boundary. Tools inside a box are not isolated from one another. A compromised tool, plugin, MCP source, or prompt-injected agent may access the other tools' credentials and workspace.</p>
</section>
<section id="troubleshooting">
<h2>Troubleshooting</h2>
<h3>Executor or MCP is unhealthy</h3>
<pre><code>./box doctor alpha
./box repair alpha</code></pre>
<p>Inside the box, inspect <code>hb status</code> and <code>hb logs executor</code>. Run <code>hb wire-mcp</code> to replace stale legacy stdio wiring with the authenticated HTTP configuration.</p>
<h3><code>box open</code> reports success but no browser appears</h3>
<p>This is expected on a headless host reached over SSH or Tailscale rather than at its console — see <a href="../README.md#executor-and-mcp">README's Executor and MCP section</a> for how to reach the UI from a separate client machine instead.</p>
<h3>An operation says the box is locked</h3>
<p>Another mutation may be running. Locks contain an owning PID and stale locks are recovered automatically after that process exits. Do not manually remove a lock while a save, load, repair, or delete is active.</p>
<h3>A restore fails before VM creation</h3>
<p>The passphrase may be incorrect, or the decrypted archive may be corrupt or unsafe. This failure intentionally occurs before provisioning so it does not leave an orphan VM.</p>
<h3><code>box new</code> fails while installing Hermes</h3>
<p>Provisioning uses Hermes's current official installer. Check the installer output and upstream release status, then retry once any upstream or network failure is resolved.</p>
<h3>Validate the repository</h3>
<pre><code>make check</code></pre>
<p>This requires ShellCheck, Python 3, and jq, then runs Bash/Python syntax checks, static contracts, protocol-health regressions, encrypted archive round trips, native Hermes ZIP/import safety tests, validation-before-VM tests, cleanup checks, and mock failure rollback.</p>
</section>
</div>
</div>