Open source · local-first · MIT

Don’t start the next chat from zero.

When one coding agent stops, Hermes packs the work on your disk and hands it to the next. Same folder. Same machine.

$ curl -fsSL https://tryhermes.pages.dev/install | sh
Read the docs

Other tools remember forever or plug into MCP. Hermes just carries the work across: this folder, this machine, one command.

app · zsh
claude
✻ Claude Code · ~/src/app
> add rate limiting to POST /api/upload
●I’ll add a token bucket and wire it into the upload route.
●Read(api/upload.ts)
⎿Read 88 lines
●Write(middleware/ratelimit.ts)
⎿Wrote 42 lines
●Update(api/upload.ts)
⎿+6 −1
●Bash(pnpm test ratelimit)
⎿Running…
⎿5 passed, 1 failed
✗ refills the bucket after the window
●The refill test fails: the bucket reads Date.now(). Injecting a clock…
!Context limit reached. Start a new session to continue.
~/src/app main* ❯ hermes handoff claude cursor -m "finish upload rate limit"
packed handoff-20260927T141205
from claude id=7c21a9f0-3b1e-4c2a-9e51-0d3c1b2a7f44
to cursor
copied PROMPT.md → clipboard
next hermes resume cursor
app · Cursor
Refactor auth middleware New Chat
refactor auth middleware to use the session store

Done. Session checks now live in middleware/auth.ts and read from the store.

# Hermes handoff You are continuing work from another coding agent / window. Do not restart from scratch. Use the git state and notes below. ## Goal · finish upload rate limit
Reading the handoff
ReadPROMPT.md
Readgit/diff.patch
Readmiddleware/ratelimit.ts

Picking up from Claude Code on main. The limiter works. The refill test fails because the bucket reads Date.now() directly.

middleware/ratelimit.ts+2 −1
+import { clock } from "../lib/clock";
− const now = Date.now();
+ const now = clock.now();
Runpnpm test ratelimit
6 passed

Done. POST /api/upload is limited to 20 requests a minute per key.

Ask anything, @ to add files
# Hermes handoff
You are continuing work from another coding agent / window. Do not restart from scratch…
## Goal
finish upload rate limit
Agent
PROMPT.md copied to clipboard

Hands off between Claude Code · Codex · Cursor · Cline · Kimi · Antigravity · OpenCode · Pi Agent · Copilot CLI · ZCode · DeepSeek Harness

One rule.

One name is where the work goes. Two names are from, then to.

app · zsh
~/src/app main* ❯ hermes handoff cursor
packed handoff-20260927T141205
from claude id=7c21a9f0-3b1e-4c2a-9e51-0d3c1b2a7f44
to cursor
copied PROMPT.md → clipboard
next hermes resume cursor
To Cursor. Source: the newest chat in this folder.Editor: PROMPT.md goes to your clipboard. Open a new chat and paste.

The rest of the CLI.

Pick the exact chat. Stay in this folder. Resume without globs. Check what Hermes can see.

app · zsh
~/src/app main* ❯ hermes list --here
# claude
# cursor
~/src/app main* ❯ hermes handoff cursor claude --id e188
packed handoff-20260927T141205
from cursor id=e1884976-2f0c-4b7e-9a51-3d0c1b2a7f10
to claude
opened claude (seeded from the pack)
~/src/blog main ❯ hermes handoff codex
packed handoff-20260927T142030
from git only
to codex
opened codex (seeded from the pack)
warn no agent session for this folder; pack is git-only (this is fine). Use --id to pick a chat from another project
next hermes resume codex
~/src/app main* ❯ hermes resume --print
# Hermes handoff
You are continuing work from another coding agent / window. Do **not** restart from scratch. Use the git state and notes below.
## Goal
finish upload rate limit
## Repo
- Path: `~/src/app`
- Branch: `main`
- Came from: `claude`
## Files in play
Read these first. The patch is in `git/diff.patch`.
~/src/app main* ❯ hermes doctor
hermes doctor
✓ git binary ok
✓ git repo ~/src/app (branch main, 3 changed files)
✓ sqlite3 (Cursor DBs) ok
✓ claude 3 session(s)
✓ cursor 2 session(s)
✓ codex 1 session(s)
✗ opencode 0 session(s)
✗ cline 0 session(s)
✗ kimi 0 session(s)
✓ antigravity 1 session(s)
✗ pi 0 session(s)
✗ copilot 0 session(s)
✗ zcode 0 session(s)
✗ deepseek 0 session(s)
✓ home /Users/you
Hermes never writes into Cursor/Claude databases.
You do not need every agent installed to test Hermes.

Things to know.

Hermes is a one-shot messenger. It packs this folder’s work and carries it to the next chat. That is the whole job.

What goes in the pack?

A handoff-<timestamp>/ folder next to your project. PROMPT.md is the brief the next agent reads. The rest is there if it wants to dig.

  • PROMPT.md
  • SUMMARY.md
  • manifest.json
  • git/diff.patch
  • git/log.txt
  • sessions/claude.md
  • DECISIONS.md --decisions
  • files/ --include-files
Do I paste, or does the next agent open?

CLI agents such as Claude Code or Codex start seeded from the pack when they are on your PATH. Editors such as Cursor and Antigravity get PROMPT.md on your clipboard: open a new chat and paste, or type @PROMPT.md. Force either path with --open, --no-open or --copy.

How do I pick one chat out of many?

hermes list --here shows the sessions for this folder. Filter with --agent cursor or -q keyword, then pass --id. A prefix of the id is enough. Without --id, Hermes takes the newest session that belongs to this folder.

Does anything leave my machine?

No. Hermes reads local git and local session files, then writes a folder on disk. No upload, no MCP server, no account.

Does it merge two agents into one history?

No. One agent at a time. Hermes never writes into Cursor or Claude databases and cannot restore an old Cursor composer id. The next agent starts a new chat with the brief.

Install in one line.

macOS and Linux. One binary. No npm, no plugin, no account.

$ curl -fsSL https://tryhermes.pages.dev/install | sh
Then, in a new terminal
$hermes doctor
Not found?
$export PATH="$HOME/.local/bin:$PATH"