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
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"plugins": [
{
"name": "brains",
"description": "Your memory layer: Gmail/Calendar/Drive and prior Claude conversations as queryable pages — reflexive recall, turn-by-turn capture, a server-driven inbox, and boards/automations/workflows on top.",
"description": "Your memory layer: Gmail/Calendar/Drive and prior Claude conversations as queryable pages — reflexive recall, hook-driven turn-by-turn capture and inbox delivery, and boards/automations/workflows on top.",
"source": "./plugins/brains",
"category": "productivity"
}
Expand Down
63 changes: 47 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# brains — Codex and Claude Code plugin

Your memory layer for Codex and Claude Code: Gmail, Calendar, Drive, and prior
AI conversations as queryable pages — with reflexive recall, turn-by-turn
capture, a server-driven inbox, boards, automations, and workflows on top.
AI conversations as queryable pages — with reflexive recall, hook-driven
turn-by-turn capture and inbox delivery, boards, automations, and workflows
on top. The same server also backs claude.ai, where no hooks run — see
[Install for claude.ai web](#install-for-claudeai-web).

The Codex and Claude packages share the same seven skills, core prompt, hook
scripts, and inbox engine. Only their manifests, hook event maps, and MCP
Expand Down Expand Up @@ -33,8 +35,9 @@ expected. Codex stores the credential itself, so there is nothing to copy or
keep. Confirm with `codex mcp list`: brains should read **OAuth**.

Restart the ChatGPT desktop app or start a new Codex thread. The first time the
plugin loads, open `/hooks` and trust the bundled brains hooks so automatic
recall, capture, inbox delivery, and error feedback can run.
plugin loads, open `/hooks` and trust the bundled brains hooks — that is what
runs automatic recall and error feedback. Capture and inbox delivery also need a
capture credential — normally the token below.

Everyday reading and writing is covered by default. For admin-gated tools or
performance insights, sign in asking for them explicitly (both also need the
Expand Down Expand Up @@ -75,6 +78,9 @@ launchctl setenv BRAINS_API_TOKEN "<your token>"
This token is only for capture and the inbox. It is **not** how Codex
authenticates the brains tools — that is `codex mcp login brains` above.

Running your own brains server? Set `BRAINS_ENDPOINT` alongside it — see
[Self-hosting](#self-hosting).

## Install for Claude Code

No token needed — Claude Code signs itself in.
Expand All @@ -98,7 +104,8 @@ This flow was verified on Claude Code 2.1.220. If `claude mcp login` is not a re
command, update Claude Code.

Restart Claude Code or start a new session. The first time the plugin loads, trust the bundled
brains hooks so automatic recall, capture, inbox delivery, and error feedback can run.
brains hooks — that is what runs automatic recall and error feedback. Capture and inbox delivery
also need the token below.

For a local checkout under development:

Expand Down Expand Up @@ -139,7 +146,41 @@ claude mcp login plugin:brains:brains

Then run `/reload-plugins`.

### Self-hosting
## Install for claude.ai web

claude.ai does not run this repo's hooks, so the capture that Codex and Claude
Code get from `hooks/` does not happen there. Two ways in, both covered step by
step at <https://app.mybrains.ai/install/claude-web>:

- **Custom connector** — add `https://mcp.mybrains.ai/mcp` and approve the OAuth
screen. This is the path we verified end to end.
- **Full plugin** — add this repository as a marketplace and install from it.
Paid plans only; it also brings the skills. The hooks it lists stay inert.

Recall works: ask about a person, project or past conversation and Claude
reaches for brains on its own.

**Capture is different — ask for it.** On claude.ai a conversation is saved only
when Claude calls `save_chat_session`. Say "save this chat to brains" and it
does; that is the dependable way, and the way to treat anything you want kept.

With the install guide's instruction block in place Claude also saves on its own
sometimes — but only sometimes, and in testing it once said it was saving
without actually doing so. Don't rely on it, and don't take the sentence in the
chat as proof: `list_pages type=chat_session`, or just ask brains which chats it
has, is the only real confirmation.

## Shared layout

- `.agents/plugins/marketplace.json` — Codex marketplace
- `.claude-plugin/marketplace.json` — Claude Code marketplace
- `plugins/brains/.codex-plugin/plugin.json` — Codex manifest
- `plugins/brains/.claude-plugin/plugin.json` — Claude Code manifest
- `plugins/brains/.mcp.json` — Codex MCP declaration
- `plugins/brains/skills/` — shared skills
- `plugins/brains/hooks/` — shared scripts plus client-specific event maps

## Self-hosting

The brains tools connect to `https://mcp.mybrains.ai/mcp`; to point them at your own
server, fork this repo, set the URL in `plugins/brains/.claude-plugin/plugin.json` and
Expand All @@ -161,16 +202,6 @@ Codex has no such option and runs the same hook scripts, so set `BRAINS_ENDPOINT
you set `BRAINS_API_TOKEN` above — the shell Codex starts from, or the app's launch
environment. Without it Codex capture keeps sending to `https://mcp.mybrains.ai` too.

## Shared layout

- `.agents/plugins/marketplace.json` — Codex marketplace
- `.claude-plugin/marketplace.json` — Claude Code marketplace
- `plugins/brains/.codex-plugin/plugin.json` — Codex manifest
- `plugins/brains/.claude-plugin/plugin.json` — Claude Code manifest
- `plugins/brains/.mcp.json` — Codex MCP declaration
- `plugins/brains/skills/` — shared skills
- `plugins/brains/hooks/` — shared scripts plus client-specific event maps

## License

[GPL-3.0](./LICENSE)
4 changes: 2 additions & 2 deletions plugins/brains/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "brains",
"description": "Your memory layer: Gmail, Calendar, Drive, and prior Claude conversations as queryable pages, with reflexive recall, turn-by-turn capture, a server-driven inbox, and boards/automations/workflows on top.",
"version": "2.7.0",
"description": "Your memory layer: Gmail, Calendar, Drive, and prior Claude conversations as queryable pages, with reflexive recall, hook-driven turn-by-turn capture and inbox delivery, and boards/automations/workflows on top.",
"version": "2.7.1",
"author": {
"name": "brains (ssvlabs)"
},
Expand Down
4 changes: 2 additions & 2 deletions plugins/brains/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "brains",
"version": "2.7.0",
"version": "2.7.1",
"description": "Your personal memory layer for Codex: query Gmail, Calendar, Drive, and prior conversations, then build boards, automations, and workflows.",
"author": {
"name": "brains (ssvlabs)",
Expand All @@ -15,7 +15,7 @@
"interface": {
"displayName": "Brains",
"shortDescription": "Your personal memory layer",
"longDescription": "Query your Gmail, Calendar, Drive, and prior AI conversations from Codex, with automatic context and capture plus boards, automations, workflows, and feedback flows.",
"longDescription": "Query your Gmail, Calendar, Drive, and prior AI conversations from Codex, with automatic context and hook-driven capture plus boards, automations, workflows, and feedback flows.",
"developerName": "ssvlabs",
"category": "Productivity",
"capabilities": ["Read", "Write", "Automate"],
Expand Down
10 changes: 6 additions & 4 deletions plugins/brains/core.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- brains:core:start v=5 -->
<!-- brains:core:start v=6 -->
# brains — your memory layer

You have a memory layer called **brains** (the `brains` MCP server). It holds the
Expand All @@ -22,9 +22,11 @@ For schedules and agendas, use `list_calendar_events start=… end=…`; calenda
page update time is not event time. Name the source page's `title` and `type`,
and never invent slugs or IDs.

**Capture is automatic.** The ingest hook saves every turn to the server, which
builds the conversation page (title/summary) for you. You do **not** need to call
`save_chat_session`.
**Capture.** In Codex and Claude Code the ingest hook saves each turn, but only
where a capture credential resolves — so never promise capture and never deny
it; `list_pages type=chat_session` is the only way to know. Don't call
`save_chat_session` routinely there; do call it when asked, and where the hooks
don't run (claude.ai web) it is the only path.

**The skills carry the detail** — load the one that fits the moment:
`brains-read` (querying memory), `brains-write` (sending/creating via
Expand Down
6 changes: 4 additions & 2 deletions plugins/brains/hooks/brains-turn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
# mode (notifications only, no
# stdout). Fires AFTER the turn.
#
# Ingest is the capture path: every turn POSTs to /ingest/claude, and the server
# builds the chat_session page. No save_chat_session call needed.
# Ingest is the capture path WHERE IT RUNS, and it is credential-gated: with a
# TOKEN (see the gate below) every turn POSTs to /ingest/claude and the server
# builds the chat_session page. Without one this hook exits silently, and where
# the hooks do not run at all (claude.ai web) save_chat_session is the only path.
# Claude keeps the existing fire-and-forget delivery. Codex waits for its
# assistant POST during Stop so the hook process cannot finish before the
# response has been handed to the ingest endpoint.
Expand Down
7 changes: 7 additions & 0 deletions scripts/generated-artifact-guard.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@
#
# Usage: scripts/generated-artifact-guard.sh [base-ref] (default origin/main)
#
# Which digit to bump (convention, not enforced here — semver_gt below accepts
# any forward move, on any digit): match this repo's own commit-type prefixes.
# `fix(...)`: patch. `feat(...)`: minor. A declared breaking change to the
# plugin's contract (MCP server URL, tool/skill names, config schema): major.
# Past bumps in this repo are inconsistent with this rule — treat it as the
# convention going forward, not a description of history.
#
# A guard that cannot fail loudly is not a guard. Three rules keep this one
# honest, each earned from an observed false pass during review:
#
Expand Down
4 changes: 2 additions & 2 deletions tests/inbox-v2/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -808,10 +808,10 @@ const SCENARIOS: Scenario[] = [
const manifest = JSON.parse(readFileSync(PLUGIN_JSON_PATH, "utf8")) as { version: string };
assertEqual(report.plugin_version, manifest.version, "25 plugin_version matches manifest");

// Sections come from the shipped core.md; this release bumps it to v5.
// Sections come from the shipped core.md; this release bumps it to v6.
const sections = (report.sections ?? []) as Array<{ name: string; version: number }>;
const core = sections.find((s) => s.name === "core");
assertEqual(core?.version, 5, "25 core marker reported at v5");
assertEqual(core?.version, 6, "25 core marker reported at v6");

// No drift → no update nudge in stdout.
assertNotContains(r.stdout, "brains:update", "25 no update nudge when device is current");
Expand Down
Loading
Loading