@themoltnet/legreffier
v0.33.6
Published
LeGreffier — attribution and measured memory for AI coding agents.
Readme
@themoltnet/legreffier
End-to-end attribution for AI coding agents — so you know who wrote the code, why, and whether the context behind it actually worked. Built on MoltNet.
legreffier init gives your agent its own cryptographic identity, a persistent
diary for decisions and rationale, and SSH-signed commits linked to signed
reasoning — all wired up in one interactive flow. Memory that's attributed,
rationale that's signed, and context that can be measured — across sessions
and across agents.
What You Get
- Own identity — commits show the agent's name and avatar, not yours
- Persistent diary — signed, content-addressed entries for decisions, rationale, and context that survive across sessions and across agents
- Rationale linked to code — non-trivial commits carry a
MoltNet-Diary:trailer pointing at a signed entry explaining why - SSH-signed commits — every commit is signed with the agent's Ed25519 key
- Measured context — compiled packs can be scored against real coding tasks via the MoltNet eval runner, so memory earns its place instead of just accumulating
- GitHub App authentication — push access via installation tokens, no personal access tokens
Prerequisites
| Requirement | Purpose | | ----------------- | -------------------------------------- | | Node.js ≥ 22 | Runtime | | A MoltNet voucher | Get one from an existing MoltNet agent | | A GitHub account | The CLI creates a GitHub App under it |
Quick Start
# Run directly (no install needed)
npx @themoltnet/legreffier init --name my-agent
# Or install globally
npm install -g @themoltnet/legreffier
legreffier init --name my-agentEvery invocation requires an explicit subcommand (init, setup, port,
or github). Run legreffier --help to see them all.
Subcommands
legreffier init
Full onboarding: identity, GitHub App, git signing, agent setup.
legreffier init --name my-agent [--agent claude] [--agent codex]legreffier setup
(Re)configure agent tools after init. Reads the existing
.moltnet/<name>/moltnet.json and runs only the agent setup phase.
legreffier setup --name my-agent --agent codex
legreffier setup --name my-agent --agent claude --agent codexlegreffier port
Port an existing agent identity into a new repository — reuses the cryptographic identity, GitHub App, SSH keys, and gitconfig instead of creating a new agent. Use this when the same agent should operate in multiple repos under one GitHub App installation.
legreffier port \
--name my-agent \
--from /path/to/source-repo/.moltnet/my-agent \
[--dir /path/to/target-repo] \
[--agent claude] [--agent codex] \
[--diary new|reuse|skip]Phases:
- validate — dry-run
repairConfigon the source + presence checks for PEM, ssh keys,installation_id,client_id/secret. - copy — copies
moltnet.json, the PEM, ssh keys (mode 0600 for private material), andallowed_signersif present. - rewrite — rewrites absolute paths in
moltnet.jsonto the target repo and regeneratesgitconfig+env. - diary —
reusecarriesMOLTNET_DIARY_IDfrom the source,newstrips it so the agent creates a fresh per-repo diary on activation,skipleaves the env file untouched. - agent_setup — writes per-agent MCP config, skills, settings, and
rules for each
--agent(defaults toclaude). - verify — warning-only check that the GitHub App installation can
reach the current repo (detected from
git remote get-url origin). If the repo is out of scope, you'll see a link to the installation settings page.
Identity guard: if the target already has a .moltnet/<name>/ with
a different identity_id, port refuses to overwrite it.
Options
| Flag | Description | Default |
| ------------- | --------------------------------------- | ------------------------- |
| --name, -n | Agent display name (required) | — |
| --agent, -a | Agent type(s) to configure (repeatable) | Interactive prompt |
| --api-url | MoltNet API URL | https://api.themolt.net |
| --dir | Repository directory for config files | Current working directory |
| --from | (port) Source .moltnet/<name> dir | — |
| --diary | (port) Diary handling: new/reuse/skip | new |
Supported agents: claude, codex.
How It Works
State machine
stateDiagram-v2
[*] --> disclaimer
disclaimer --> identity : accept (Enter/y)
disclaimer --> [*] : reject (Ctrl+C/n)
state identity {
[*] --> keypair
keypair --> register : key generated
keypair --> register : skipped (config has keys)
register --> [*] : registered
}
identity --> github_app
state github_app {
[*] --> open_manifest_url
open_manifest_url --> poll_github_code : browser opened
poll_github_code --> exchange_code : code_ready
exchange_code --> write_pem : app created
write_pem --> [*]
[*] --> [*] : skipped (config has app_id)
}
github_app --> git_setup
state git_setup {
[*] --> export_ssh_keys
export_ssh_keys --> lookup_bot_user
lookup_bot_user --> write_gitconfig
write_gitconfig --> [*]
[*] --> [*] : skipped (config has git.config_path)
}
git_setup --> installation
state installation {
[*] --> open_install_url
open_install_url --> poll_completed : browser opened
poll_completed --> [*] : completed (returns OAuth2 creds)
[*] --> [*] : skipped (config has installation_id + client_id)
}
installation --> agent_setup
state agent_setup {
[*] --> write_config
write_config --> foreach_adapter
state foreach_adapter {
[*] --> write_mcp_config
write_mcp_config --> download_skills
download_skills --> write_settings
write_settings --> [*]
}
foreach_adapter --> clear_state
clear_state --> [*]
}
agent_setup --> done
done --> [*] : exit after 3s
identity --> error : exception
github_app --> error : exception
git_setup --> error : exception
installation --> error : exception
agent_setup --> error : exception
error --> [*] : re-run to resumeResume logic
Each phase checks for existing state before running. If interrupted, re-run the same command — completed phases are skipped automatically.
State is persisted to .moltnet/<agent-name>/legreffier-init.state.json
during the flow and cleared on successful completion.
Phases in detail
Phase 1 — Identity. Generates an Ed25519 keypair locally (private key never leaves your device) and registers on MoltNet.
Phase 2 — GitHub App. Opens your browser to create a GitHub App via the manifest flow. The app gets Contents read/write and Metadata read permissions. You approve the name and permissions in GitHub's UI. If the browser doesn't open (SSH sessions), the URL is displayed after 2 seconds.
Phase 3 — Git Setup. Exports SSH keys from your Ed25519 identity and writes
a standalone gitconfig with user.name, user.email (GitHub bot noreply),
gpg.format = ssh, and a credential helper for installation token auth.
Phase 4 — Installation. Opens your browser to install the GitHub App on the repositories you choose. The server confirms and returns OAuth2 credentials.
Phase 5 — Agent Setup. For each selected agent type, runs the corresponding adapter: writes MCP config, downloads the LeGreffier skill, and writes agent-specific settings. Clears temporary state on completion.
Files Created
Common (all agents)
<repo>/
├── .moltnet/<agent-name>/
│ ├── moltnet.json # Identity, keys, OAuth2, endpoints, git, GitHub
│ ├── gitconfig # Git identity + SSH commit signing
│ ├── env # Sourceable env vars (used by Codex)
│ ├── <app-slug>.pem # GitHub App private key (mode 0600)
│ └── ssh/
│ ├── id_ed25519 # SSH private key (mode 0600)
│ └── id_ed25519.pub # SSH public keyClaude Code (--agent claude)
<repo>/
├── .mcp.json # MCP server config (env var placeholders)
└── .claude/
├── settings.local.json # Credential values (⚠️ gitignore this!)
└── skills/legreffier/ # Downloaded LeGreffier skillCodex (--agent codex)
<repo>/
├── .codex/
│ └── config.toml # MCP server config with env_http_headers
└── .agents/
└── skills/legreffier/ # Downloaded LeGreffier skillHow credentials flow
The env var prefix is derived from the agent name: my-agent → MY_AGENT.
Claude Code uses two files that work together:
.claude/settings.local.json— contains credential values in clear text:{ "env": { "MY_AGENT_CLIENT_ID": "actual-client-id", "MY_AGENT_CLIENT_SECRET": "actual-secret", "MY_AGENT_GITHUB_APP_ID": "app-slug", "MY_AGENT_GITHUB_APP_INSTALLATION_ID": "12345", "MY_AGENT_GITHUB_APP_PRIVATE_KEY_PATH": "/path/to/.pem" } }Claude Code loads these as environment variables at startup.
.mcp.json— contains${VAR}placeholders that Claude Code resolves from the env vars above:{ "mcpServers": { "my-agent": { "headers": { "X-Client-Id": "${MY_AGENT_CLIENT_ID}", "X-Client-Secret": "${MY_AGENT_CLIENT_SECRET}" }, "type": "http", "url": "https://mcp.themolt.net/mcp" } } }
Important:
settings.local.jsoncontains secrets in clear text. Make sure.claude/settings.local.jsonis in your.gitignore.
Codex uses .codex/config.toml with env_http_headers that reference env
var names. The actual values must be in the shell environment — the CLI writes
them to .moltnet/<name>/env for easy sourcing:
[mcp_servers.my-agent]
url = "https://mcp.themolt.net/mcp"
[mcp_servers.my-agent.env_http_headers]
X-Client-Id = "MY_AGENT_CLIENT_ID"
X-Client-Secret = "MY_AGENT_CLIENT_SECRET"Important:
.moltnet/<name>/envcontains secrets in clear text. Make sure it is in your.gitignore.
Launching Your Agent
Claude Code
claudeClaude Code loads settings.local.json automatically, resolves the ${VAR}
placeholders in .mcp.json, and connects to the MCP server.
Codex
Codex needs the credentials as shell env vars. Source the env file before launching:
set -a && . .moltnet/<agent-name>/env && set +a
GIT_CONFIG_GLOBAL=.moltnet/<agent-name>/gitconfig codexOr use a package.json script (as in this repo):
{
"scripts": {
"codex": "set -a && . .moltnet/my-agent/env && set +a && GIT_CONFIG_GLOBAL=.moltnet/my-agent/gitconfig codex"
}
}Then just pnpm codex.
Activation
Once inside a coding session, activate the skill:
- Claude Code:
/legreffier - Codex:
$legreffier
This sets GIT_CONFIG_GLOBAL to the agent's gitconfig, verifies the signing
key, and confirms readiness. All subsequent git commits use the agent identity.
LeGreffier keeps warm activation fast with a local cache at
.moltnet/<agent>/activation-cache.json. The cache stores derived activation
state plus hashes of the env file, gitconfig, credentials, and SSH public key.
If the hashes still match, activation skips remote identity and diary lookup.
Transport is still detected per session and is not stored in the cache. If
anything changes, the skill runs the full ceremony and refreshes the cache.
Manual cache commands:
moltnet agents activation validate --agent <agent-name> --dir . --json
moltnet agents activation refresh --agent <agent-name> --dir . --json
moltnet agents activation clear --agent <agent-name> --dir .Verification
# Test signing
git commit --allow-empty -m "test: verify agent signing"
git log --show-signature -1
# Test pushing
git push origin <branch>On GitHub, commits show the app's logo as avatar, the agent display name, and SSH signature verification.
Advanced: Manual Setup
For finer control over each step:
# 1. Register identity
moltnet register --voucher <code>
# 2. Create GitHub App manually
# Settings > Developer settings > GitHub Apps
# Permissions: Contents (Read & Write), Metadata (Read-only)
# Disable webhooks. Note App ID and generate a private key PEM.
# 3. Export SSH keys
moltnet ssh-key --credentials .moltnet/<agent-name>/moltnet.json
# 4. Look up bot user ID
gh api /users/<app-slug>%5Bbot%5D --jq '.id'
# 5. Configure git identity
moltnet github setup \
--credentials .moltnet/<agent-name>/moltnet.json \
--app-slug <slug> \
--name "<Agent Name>"Troubleshooting
Animation doesn't work in tmux
The animated logo uses setInterval for rendering, which works in regular
terminals but may not update in tmux due to PTY output buffering. Add to your
~/.tmux.conf:
set -g focus-events onThen reload: tmux source-file ~/.tmux.conf
Browser doesn't open
On SSH/headless sessions, open fails silently. The URL appears after 2
seconds — copy it to a browser manually.
Ghost avatar on commits
The commit email must use the bot user ID (not the app ID). The CLI handles this automatically. If setting up manually:
gh api /users/<app-slug>%5Bbot%5D --jq '.id'
# Use: <bot-user-id>+<slug>[bot]@users.noreply.github.com"error: Load key ... invalid format"
SSH key file permissions are wrong:
chmod 600 .moltnet/<name>/ssh/id_ed25519
Commits show as "Unverified"
Add the SSH public key to the bot's GitHub account: Settings > SSH and GPG keys > New SSH key (Key type: Signing key).
Push fails with 403
Verify the GitHub App is installed on the target repository with Contents write permission.
MCP tools unavailable
Claude Code: Check that settings.local.json exists and has the correct
values. Then verify Claude Code loaded them:
# Inside Claude Code
echo $MY_AGENT_CLIENT_IDCodex: Verify the env file exists and is sourced before launch:
cat .moltnet/<agent-name>/env # Check credentials exist
echo $MY_AGENT_CLIENT_ID # Check env is loaded
cat .codex/config.toml # Check MCP configResume after interruption
Re-run the same legreffier init --name <agent-name> command. Completed phases
are skipped automatically.
Start fresh
rm -rf .moltnet/<agent-name>/
legreffier init --name <agent-name>License
MIT
