Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ The foundation is built on open standards, so your agent is never tied to one ap
| To | Run |
| --- | --- |
| Back up your agent onchain | `ethagent save` |
| See every identifier and what needs attention | `ethagent check` |
| See what changed since the last save | `ethagent status` |
| See what changed in memory since a date | `ethagent diff at:YYYY-MM-DD working --file MEMORY.md --sections` |
| Find when a rule first appeared | `ethagent history --file MEMORY.md --sections` |
Expand All @@ -158,6 +159,9 @@ The foundation is built on open standards, so your agent is never tied to one ap
| Remove leaked content | Edit it out, `ethagent save`, then `ethagent forget <ref> --file <path> --yes` for each version that held it |
| Connect another tool | `ethagent --add "<path to the instructions file it loads every session>"` |
| Find the vault | `ethagent --vault-dir` |
| List skills and what the Agent Card shows | `ethagent skills` |
| Make a skill public or private | `ethagent skills --public <name>` or `ethagent skills --private <name>` |
| Delete a skill | `ethagent skills --delete <name>`, then again with `--yes` |
| See the Vault, its build, and who may do what | `ethagent custody`, or `ethagent custody --verify` to simulate each permission |
| Check the agent's ENS name | `ethagent ens` |
| Point the agent at another ENS name | `ethagent ens <name>`, then again with `--yes` |
Expand Down Expand Up @@ -188,6 +192,10 @@ Run any of these with `npx ethagent`. Commands marked interactive need a termina
| `pause` / `resume` | Stop or restart background sync. | Local |
| `--status` | One-line summary: agent, network, local changes, connected tools. | Read-only |
| `--vault-dir` | Print the vault path. | Read-only |
| `check [--json]` | Every value that identifies the agent: token ID, network, registry, owner, agent URI, snapshot, metadata and agent card CIDs, ENS name, custody, Vault, operator, last saved, pending publish, transfer state, and any unconfirmed transaction. Then anything that needs attention, each with the command that fixes it. Exits 4 when something does. | Goes online |
| `skills [--json]` | Every skill in the vault, its visibility, and whether the Agent Card publishes it. | Read-only |
| `skills --public <name> \| --private <name> [--json]` | Change a skill's visibility and update the Agent Card. `ethagent save` publishes it. | Writes the vault |
| `skills --delete <name> [--yes] [--json]` | Remove a skill's folder. Previews until `--yes`, checkpoints first, and names the rollback that brings it back. | Writes the vault |
| `reset [--yes]` | Delete the local identity, vault, history, and saved secrets (the IPFS storage credential is kept), and disconnect your tools. Asks first unless `--yes`. | Deletes local data |
| `status [--verify] [--json]` | What changed since the latest snapshot, per file and per skill. | Read-only; `--verify` goes online |
| `history [--json]` | Snapshots and checkpoints, newest first. | Read-only |
Expand Down Expand Up @@ -235,7 +243,7 @@ Run any of these with `npx ethagent`. Commands marked interactive need a termina
| `1` | Failed. |
| `2` | Usage error. |
| `3` | No working storage credential, no operator key, or the wallet was cancelled or timed out. |
| `4` | Pinned, but the owner still needs to publish it. |
| `4` | Pinned, but the owner still needs to publish it: run `ethagent save` again and approve with the owner wallet. |

### Onchain identity

Expand All @@ -249,7 +257,7 @@ Run any of these with `npx ethagent`. Commands marked interactive need a termina

### Setting up and moving an agent

`create`, `restore`, `profile`, `transfer`, `storage`, and the custody changes run without the manager too. Everything the manager can do now has a command.
`create`, `restore`, `profile`, `transfer`, `storage`, and the custody changes run without the manager too. Everything the manager can do has a command, except deleting an ENS subname, which stays in the manager on purpose; `ens --unlink` clears the agent's records instead.

- **Previews.** Anything that signs or sends previews first: every signature and transaction, who signs it, and what can be simulated now. Nothing happens without `--yes`.
- **One tab.** Each command runs all its wallet prompts in one browser tab. `--no-open` prints the link instead of opening it.
Expand Down Expand Up @@ -380,6 +388,8 @@ Instructions for the agent.

What a save packs: folder and file names of letters, digits, `.`, `_`, and `-`; files with an extension; up to 4 folders deep; up to 2 MiB per file and 500 files in total. Build caches (`__pycache__`, `.pyc`, `node_modules`) and dotfiles are left out. Files are stored as text, so `ethagent status` lists anything a save would skip or couldn't store exactly.

`ethagent skills` lists the skills and which ones the Agent Card publishes; `--public <name>` and `--private <name>` set `visibility` for you. A public skill without a real description is treated as a draft and left off the card.

### Files and locations

