Skip to main content
Glama
README.md
# Agent Notebook

A **local-first notebook shared by you and all your AI agents**.

- **Notion-like UI** — pages with properties, kanban boards with drag-and-drop, side-peek editing, search, dark mode.
- **Obsidian-compatible storage** — everything is plain Markdown + YAML frontmatter in one folder. Open the vault in Obsidian any time. No database, no lock-in.
- **Built for agents** — an MCP server (stdio for local agents, Streamable HTTP for remote ones) with per-agent **tokens**, **read / write / admin scopes**, optional **folder restrictions**, and an **audit log** of everything each agent did.
- **GitHub backup** — optional scheduled `git commit` + `push` to any remote. Off by default: then your notes stay on your disk only.
- **Skill included** — `skills/agent-notebook/SKILL.md` teaches agents the conventions (which board for what, always tag `source`, dedupe before writing).

## How it is organised (v0.2)

- **Notebooks** (领域) are top-level folders with a `_notebook.md`: 收件箱, 健康, 阅读, 思维, 财务, Alpha看板, 选题会 … each with an icon, a description, **routing keywords** and a *kind*:
  - `journal` — one page per day, entries appended with a timestamp (健康, 财务)
  - `board` — kanban cards with columns (Alpha看板, 选题会)
  - `pages` — one page per note (阅读, 思维)
- **Agents call one tool**: `notebook_capture { text }`. The router scores every notebook by keywords and by rules learned from your corrections, files the text in the notebook's own shape, or drops it in **收件箱** with suggestions. Assign an inbox item once and the router remembers (`.notebook/rules.json`); **设置 → 归类规则** lists every learned keyword / tag / source rule and lets you forget one (or all). The capture result's `related` ranks existing notes by shared title words, shared tags, titles mentioned in the new text and recency in the same notebook, each with the reasons.
- **Links**: write `[[Page title]]` anywhere; it resolves by title across notebooks, renders as a link, and the target shows **backlinks**.
- **Reading**: the home page is a quick-capture box, the inbox, and *today's feed* grouped by notebook; each notebook has kanban / timeline / table views.
- **Graph**: **关系图** draws every note as a node and every `[[link]]` as an edge — coloured by notebook (legend doubles as a filter), sized by link count, hover to see neighbours, click to open, drag / zoom / pan, optional orphan notes; a note's page links to the graph centred on it. `GET /api/graph` returns nodes, edges and unresolved link names.
- **Charts**: numbers an agent passes in `properties` (`{ amount: 35 }`, `{ weight: 71.5 }`) — or that you type as `[amount:: 35]` / `weight:: 71.5` — are kept per entry as Obsidian/Dataview inline fields and plotted per day in the notebook's **图表** view (sum / average / latest, 7 / 30 / 90 days / all, hover for the entries, click to open the day). `notebook_metrics` gives agents the same series.

## Quick start

```bash
npm install
node src/cli.js init            # creates ./vault with example boards (Alpha看板, 选题会, 灵感)
node src/cli.js serve           # http://127.0.0.1:3777
```

Open the web UI. The home page tells you which local agents it detected; **接入 Agent** lets you connect each one with one click.

## Connect your agents

```bash
node src/cli.js agents              # detect local agents and show their status
node src/cli.js connect claude-code # create a token, write the MCP entry, install the skill
node src/cli.js connect codex --scopes read --folders "Alpha看板"
```

| Agent | How it is connected |
|---|---|
| Claude Code, Claude Desktop, Cursor, Windsurf, Gemini CLI, Antigravity, Kiro, Devin, VS Code | writes `mcpServers.agent-notebook` into its JSON config |
| Codex CLI, Grok CLI | writes a `[mcp_servers.agent-notebook]` block into its `config.toml` |
| OpenCode | writes `mcp.agent-notebook` (`type: local`) into `opencode.json` |
| Grok Bot, Cue, Hermes, Muse, anything else that speaks MCP | **其他 agent**: name it, get a token plus HTTP / stdio JSON / TOML snippets to paste into that app |

Every write backs up the original file as `<file>.agent-notebook.bak` and only touches the `agent-notebook` entry. Each agent gets its own token, so you can revoke one without affecting the others, and the activity log shows which agent did what.

The old manual path still works: **设置 → Agent 访问令牌 → 创建令牌** prints ready-to-paste config.

Or from the CLI:

```bash
node src/cli.js token create claude-code --scopes read,write
node src/cli.js token create alpha-bot --scopes read,write --folders "Alpha看板"
node src/cli.js token create reader --scopes read
```

### Connect Claude Code

