iroha for Notion
by iroha924
README.md
# iroha
> **Sessions scatter. iroha remembers.**
**English** | [日本語](README.ja.md)
> Persist Claude Code sessions to Notion as a living, queryable **team memory** —
> the background each session started from, decisions (with rationale and rejected
> alternatives), work-state, and per-project architecture profiles. So humans *and* future
> Claude sessions can recall what was decided, why, what's unfinished, and how things are built.
[](LICENSE)
[](https://github.com/iroh4-labs/iroha-for-memory/actions/workflows/ci.yml)
## Why
Claude Code now ships its own memory — but it lives on **one developer's disk** and is
written for the agent to read back, not for a team to browse. iroha is the layer **on top**:
it turns each session into a **team-shared, human-browsable** record in Notion — a decision
ledger with the *rationale and the rejected alternatives*, a supersede history (a change of
mind is itself memory), work-state, and per-project architecture. So the next session — yours
or a teammate's — and any human opening Notion can see what was decided, *why*, what was ruled
out, what's unfinished, and how things are built. The more the team uses it, the more it grows:
ask *"have we built something like this before?"* and iroha points at the prior session, the
files it changed, and why.
## How it works
- The **runtime is Bun + TypeScript** (`scripts/**/*.ts`, run directly with no build step):
it does the deterministic extraction (your real messages, changed files, metadata) from the
session transcript. The **intelligence** (summary, context, decisions, classification)
is produced by Claude inside the skills.
- All Notion reads/writes go through the **Notion MCP** — there is **no API token**.
Auth is the MCP's OAuth, so setup is a single connection. Works on the **free** Notion plan.
- **Recall is two-stage.** On every prompt, a `UserPromptSubmit` hook runs a *cheap, local*
BM25 search (`search.ts`, CJK-aware, **no LLM and no network**) over a tiny on-disk index and
proactively surfaces the most relevant past decisions — so Claude consults them *before*
rebuilding, at zero per-prompt latency or token cost. When that pointer isn't enough,
`/iroha:recall` escalates to Notion's own **semantic** search (`notion-search`; on a free
workspace it is scoped to your own pages — all iroha needs — full ranking may want Notion AI) for the
full rationale and rejected alternatives. The local BM25 is the always-on proactive net at zero
cost; the semantic stage is Notion's own search (no local models) — so recall stays dependency-free
with nothing to install, and the deep `/iroha:recall` runs as a forked subagent to keep its bulky
lookups out of the main context. On a brand-new project the proactive net stays **quiet** until
the memory has grown enough for the ranking to be trustworthy (a cold-start gate) — better silence
than a confident-but-coincidental match.
- A SessionStart hook injects the project's **State** (from a small repo mirror) so
Claude proactively tells you where you left off and what's unfinished. After `/compact`
or auto-compact it also **re-injects the current session's own thread** (your prompts +
a capped recent tail), so the conversation survives compaction.
- A **write-time** check (a `PreToolUse` hook on `git commit`) runs the same cheap local
recall over the commit subject + staged paths and, if **Active decisions** govern that
area, adds an advisory to verify you are not silently reversing one (and to run
`/iroha:check`). It is purely advisory — it **never blocks or auto-approves** the commit —
and catches a course-reversal at the last moment before code lands.
- A saved session carries the **background it started from** (the issue you pasted, the meeting
transcript — quoted verbatim from your real messages), the decisions, what moved, what broke,
and — when the branch has one — a **link to its GitHub PR** (found via a bounded, fail-soft
`gh` lookup, so a missing PR or no `gh` never blocks the save). No metrics, no transcript
dump: only what explains the work. `/iroha:digest` rolls a week or month into one page;
`/iroha:audit` keeps the growing memory clean (duplicate decisions, State drift, stale items).
## Memory model — three layers + State
```mermaid
graph TD
CC["Claude Code session"] -->|/iroha:save-session| SK["save-session skill"]
SK -->|deterministic| EX["extract.ts (Bun)"]
SK -->|intelligence| CL["Claude"]
SK -->|Notion MCP / OAuth| N[("Notion")]
N --> SES["Sessions — what happened"]
N --> DEC["Decisions — why"]
N --> PRJ["Projects — current stack"]
N --> ST["State — where we are"]
ST -->|repo .iroha/state.md| HK["SessionStart hook"]
DEC -->|notion-search| RC["/iroha:recall"]
```
- **Sessions** — why each session happened: the background it started from (quoted verbatim from your real messages), decisions made, what moved, what broke.
- **Decisions** — *why* the project is the way it is: rationale + rejected alternatives, with supersession history (a change of mind is itself memory).
- **Projects** — *what the project is now*: languages, key libraries, dev tooling, CI, an architecture diagram — for onboarding and cross-project search.
- **State page** — the always-current "where are we / what's unfinished", injected at session start.
## Requirements
- [Claude Code](https://code.claude.com/docs)
- **[Bun](https://bun.sh) ≥ 1.1** — the runtime for iroha's hooks and skills. Claude Code does
**not** bundle it, so install it first (`curl -fsSL https://bun.sh/install | bash`) and check
`bun --version`. Without Bun every hook and skill fails with `bun: command not found`.
- A Notion account with the **hosted Notion MCP** connected (OAuth) — see *Getting started*.
iroha deliberately does **not** bundle the server, so you configure it once yourself and every
project on the machine shares it. Works on the **free** plan:
the always-on proactive recall and your project State are fully **local** (no Notion, no Notion
AI). The deep `/iroha:recall` uses Notion's own search — on a free workspace it is scoped to your
own pages (which is all iroha needs); full semantic ranking may require Notion AI.
## Install
In Claude Code:
```
/plugin marketplace add iroh4-labs/iroha-for-memory
/plugin install iroha@iroha-for-memory
```
## Getting started
1. **Connect Notion MCP** — once per machine:
```
claude mcp add --transport http notion --scope user https://mcp.notion.com/mcp
```
Then run `/mcp`, pick `notion`, and complete the OAuth in your browser. If you already use the
Notion MCP, skip this — iroha reuses the server you have. (It is not bundled with the plugin on
purpose: a bundled server is registered under a plugin-prefixed tool name, which would clash
with the one you already configured.)
2. **`/iroha:init`** — creates the `Sessions` / `Decisions` / `Projects` databases (plus
Recent / Active / By-Language views) under a Notion page you choose. Re-running it on a
shared page lets a teammate **join** the same workspace.
3. **`/iroha:save-session`** — save the current session.
4. **`/iroha:recall <query>`** — *"did we decide against X? why?"* / *"have we built this before?"*.
5. **`/iroha:project`** — record (or refresh) the project's tech stack. Manual, engineer-reviewed.
## Commands
| Command | What it does |
| --- | --- |
| `/iroha:init` | One-time setup (idempotent): create or join the Notion databases + views. |
| `/iroha:save-session` | Save this session: the background it started from, decisions, work-state, failures, changed files. |
| `/iroha:decide "<topic>: <choice>"` | Record one decision (rationale + rejected alternatives) the moment you make it — the lightweight capture that grows the ledger between full saves. |
| `/iroha:recall <query>` | Semantic search over Sessions + Decisions for past decisions and similar prior work. |
| `/iroha:history <topic>` | Walk a decision's supersede lineage — how and why the choice evolved (`v3 ← v2 ← v1`), with the reason at each step. Read-only. |
| `/iroha:project` | Capture/update this project's architecture profile (manual). |
| `/iroha:digest [week\|month\|range]` | Roll a period up into one digest: decisions, sessions, what's still open, and a timeline. |
| `/iroha:audit [--fix]` | Health-check the memory (duplicate decisions, State drift, stale items); optionally apply safe, reversible fixes. |
| `/iroha:check` | Check the current working changes (git diff + new files) against the project's Active decisions and flag conflicts before you commit. Read-only. |
## What iroha is **not**
- **No secrets.** No API token to manage — Notion auth is MCP OAuth only; only non-secret
ids are cached locally.
- **No relation properties.** Session↔Decision links use a URL property (a known
relation-write bug in the Notion MCP); promotable to native relations once stable.
- **Only what explains the work.** A session page answers one question — *why was this done,
and what did it decide?* No transcript dump, no metrics dashboard, no tool tallies, no copy
of your rules. Those are either vanity or a second truth that drifts from `CLAUDE.md`.
- **The "why" lives in your words, not Claude's.** `## Context` is the background a session
started from — the issue you pasted, the meeting transcript, the problem statement. Claude
*selects* which of your real messages carry it; the renderer *quotes* them verbatim into a
collapsed `Context prompts (K of N)` toggle. Claude passes an index, never the text — so its
prose always sits beside receipts it could not have altered.
- **No save coercion.** Hooks remind, they don't block.
## Design
- Architecture invariants: [`.claude/rules/architecture.md`](.claude/rules/architecture.md)
- Project notes & scope: [`CLAUDE.md`](CLAUDE.md)
- Contributing: [`CONTRIBUTING.md`](CONTRIBUTING.md) · Security: [`SECURITY.md`](SECURITY.md)
## License
[MIT](LICENSE) © Shunichi Hirata
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing