Skip to content

feat(integrations): add Pi memory package - #1492

Open
phernandez wants to merge 2 commits into
mainfrom
feat/pi-memory
Open

feat(integrations): add Pi memory package#1492
phernandez wants to merge 2 commits into
mainfrom
feat/pi-memory

Conversation

@phernandez

@phernandez phernandez commented Sep 6, 2026

Copy link
Copy Markdown
Member

Why

Pi users should be able to carry Basic Memory continuity across sessions without starting over: capture the current working thread, open a fresh Pi session, and recover the decision, rationale, blocker, and next step from a real Basic Memory note.

This also proves the transport strategy from #1488: ship one Pi package with shared continuity semantics while supporting both direct Basic Memory CLI access and MCP access through the existing pi-mcp-adapter.

What Changed

  • Added a new Pi package under integrations/pi/ published as @basicmemory/pi-basic-memory.
  • Added a TypeScript Pi extension with:
    • /bm-status
    • /bm-recall
    • /bm-capture
    • bm_recall
    • bm_capture
  • Added project-local configuration via .pi/basic-memory.json, including CLI/MCP mode, explicit project/project-id routing, capture folder, recall timeframe, and opt-in automation settings.
  • Added a Pi-aware active skill, basic-memory-pi, that uses the package's bm_recall and bm_capture tools.
  • Bundled focused canonical Basic Memory skill text as non-active references:
    • memory-notes
    • memory-capture
    • memory-continue
    • memory-tasks
  • Added scripts/fetch-skills.ts and skill-references/manifest.json so the package refreshes bundled references from the monorepo source.
  • Added maintainer documentation and E2E evidence in docs/PI_MEMORY_*.md.
  • Added package/release wiring:
    • just package-check-pi
    • Pi included in just package-check and agent-harness-check
    • version bump support in scripts/update_versions.py
    • release recipes now include Pi package version files.

Implementation Details

The Pi integration is intentionally thin. Basic Memory owns storage, search, graph operations, routing, and authentication; the Pi package owns Pi lifecycle integration, explicit capture/recall commands, and packaging.

CLI mode is the default and shells out to bm tool ... with bounded subprocess timeouts. MCP mode does not implement a new MCP host; it registers Basic Memory with pi-mcp-adapter through the adapter's public runtime registration event. If the adapter is missing, the package reports a visible warning and leaves Pi usable.

Automatic recall and capture default off. Users can start with explicit /bm-recall and /bm-capture before opting into automation. Recalled notes are fenced as reference data, not instructions, and captures are synthesized checkpoints rather than raw transcript dumps.

Testing

Passed:

just package-check-pi

That runs:

npm ci --ignore-scripts
npm run fetch-skills
npm run check-types
npm test
npm pack --dry-run

Also passed:

uv run python scripts/update_versions.py v0.23.3 --scope packages --dry-run
uv run pytest tests/test_update_versions.py -q

Manual isolated E2E evidence is recorded in docs/PI_MEMORY_E2E_RESULTS.md:

  1. CLI capture → fresh CLI recall.
  2. CLI-written note → MCP adapter recall.
  3. MCP adapter write → CLI search/recall.

All E2E runs used temporary BASIC_MEMORY_HOME, BASIC_MEMORY_CONFIG_DIR, Pi session directories, and throwaway Basic Memory projects.

Risks / Follow-ups

  • Pi npm publishing is wired for package checks and version bumps, but the GitHub Actions npm publish step still needs to be added before release.
  • The extension commands are CLI-backed even when transport: "mcp"; MCP mode currently exposes Basic Memory to the model via pi-mcp-adapter.
  • docs.basicmemory.com needs a Pi integration page in a separate docs PR.
  • Broader lifecycle behavior — compaction-aware checkpoints, reload/resume/fork handling, and final automation defaults — remains planned follow-up work.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-06T15:11:56.259585Z 888a4b0 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c88864c242

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread integrations/pi/extensions/session.ts Outdated
const now = new Date();
const openedWith = userTurns[0]?.text ?? "Pi session";
const recent = params.turns.slice(-8);
const title = params.title?.trim() || `Pi session ${now.toISOString().slice(0, 19).replace("T", " ")} — ${clip(openedWith, 48)}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reuse a stable title for repeated session captures

When /bm-capture is invoked without a title, or whenever autoCapture runs, the title includes the current timestamp, so captures more than a second apart target different permalinks. Consequently, --overwrite never updates the previous checkpoint and every settled turn can create another permanent note for the same session, despite the available stable session ID and the bundled capture contract requiring same-thread recaptures to rewrite one note. Use the session ID to find/reuse the original title or otherwise persist a stable per-session title.

Useful? React with 👍 / 👎.

Comment thread integrations/pi/extensions/index.ts Outdated
Comment on lines +120 to +124
for (const row of rows.slice(0, 5)) {
lines.push(`- ${row.title ?? "(untitled)"} — ${row.permalink ?? row.file_path ?? ""}`.trim());
if (row.content) lines.push(` ${row.content.replace(/\s+/g, " ").slice(0, 500)}`);
}
lines.push("```", "", "Use these note references when continuing the task.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prevent recalled note data from closing its fence