```bash
claude mcp add agent-notebook \
  -e AGENT_NOTEBOOK_TOKEN=nb_xxx \
  -e AGENT_NOTEBOOK_VAULT="/path/to/agent-notebook/vault" \
  -- node /path/to/agent-notebook/src/cli.js mcp
```

Copy `skills/agent-notebook/` into `~/.claude/skills/` so Claude Code knows the house rules.

### Connect any MCP client (Codex, Cursor, Claude Desktop, …)

```json
{
  "mcpServers": {
    "agent-notebook": {
      "command": "node",
      "args": ["/path/to/agent-notebook/src/cli.js", "mcp"],
      "env": { "AGENT_NOTEBOOK_TOKEN": "nb_xxx", "AGENT_NOTEBOOK_VAULT": "/path/to/agent-notebook/vault" }
    }
  }
}
```

### Remote agents (HTTP)

While `serve` runs, `POST http://127.0.0.1:3777/mcp` with `Authorization: Bearer nb_xxx` is a Streamable HTTP MCP endpoint. Bind to another host with `--host 0.0.0.0` (put it behind a tunnel or reverse proxy with TLS; the web UI is owner-only from loopback, everything else needs a token).

## MCP tools

| Tool | Scope | What it does |
|---|---|---|
| `notebook_capture` | write | **the one call**: route text to the right notebook (journal entry / card / page), returns related notes |
| `notebook_list_notebooks` / `notebook_create_notebook` | read / write | areas with kind, keywords, columns |
| `notebook_today` | read | everything recorded on a day, grouped by notebook |
| `notebook_metrics` | read | numeric series of a notebook (`amount`, `weight` …): count / sum / avg / min / max / latest + points, optional `key`, `from`, `to` |
| `notebook_move_note` | write | move a note (e.g. out of the inbox); the router learns |
| `notebook_whoami` | — | token name, scopes, folder limits |
| `notebook_list_boards` / `notebook_get_board` | read | boards, columns, cards (optionally one `date`) |
| `notebook_list_notes` / `notebook_read_note` / `notebook_search` | read | browse and read |
| `notebook_create_note` | write | new page or card (`source` = agent) |
| `notebook_update_note` | write | replace / append body, rename, change properties |
| `notebook_move_card` | write | change a card's column |
| `notebook_create_board` | write | new kanban board |
| `notebook_delete_note` | write | move to `.trash/` |

## Vault layout

```
vault/
  欢迎.md                      # a page: Markdown + frontmatter
  收件箱/_notebook.md          # inbox: true
  健康/
    _notebook.md               # kind: journal, keywords: [睡眠, 运动, …]
    2026-10-31.md              # one page per day, "## 09:12 · title" entries, numbers as "[weight:: 71.5]" fields
  阅读/_notebook.md            # kind: pages
  Alpha看板/
    _notebook.md               # kind: board, columns: [新发现, 关注中, 已验证, 归档]
    Hyperliquid ….md           # a card: status / tags / source / date / url …
  .notebook/
    config.json                # port, token hashes (sha256), backup settings  (git-ignored)
    rules.json                 # learned routing rules (keyword / tag / source → notebook)
    audit.jsonl                # who did what, when
  .trash/                      # deleted notes
```

A card:

```markdown
---
title: Hyperliquid 新上线永续合约交易量激增
status: 新发现
tags: [DeFi, 永续]
source: alpha-bot
date: '2026-10-31'
created: '2026-10-31T09:12:00.000Z'
updated: '2026-10-31T09:12:00.000Z'
url: https://…
---
## 线索
- …
```

## Backup

```bash
node src/cli.js backup init https://github.com/you/my-notes.git   # git init + remote, enables scheduled backup
node src/cli.js backup now
node src/cli.js backup status
```

Or in the UI under **设置 → 备份**. Interval defaults to 30 minutes. Pushing uses your normal git credentials (`gh auth login` or SSH keys). `.notebook/config.json` is git-ignored so token hashes never leave the machine.

## Security model (MVP)

- Requests from loopback **without** a bearer token are treated as the owner (full access). Requests with a token get that token's scopes/folders. Non-loopback requests without a token are rejected.
- Tokens are stored as SHA-256 hashes; the plaintext is shown once.
- Every write and every denied call is appended to `.notebook/audit.jsonl`, visible under **活动日志**.

## Roadmap ideas

Block-level editor, per-column WIP limits, webhooks (notify Slack when an agent adds a card), MCP resources for `notebook://` URIs, OAuth for remote agents, Tauri/Electron shell.

MIT.

Maintenance

ActivityMaintained
ResponsivenessNo issues