An open API service indexing awesome lists of open source software.

https://github.com/filopedraz/pocket

Bring your own memory. Switch CLI agents without losing context.
https://github.com/filopedraz/pocket

agents byom claude-code cli codex memory opencode terminal

Last synced: 17 days ago
JSON representation

Bring your own memory. Switch CLI agents without losing context.

Awesome Lists containing this project

README

          

# pocket

> A self-extending CLI agent.
> It grows its own tools.
> It remembers you across vendors.

A folder. Some hooks. A tiny TypeScript CLI. When the agent needs a
capability it doesn't have, it writes the command into
`cli/src/commands/` and uses it on the next run. When the session ends,
a subagent updates `memory/general.md` with what was durable. Switch
from Claude to Codex to OpenCode tomorrow — the folder doesn't move.

## Why

Most "AI memory" tools are read-only state you pour into a vendor's
context window. They don't change what the agent can do; they just give
it more to read. And when that vendor rate-limits you or your credits
run out, the memory is stuck inside their walls.

`pocket` is the other shape. Two things live in this repo:

1. **What the agent knows about you** — `memory/general.md`. Small,
durable, refreshed at the end of each session by a subagent that
reads the transcript and proposes a diff.
2. **What the agent can do** — `cli/src/commands/`. Every time the agent
hits a task it can't do directly, the rule in `AGENTS.md` tells it
to spawn a subagent, implement a new `bin/pocket `, and add
it to the toolset. Next session it just calls the command.

Both are plain files in a git repo. Every supported CLI agent
(`claude`, `codex`, `opencode`) reads them at session start and writes
back to them on the way out, via pre-wired hooks. Switching providers is
changing which binary you type.

The pieces:

- **`memory/general.md`** — what an agent should know about you.
Durable, small. Created from a template by `bin/pocket init`; refreshed
by a subagent at the end of each substantive session.
- **`cli/src/commands/`** — the agent's growing toolset. One TypeScript
file per subcommand; the agent appends here through subagents.
- **`chats/`** — every session, every agent, one JSONL file each. Local
by default. Populated automatically by hooks; queryable via
`bin/pocket recent / find / show / tail`.

## Quickstart

```bash
git clone https://github.com/filopedraz/pocket.git
cd pocket
bin/pocket init # scaffold memory/general.md
$EDITOR memory/general.md # tell agents who you are
cp .env.example .env # if you have keys to store
git config core.hooksPath .githooks # enable AGENTS.md → CLAUDE.md sync hook
bin/pocket doctor # check deps (needs bun)
```

From here, run whichever CLI agent you like inside this directory — its
hooks are pre-wired.

```bash
claude # Claude Code session — auto-logs to chats/
codex # Codex session — auto-logs to chats/
opencode # OpenCode session — plugin auto-logs to chats/
```

To find what you talked about yesterday:

```bash
bin/pocket recent # last 10 sessions, any agent
bin/pocket find "kafka" # grep across all chats
bin/pocket show # pretty-print one session
```

## CLI commands

| Command | What it does |
|---|---|
| `bin/pocket init` | Scaffold `memory/general.md` from the embedded template and ensure `.gitkeep` markers exist. Re-run with `--force` to overwrite. |
| `bin/pocket recent [N]` | Last N sessions across all agents (default 10), sorted by mtime. |
| `bin/pocket find ` | Literal-string grep across every `chats/*.jsonl`. |
| `bin/pocket show ` | Pretty-print every JSONL line of the matching session. |
| `bin/pocket tail` | Follow the most recently modified session file. |
| `bin/pocket doctor` | Verify bun is installed and every agent's hook plumbing is in place. |
| `bin/pocket help` | Print the live command list. |

This table is the source of truth. New commands land here in the same PR
that adds them — see [Adding a pocket CLI command](AGENTS.md#adding-a-pocket-cli-command).

## How it works

Three thin layers — no service, no background daemon.

**1. Hooks.** Each agent's hook config (`.claude/settings.json`,
`.codex/hooks.json`, `.opencode/plugins/pocket-log.js`) fires on every user
prompt, tool use, and session end. The hook serialises the event and pipes
it into `hooks/log.sh`.