A recalled note controls title, permalink, and content, but these values are inserted into a fixed triple-backtick fence without escaping or choosing a longer delimiter. For example, a synced note with a title containing a newline followed by ``` can close the fence and place attacker-controlled text outside the region labeled as untrusted reference data; this affects both explicit and automatic recall. Derive a fence longer than every backtick run in the rendered results, as the existing lifecycle recall path does.

Useful? React with 👍 / 👎.

Comment thread integrations/pi/extensions/config.ts Outdated
throw new Error(`basic-memory Pi config has unknown keys: ${unknown.join(", ")}`);
}

const transport = data.transport === "mcp" ? "mcp" : "cli";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject invalid transport values instead of selecting CLI

When a known transport key contains any value other than the exact string "mcp"—for example a typo such as "mpc"—configuration parsing silently selects CLI mode. That bypasses the visible configuration-error path and can execute local CLI operations when the user intended MCP; missing values may default, but present invalid enum values should fail validation. This also conflicts with the repository's fail-fast rule against silent fallback logic.

AGENTS.md reference: AGENTS.md:L132-L133

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b6ed753c9e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread integrations/pi/extensions/index.ts Outdated
name: cfg.mcpServerName,
definition: {
command: cfg.bmPath,
args: ["mcp", "--transport", "stdio"],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Constrain the registered MCP server to the configured project

When transport is "mcp" and project or projectId is configured, the registered process receives only bm mcp --transport stdio, so adapter calls that omit their own project argument fall through to the user's global default. I checked basic-memory mcp --help, which documents --project as “Restrict MCP server to single project,” and src/basic_memory/cli/commands/mcp.py:73-83 confirms that this establishes the server constraint. As written, /bm-status can report one project while MCP reads or writes another; pass the configured project constraint when launching the server and explicitly resolve or reject the unsupported projectId case.

AGENTS.md reference: AGENTS.md:L393-L395

Useful? React with 👍 / 👎.

Comment thread scripts/update_versions.py
Comment thread integrations/pi/extensions/index.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b80f2ec4ac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread integrations/pi/package.json Outdated
"version": "0.23.2",
"type": "module",
"description": "Basic Memory package for Pi — local-first continuity so you are never starting over",
"license": "MIT",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Align the published package license

When this package is published, its npm metadata advertises MIT while the bundled integrations/pi/LICENSE contains the GNU AGPL v3 text. Because LICENSE is included in the package tarball, consumers receive conflicting licensing terms and cannot safely rely on the advertised grant; either declare the package as AGPL-3.0-or-later or bundle the intended MIT license.

Useful? React with 👍 / 👎.

Comment thread integrations/pi/extensions/config.ts Outdated
Comment on lines +83 to +85
const data = raw && typeof raw === "object" && !Array.isArray(raw)
? raw as Record<string, unknown>
: {};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject wrong-typed configuration values

The new transport check is strict, but other present known keys still silently become defaults: for example, {"project": 123} produces project: undefined, and a non-object JSON root also becomes the complete default configuration. In those cases captures and recalls can run against the user's global default project rather than reporting the malformed project configuration, so distinguish missing values from invalid values and reject the latter.

AGENTS.md reference: AGENTS.md:L132-L133

Useful? React with 👍 / 👎.

Comment thread integrations/pi/extensions/session.ts Outdated
Comment on lines +89 to +91
const stableSessionTitle = params.sessionId
? `Pi session ${clip(params.sessionId, 24)} — ${clip(openedWith, 48)}`
: `Pi session ${now.toISOString().slice(0, 19).replace("T", " ")} — ${clip(openedWith, 48)}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep checkpoints distinct across session branches

The stable session-ID title added for repeated captures does not distinguish branches within that session. Two Pi branches share the session ID and opening user turn, so automatic captures derive the same title and captureSession writes with --overwrite; capturing branch B therefore replaces branch A's canonical checkpoint with contradictory branch state. Include a stable branch/leaf identity while continuing to reuse the title for recaptures of the same branch.

AGENTS.md reference: AGENTS.md:L156-L160

Useful? React with 👍 / 👎.

Comment thread integrations/pi/extensions/index.ts
Comment thread justfile Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ae517fb5d7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread integrations/pi/extensions/session.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f1427ceaf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread integrations/pi/extensions/index.ts Outdated
Comment thread integrations/pi/skill-references/memory-notes/REFERENCE.md
Comment thread integrations/pi/justfile Outdated
pack:
npm pack --dry-run

