Skip to main content

hermes-pubky

Run a Hermes agent whose saved state lives on your own Pubky homeserver. The laptop becomes a working copy, but the agent belongs to you.

Why

Hermes keeps everything it knows in one directory on one machine: SOUL.md, your memories, its learned skills, your conversations. New laptop, fresh container, throwaway VM, and the agent starts from nothing. The usual alternative is a memory SaaS, which makes your agent portable by moving it into someone else's account.

This is a third option. The homeserver holds the authoritative copy of the agent, a local Hermes reconstructs a working copy, runs it, and saves changes back. What travels:

  • instructions (SOUL.md), user and agent memories
  • learned skills and their assets
  • allowlisted settings
  • the conversation database, including tool calls, compaction and rewind history
  • a designated workspace: notes, references, outputs

What stays on the machine: API keys, OAuth sessions, the Pubky grant itself, and anything else machine-specific.

Install

uv pip install hermes-pubky==0.2.1 "hermes-agent==0.19.0"
hermes-pubky agent init default
hermes-pubky run default

Needs Python 3.11–3.13, Hermes 0.19.0 exactly, and a Pubky homeserver on v0.11 or later. agent init asks Pubky Ring to authorize one scoped capability, then publishes the agent's first checkpoint.

On a second computer:

uv pip install hermes-pubky==0.2.1 "hermes-agent==0.19.0"
hermes-pubky agent attach pubky://<owner>/priv/hermes.pubky.app/v2/agents/default/head.json
hermes-pubky run default

Nothing is copied between machines. attach downloads the instructions, memories, skills, settings and conversation database; workspace documents are fetched when the agent asks for them. Every run saves a checkpoint when it ends, and the next run on any machine starts from the newest one.

Hermes plugin packaging

plugin/ is the directory-plugin wrapper for catalog distribution. It declares the pinned hermes-pubky package dependency, which includes the native Pubky extension, and adds /pubky setup help when enabled. Managed agents still start through hermes-pubky run; enabling the companion does not sync an ordinary Hermes profile or select its memory provider.

Once this directory is published in the repository, install it with:

hermes plugins install MCarlomagno/hermes-pubky/plugin
hermes plugins enable hermes-pubky

Hermes 0.19.0 only copies the plugin directory; it does not install its Python dependencies automatically. Use the pip installation above in that environment. Newer installers can read plugin/pyproject.toml, but the managed launcher still requires Hermes 0.19.0 exactly. Use a separate environment if needed. The installer also displays setup instructions.

For a catalog submission, set subdir: plugin and requires_hermes: "==0.19.0". Keep the wrapper's manifest version, project version, and exact package dependency aligned with the published release. The wrapper never downloads or updates code at import time.

Commands

hermes-pubky run <id> [--resume SESSION] [--offline] [--query TEXT]

hermes-pubky agent init <id> [--from-hermes-home PATH] [--workspace PATH]
hermes-pubky agent attach <pubky-uri>
hermes-pubky agent list
hermes-pubky agent status <id> [--json] [--offline]
hermes-pubky agent login <id>
hermes-pubky agent logout <id>
hermes-pubky agent sync <id> [--prefer local|remote]
hermes-pubky agent files <id> list|fetch|import|remove
hermes-pubky agent history <id>
hermes-pubky agent restore <id> <snapshot-id>

hermes-pubky template init|inspect|publish <directory>
hermes-pubky template adopt <agent-id> <pubky-uri>
hermes-pubky template update <agent-id>

agent sync seals whatever changed locally, including files added by hand or with agent files import, then publishes everything pending. agent logout revokes the grant at the homeserver and says so only when that succeeded.

Exit codes: 0 done, 1 usage, 2 saved locally but not yet on the homeserver, 3 conflict, 4 authorization needed, 5 quota, 6 integrity or unsupported runtime.

What it can reach

agent init requests one capability:

/priv/hermes.pubky.app/v2/agents/<id>/:rw

Read and write inside that agent's own directory. No root capability, no access to your other apps. The launcher also refuses paths outside that directory locally, before a request leaves the process, and keeps the grant out of the Hermes child's environment entirely.

Publishing a template needs its own separate capability under /pub/. An agent's grant can never publish.

A grant holds one session at a time. Authorize each computer with its own agent login rather than copying a grant between machines, or each will keep signing the other out.

Read this before you store anything

Your homeserver operator can read your agent. /priv is access-controlled, not encrypted. If you self-host, that operator is you, otherwise assume whoever runs your homeserver can read your instructions, memories and conversations. Credentials are never uploaded, but a conversation can contain anything you or a tool put in it.

One writer at a time. Read from as many machines as you like, but stop and sync on one before writing from another. If the homeserver's checkpoint moved while this machine has unsaved work, run stops before starting the agent, installs nothing over your work, and asks you to choose with agent sync --prefer local|remote; whichever side you drop is preserved under recovery/ first.

Offline works. Startup seals anything a previous run left unsaved, then refreshes from the homeserver with a five-second budget. Offline runs chain their checkpoints, survive restarts, and publish in order at the next sync, retrying with backoff capped at 60 seconds. A run that could not reach the homeserver exits 2 and says saved locally; not yet saved to homeserver. A run whose conversation database cannot be captured exits 6 and does not claim anything was saved.

A cold attach downloads the conversation database in full. It is streamed and reassembled on disk, never held in memory, but a large history takes time. Workspace documents stay remote until requested.

History is kept. Older checkpoints remain recoverable and count against your homeserver quota. Removing a file drops it from the current inventory, not from history; this is not secure erasure.