| What | Where | Notes |
Expand Down Expand Up @@ -435,7 +445,7 @@ With `--json`, every history and onchain command prints one line of ASCII-only J
| `1` | Failed: unknown ref, missing path, or a store error. |
| `2` | Usage error, or a ref that matches more than one thing. |
| `3` | The snapshot isn't cached here or there's no key to open it, `--operator` ran without an injected operator key, or the wallet approval was cancelled. |
| `4` | Partly done (a custody change or `create --advanced` that stopped after something landed; run it again to finish), or `status --verify` or `custody --verify` found a mismatch. |
| `4` | Partly done (a custody change or `create --advanced` that stopped after something landed; run it again to finish), `status --verify` or `custody --verify` found a mismatch, or `check` found something that needs attention. |

### Environment variables

Expand Down
6 changes: 4 additions & 2 deletions commands/ethagent.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@ Most of these run in a separate terminal because they need a wallet or a TTY, bu
- `npx ethagent` opens the interactive identity manager. Every action in it also has a headless command (`create`, `restore`, `profile`, `custody`, `ens`, `transfer`, `storage`); see "Onchain identity" below.
- `ethagent save` runs Save Snapshot (encrypt, pin to IPFS, rotate the onchain pointer). **You can run this yourself** as a normal tool call (e.g. `npx ethagent save`): no separate terminal and no TTY, and it will not hang. It prints a localhost wallet URL and opens the browser tab so the user approves the signature and transaction there. You trigger and run it; the user only approves in the wallet. Pass `--no-open` to just print the URL. Only run it when the user specifically asks to save or back up the agent; never run it on your own initiative or as a side effect of other work. It is a no-op (no wallet, no gas) when there are no local changes since the last snapshot.
- Syncing is automatic: ethagent keeps the agent's soul, memory, and skills in step across every detected tool in the background, both ways, newest edit wins. There is no sync command to run. Pause it with `npx ethagent pause` and resume with `npx ethagent resume`.
- `npx ethagent check` lists every value that identifies the agent (token ID, owner, agent URI, snapshot, metadata and agent card CIDs, registry, Vault, last saved, pending publish, transfer state) and anything that needs attention, each with the command that fixes it. Read-only and safe to run yourself; it exits 4 when something needs attention.
- `npx ethagent --status` prints a short summary: agent id, chain, address, any local changes, the vault path, and the connected tools.
- `npx ethagent --vault-dir` prints this agent's vault directory (where soul, memory, and the `skills/` folder live). Read-only and safe to run yourself.
- `npx ethagent reset` deletes the local identity, vault, history, and saved secrets (the IPFS storage credential is kept), and disconnects every tool. It asks to confirm in a terminal, so it hangs inside a session unless you pass `--yes`. Run it only when the user explicitly asks.
- `npx ethagent status`, `history`, `show`, `diff`, `fetch`, `checkpoint`, `rollback`, and `forget` manage continuity history headlessly. See "Continuity history" below.
- `npx ethagent skills` lists the vault's skills, their visibility, and which ones the Agent Card publishes. Read-only and safe to run yourself. `skills --public <name>` and `skills --private <name>` change a skill's visibility, and `skills --delete <name>` removes one (preview, then `--yes`; it checkpoints first and names the rollback that undoes it). Run those only when the user asks; `ethagent save` publishes the change.
- `npx ethagent custody` and `npx ethagent ens` inspect and manage the onchain identity headlessly. See "Onchain identity" below.

To rebuild the agent on a new machine, the user runs `npx ethagent`; it restores the identity from an ENS name or ERC-8004 token id, then asks the wallet to sign.

You may run the read-only non-interactive commands yourself whenever they help (`--status`, `--vault-dir`, and the read-only history commands below). `ethagent save` is different: run it only when the user specifically asks you to save or back up the agent, never on your own initiative or as a side effect of other work. When they do ask, you can run it directly: there is no CLI step for the user and no separate terminal needed. It is headless, will not hang, prints a wallet URL, and opens the browser tab where the user approves the signature. You trigger and run the command; you never sign. (It is also a no-op when there are no local changes since the last snapshot.) Never launch the bare interactive `npx ethagent` from inside a session: it opens a full-screen terminal app that needs a TTY and will hang the tool call. For anything else that signs or sends (`create`, `restore`, `profile`, `custody`, `ens`, `transfer`), run the preview yourself and leave the `--yes` run to the user.
You may run the read-only non-interactive commands yourself whenever they help (`check`, `--status`, `--vault-dir`, `skills`, and the read-only history commands below). `ethagent save` is different: run it only when the user specifically asks you to save or back up the agent, never on your own initiative or as a side effect of other work. When they do ask, you can run it directly: there is no CLI step for the user and no separate terminal needed. It is headless, will not hang, prints a wallet URL, and opens the browser tab where the user approves the signature. You trigger and run the command; you never sign. (It is also a no-op when there are no local changes since the last snapshot.) Never launch the bare interactive `npx ethagent` from inside a session: it opens a full-screen terminal app that needs a TTY and will hang the tool call. For anything else that signs or sends (`create`, `restore`, `profile`, `custody`, `ens`, `transfer`), run the preview yourself and leave the `--yes` run to the user.