**2. Logger.** `hooks/log.sh` is the shared scrub-and-append script. It
strips auth headers, embedded URL credentials, JWTs, and obvious secrets,
then writes one JSONL line to `chats/__.jsonl`.
Claude Code and Codex both call it directly. OpenCode runs the same logic
inside its JS plugin (their plugin API doesn't shell out).

**3. Toolset.** `bin/pocket` is a Bun-runtime TypeScript CLI in `cli/`.
Each subcommand lives at `cli/src/commands/.ts` — adding one means
dropping a file and a single dispatcher case. This is both how *you*
query the chat history (`recent`, `find`, `show`, `tail`) and how the
*agent* grows its own capabilities over time. See AGENTS.md for the
full contract.

## How the agent extends itself

The self-extension loop lives in `AGENTS.md` (mirrored to `CLAUDE.md`),
which every supported agent reads at session start. The rules, in
order:

1. **Read `memory/general.md`** to know who you are.
2. **Hit a task you can't do directly?** Spawn a subagent to either
research a library that already does it, or implement a new
`cli/src/commands/.ts` end-to-end. The new command shows up
in `bin/pocket ` on the very next run.
3. **Need an API key?** Tell the human which one, link the page, ask
them to paste it, and append `KEY=value` to `.env` — `.env.example`
gets the mirrored variable name.
4. **End of session?** Spawn a subagent that reads the transcript and
proposes a minimal diff to `memory/general.md`. Apply, end the turn.

You don't opt in — any agent that reads `AGENTS.md` picks up the rules.
The point is that the toolset and the memory both grow on their own
without the main chat carrying the weight of research, refactoring, or
re-reading transcripts.

## Supported agents

| Agent | Hook surface | Captured events |
|-------------|-----------------------------------|----------------------------------------------------------|
| Claude Code | `.claude/settings.json` | `UserPromptSubmit`, `PostToolUse`, `Stop` |
| Codex | `.codex/hooks.json` | `PreToolUse`, `PermissionRequest`, `PostToolUse` |
| OpenCode | `.opencode/plugins/pocket-log.js` | `session.created`, `session.idle`, `message.updated`, `tool.execute.before`, `tool.execute.after` |

Want another agent? See [Adding a new agent](AGENTS.md#adding-a-new-agent-cursor-aider-gemini-cli-) in AGENTS.md. PRs welcome for Cursor, Aider, Gemini CLI, anything with a hook or plugin surface.

## Repo layout

```
pocket/
├── memory/
│ ├── .gitkeep # folder marker; contents gitignored
│ └── general.md # durable notes about you (local-only)
├── chats/
│ ├── .gitkeep # folder marker; contents gitignored
│ └── *.jsonl # one per session (local-only)
├── hooks/
│ └── log.sh # shared scrub-and-append (Claude + Codex)
├── cli/
│ ├── package.json # bun + biome
│ ├── tsconfig.json
│ ├── biome.json
│ ├── build.ts # `bun run build` → cli/dist/pocket
│ └── src/
│ ├── index.ts # dispatcher (one switch case per command)
│ ├── commands/ # one file per subcommand
│ └── lib/ # args, output, env, paths helpers
├── bin/
│ └── pocket # bash shim: prefers compiled binary, falls back to `bun run`
├── .claude/settings.json # Claude Code hooks
├── .codex/hooks.json # Codex hooks
├── .opencode/plugins/ # OpenCode plugin
├── .env.example # secrets template; copy to .env (gitignored)
├── .githooks/ # tracked git hooks (enable: git config core.hooksPath .githooks)
├── AGENTS.md # instructions for any agent in this repo
└── CLAUDE.md # mirror of AGENTS.md (pre-commit hook keeps it in sync)
```

## Privacy

`chats/` and `memory/` are **gitignored by default**. Both folders ship
with a `.gitkeep` so a fresh clone has somewhere to write, but the
contents stay on your machine. If you want them committed (e.g. so a
`git pull` on another machine brings your memory with you), make the
repo private and remove the carve-outs from `.gitignore`.

`hooks/log.sh` scrubs the obvious things (auth headers, URL creds, JWTs,
anything keyed `password` / `token` / `api_key` / `secret`). It is **not**
a full PII redactor. Skim a session before you commit it if you typed
something you don't want on GitHub.

## Dependencies

- `bun` ≥ 1.0 — `curl -fsSL https://bun.sh/install | bash`
- `bash` (POSIX-ish, tested on macOS + Linux)
- `git` — for repo-root resolution

## Status

Early. The shape is right. Expect rough edges on cross-platform paths and
on agents that change their hook payloads between releases. Open an issue
if something breaks.

## License

MIT. See [LICENSE](LICENSE).