Not in 0.2: multi-device merge, client-side encryption, portable credentials, semantic retrieval, Windows wheels, and harnesses other than Hermes 0.19.0.

How it fits together

hermes-pubky run <id>
  -> read and verify the remote checkpoint
  -> materialize a dedicated HERMES_HOME and workspace
  -> start Hermes as a child, with HERMES_HOME set before it imports
       -> the in-process plugin reports changes and serves two workspace tools
  -> the supervisor owns the lock, the journal and every network call
  -> final capture and sync after the child exits

Storage is content-addressed. A checkpoint is an immutable snapshot document naming immutable objects; only head.json is mutable, and it moves last, after every object it names has been verified as recorded. The homeserver offers no conditional write, so this is ordering, not a lock: concurrent writers remain unsupported and are detected rather than merged.

Locally, the journal tracks one base: the checkpoint the working copy corresponds to. Sealing a checkpoint advances it, installing one advances it, publishing never does. That is what lets a second run continue the first and offline runs form a chain.

/priv/hermes.pubky.app/v2/agents/<id>/{head,snapshots/*,objects/*}.json
/pub/hermes.pubky.app/v2/templates/<id>/{head,snapshots/*,objects/*}.json

Markdown is stored as Markdown and JSON as JSON, so what is on your homeserver is readable there. Files over 1 MiB, and the database always, are split into 1 MiB chunks.

Development

uv venv --python 3.11 .venv
uv pip install --python .venv/bin/python maturin pytest "hermes-agent==0.19.0"
PYO3_PYTHON="$PWD/.venv/bin/python" .venv/bin/maturin develop

.venv/bin/pytest        # Python tests; the Hermes ones skip if it is absent
cargo test --lib        # Rust unit tests

tests/test_supervisor.py runs the whole launcher against a fake homeserver and a stand-in child: two runs in a row, an attach on a second machine, offline chains, a moved head over local edits, a corrupt database, a failed restore. Those are the scenarios that matter; the rest of the suite guards the wire format and the policy boundaries.

The end-to-end and acceptance suites need PostgreSQL for the homeserver and the well-known testnet ports free:

docker run -d --name hermes-pubky-pg \
  -e POSTGRES_USER=test_user -e POSTGRES_PASSWORD=test_pass -e POSTGRES_DB=postgres \
  -p 5432:5432 postgres:18-alpine

export TEST_PUBKY_CONNECTION_STRING="postgres://test_user:test_pass@localhost:5432/postgres?pubky-test=true"
cargo test --test v2 -- --ignored --test-threads=1

A real managed Hermes turn, against a local fake model so no credentials are needed:

python scripts/check_managed_hermes_integration.py

The full recovery scenario through the shipped command line, one agent across two machines, ending with the grant revoked (so each run needs a fresh fixture):

cargo run --example testnet_fixture > /tmp/fixture.json &
HERMES_PUBKY_TESTNET=1 python scripts/check_managed_handoff.py --fixture /tmp/fixture.json

Pinned upstream versions, changed only as a deliberate compatibility decision with tests to match:

Hermes hermes-agent==0.19.0, conversation schema 22
Pubky SDK v0.11.0 commit 6a14bdb8fa2e30ef4e4b241fcdd3992c453d2378

Cargo.lock is committed. tests/test_hermes_contract.py holds the upstream contract as executable tests and fails if the installed package drifts from it.

License

MIT

Metadata

Release files for hermes-pubky 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hermes-pubky 0.2.1
File Size Uploaded
hermes_pubky-0.2.1.tar.gz 191.7 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for hermes-pubky 0.2.1
File Interpreter ABI Platform
hermes_pubky-0.2.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 abi3 Linux glibc 2.17+ x86-64 Details
hermes_pubky-0.2.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.11 abi3 Linux glibc 2.17+ ARM64 Details
hermes_pubky-0.2.1-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl CPython 3.11 abi3 macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64 Details

Total release size: 17.5 MB

Release files / hermes_pubky-0.2.1.tar.gz

Download URL hermes_pubky-0.2.1.tar.gz
Size 191.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e6b527ca25caf5723856876271a23bb35e53208c5f4eb18de01837e02691cc67
BLAKE2b-256 checksum
How to use checksums
fd6f83adba55a5766fe42fa9f8258449010785ba0b0a42f368ba0a672054c77a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / hermes_pubky-0.2.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL hermes_pubky-0.2.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 4.6 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
7c11e87bac2b352b67eb27c406e556c90102c34ab2effb8fefa83aca92aeca7c
BLAKE2b-256 checksum
How to use checksums
c99c72ec66e661de2f8f9060dabdb3088c597de099d689546869dd00195533f2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / hermes_pubky-0.2.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL hermes_pubky-0.2.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 4.3 MB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
4d1c11ccf33ae3655b51ef85b6d1484cd5381b09be495d0a00392697fcdf86e0
BLAKE2b-256 checksum
How to use checksums
735ab83efea311c205ce4bbaad6e7b4f254c1ba47e9862d98dc50778c4b20ceb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / hermes_pubky-0.2.1-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl

Download URL hermes_pubky-0.2.1-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Size 8.4 MB
Tags CPython 3.11 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e972da812ba0769ded7d3d92522dfdf611a36fac25147eed695e533eab33ded8
BLAKE2b-256 checksum
How to use checksums
0a8578ea81766d288ff26058b340a8b420bf8f5b336ed22965b851c34cc56ee8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.3

4 release files

0.2.2

4 release files

This release

0.2.1 This release

4 release files

0.2.0

4 release files

0.1.0

4 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page