Where the synced files land:

- Every skill, public and private, is mirrored into `~/.claude/skills/` (per-skill folders) for Claude Code and into the managed block in `~/.codex/AGENTS.md` for Codex.
- The vault at `~/.ethagent/continuity/` is the source of truth and holds everything as plain files on this machine. Nothing leaves it unencrypted: a save encrypts soul, memory, and every skill before it pins them.
- `~/.claude/skills/` is a read-only generated mirror; never create or edit files there (the sync overwrites it from the vault). To add or change a skill, put its folder directly in the vault skills dir: run `npx ethagent --vault-dir` (non-interactive, safe to run yourself) to print the vault path, then create or edit the `<name>/SKILL.md` folder inside its `skills/` subdir. Skills are private by default; set one to public only when it should be listed on the Agent Card.
- `~/.claude/skills/` is a read-only generated mirror; never create or edit files there (the sync overwrites it from the vault). To add or change a skill, put its folder directly in the vault skills dir: run `npx ethagent --vault-dir` (non-interactive, safe to run yourself) to print the vault path, then create or edit the `<name>/SKILL.md` folder inside its `skills/` subdir. Skills are private by default; set one to public (`ethagent skills --public <name>`) only when the user wants it listed on the Agent Card.

Privacy and secrets:

Expand Down
2 changes: 1 addition & 1 deletion src/cli/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function stampState(): void {
export async function runBootstrap(opts: { quiet?: boolean } = {}): Promise<number> {
const config = await loadConfig()
if (!config?.identity) {
if (!opts.quiet) process.stdout.write('ethagent: no identity yet; run `npx ethagent` to create or link one first\n')
if (!opts.quiet) process.stdout.write('ethagent: no identity yet; run `npx ethagent create` or `npx ethagent restore <token-id>` first\n')
return 0
}

Expand Down
4 changes: 3 additions & 1 deletion src/cli/harnessGuidance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ export function buildPortableInstruction(opts: PortableInstructionOptions): stri
'put its folder in the vault skills dir (NOT this read-only mirror): run `npx ethagent --vault-dir` to print the vault ' +
"path, then create or edit the `<name>/SKILL.md` folder inside its `skills/` subdir. Past snapshots are kept locally " +
'byte for byte; `npx ethagent status --json` and `npx ethagent diff --json` show what changed. ' +
'`npx ethagent custody --json`, `ens --json`, and `profile --json` show the onchain identity; `create`, `restore`, ' +
'`npx ethagent check --json` lists the agent\'s identifiers and what needs attention; `custody --json`, `ens --json`, ' +
'`profile --json`, and `skills --json` show the rest and are read-only. Change skill visibility or delete a skill with ' +
'`skills --public`, `--private`, or `--delete` only when the user asks. `create`, `restore`, ' +
"`profile`, `custody`, `ens`, and `transfer` preview without `--yes`, and anything with `--yes` is the user's to run."
)
}
2 changes: 1 addition & 1 deletion src/cli/history/commands.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const HISTORY_COMMANDS = new Set(['status', 'history', 'show', 'diff', 'fetch', 'checkpoint', 'rollback', 'forget'])
export const HISTORY_COMMANDS = new Set(['status', 'history', 'show', 'diff', 'fetch', 'checkpoint', 'rollback', 'forget', 'skills'])
1 change: 1 addition & 0 deletions src/cli/history/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export async function runHistoryCommand(verb: string, args: string[], baseDeps:
case 'checkpoint': return (await import('./checkpoint.js')).runCheckpointCommand(args, deps)
case 'rollback': return (await import('./rollback.js')).runRollbackCommand(args, deps)
case 'forget': return (await import('./forget.js')).runForgetCommand(args, deps)
case 'skills': return (await import('./skills.js')).runSkillsCommand(args, deps)
default: return 2
}
}
2 changes: 1 addition & 1 deletion src/cli/history/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export function parseHistoryArgs(args: string[], options: ParseArgsConfig['optio
export async function requireIdentity(deps: HistoryDeps): Promise<{ config: EthagentConfig; identity: EthagentIdentity }> {
const config = await deps.loadConfig().catch(() => null)
if (!config?.identity) {
throw new HistoryError(1, 'No agent identity yet.', 'Create or link one by running `npx ethagent` in a terminal.')
throw new HistoryError(1, 'No agent identity yet.', 'Mint one with `ethagent create`, or bring one back with `ethagent restore <token-id>`.')
}
return { config, identity: config.identity }
}
Expand Down
Loading
Loading