check: install fetch-skills check-types test pack

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Verify generated skill bundles are committed

This check refreshes the copied skills in-place and then tests and packs the modified working tree without checking for a diff. If a change updates a canonical top-level skill but omits the corresponding Pi copy, just package-check-pi and the new CI job still pass while the committed package remains stale for checkout-based installs; fail the check when fetch-skills leaves generated files dirty.

AGENTS.md reference: AGENTS.md:L72-L72

Useful? React with 👍 / 👎.

Comment thread docs/PI_MEMORY_SHIPPING.md Outdated
- Bundled Basic Memory skills in `skills/`.
- Skill integration docs in `SKILLS.md`.
- User README in `README.md`.
- MIT license.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Document the package's AGPL license

Fresh evidence after the package metadata was corrected is that this shipping checklist still identifies the bundled license as MIT, while both package.json and integrations/pi/LICENSE now declare AGPL-3.0-or-later. Maintainers or release reviewers following this checklist can therefore communicate the wrong licensing terms; update the checklist to match the shipped package.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 939a3602fa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread integrations/pi/extensions/index.ts Outdated
Comment thread integrations/pi/extensions/index.ts
Comment thread integrations/pi/extensions/index.ts Outdated
@phernandez
phernandez force-pushed the feat/pi-memory branch 3 times, most recently from 132fcb3 to 9e477d1 Compare September 6, 2026 08:00

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e477d104b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread integrations/pi/extensions/session.ts Outdated

const now = new Date();
const openedWith = userTurns[0]?.text ?? "Pi session";
const recent = params.turns.slice(-8);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve facts beyond the eight-turn capture window

When auto-capture is enabled—or /bm-capture is invoked repeatedly without a custom title—each capture overwrites the stable session note, but this slice retains only the last eight user/assistant messages. A decision or blocker included in an earlier checkpoint is therefore deleted from the canonical note as soon as enough later turns occur, and subsequent Basic Memory recall cannot recover it. Preserve accumulated durable facts or synthesize a continuing summary instead of replacing the checkpoint with a moving window.

AGENTS.md reference: AGENTS.md:L156-L160

Useful? React with 👍 / 👎.

Signed-off-by: phernandez <paul@basicmachines.co>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cba6660f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

});
});

child.stdin.end(options.stdin ?? "");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Handle child stdin errors without terminating Pi

When a large capture is still being written and bm exits or is aborted before consuming stdin—for example, a hung subprocess reaches the timeout—child.stdin emits EPIPE. Because only the child process has an error listener, Node treats the stream error as unhandled and terminates the entire Pi process instead of surfacing the promised capture failure; attach an error handler to stdin and settle the command exactly once.

AGENTS.md reference: AGENTS.md:L130-L133

Useful? React with 👍 / 👎.

`- Opening request: ${clip(openedWith, 300)}`,
"",
"## Thread to date",
...thread.map((turn) => `- **${turn.role}:** ${clip(turn.text, 220)}`),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the rest of each captured turn

Fresh evidence after the earlier eight-turn finding is that the full-thread change still applies clip(turn.text, 220) to every individual message. If a decision, blocker, command result, or next step occurs after character 220 of an ordinary assistant response, it is omitted from every checkpoint and the stable overwrite removes any opportunity to recover it through recall; synthesize the durable state or retain complete turn content rather than storing only each turn's prefix.

AGENTS.md reference: AGENTS.md:L156-L160

Useful? React with 👍 / 👎.

Comment on lines +319 to +320
handler: async (_args, ctx) => {
const lines = [

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Report invalid configuration from bm-status

After configuration parsing fails, session_start replaces cfg with defaults while retaining configError, but this status handler neither checks nor displays that error. A later /bm-status therefore reports CLI/default-project settings as effective even though capture and recall are disabled and reject every call, making the primary diagnostic command misleading; report the stored configuration error instead of the fallback settings.

AGENTS.md reference: AGENTS.md:L132-L133

Useful? React with 👍 / 👎.

Signed-off-by: phernandez <paul@basicmachines.co>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 888a4b0729

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

pi.on("session_start", async (_event, ctx) => {
await disposeCurrentMcp();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Continue session startup after MCP disposal errors

When the previous MCP registration's dispose() rejects—for example after an adapter or server shutdown failure—this await aborts session_start before recall state is reset or the new workspace configuration is loaded. The fresh evidence after the earlier cleanup change is that the disposal await remains outside the startup try; subsequent bm_capture or bm_recall calls can therefore use the preceding session's cfg and route canonical notes to its project. Surface the cleanup error but continue loading the new session configuration, such as via a guarded cleanup or finally.

AGENTS.md reference: AGENTS.md:L130-L131

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant