Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,4 @@ packages/plugin/scripts/experiments/issue-195-repro.mjs
packages/plugin/scripts/experiments/visual-memory/render-trimmed-memories.ts
packages/plugin/scripts/experiments/visual-memory/trials/REPORT.md
packages/plugin/scripts/mural-test-output/
AgentLogs/
17 changes: 10 additions & 7 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Configuration Reference

All settings are flat top-level keys in `magic-context.jsonc`. The schema is **shared between the OpenCode plugin and the Pi extension** — every setting documented here applies to both unless explicitly marked **Pi only** or **OpenCode only**.
All settings are flat top-level keys in `magic-context.jsonc`. The schema is shared by the OpenCode plugin and the Pi-compatible extension used on both Pi and OMP.

### Configuration locations

Magic Context reads config from **one shared CortexKit location**, the same for both harnesses (project overrides user):
Magic Context reads config from one shared CortexKit location across OpenCode, Pi, and OMP (project overrides user):

| Path | Scope |
|---|---|
Expand All @@ -19,12 +19,12 @@ Project config always merges on top of user config. The unified setup wizard (`n

Both plugins write to the same SQLite database at `~/.local/share/cortexkit/magic-context/context.db`. Tables are scoped by:

- `harness` column (`'opencode'` or `'pi'`) for **session-scoped** data — tags, compartments, session facts, notes
- `harness` column (`'opencode'` or `'pi'`) for **session-scoped** data — OMP intentionally uses the Pi-compatible `'pi'` discriminator
- `project_path` (resolved git root) for **project-scoped** data — memories, embeddings, dreamer runs, key-file pins, smart notes

So memories you write in OpenCode appear in Pi sessions for the same project (and vice versa), while per-session compartments and tags stay correctly attributed to their originating harness.
Project memories therefore flow across OpenCode, Pi, and OMP, while per-session state remains scoped to the OpenCode or Pi-compatible runtime.

For semantic search to work cross-harness, both plugins resolve embedding config per project identity on every retrieval path. OpenCode and Pi can run in the same process against different projects without sharing one process-global embedding provider. For one project, keep the effective `embedding` block consistent across the OpenCode and Pi config stack; Magic Context tags stored vectors with the resolved model identity and clears stale vectors for that project when the provider/model changes.
For semantic search to work cross-harness, every host resolves embedding config per project identity on each retrieval path. Keep the effective `embedding` block consistent across OpenCode, Pi, and OMP for the same project.

### JSON Schema

Expand All @@ -43,19 +43,22 @@ Both setup wizards add this automatically.
If something isn't working, run the unified doctor to auto-detect installed harnesses and fix common issues:

```bash
# Auto-detect installed harnesses; if both, picks the first or asks
# Auto-detect installed harnesses; if multiple are present, pick or prompt
npx @cortexkit/magic-context@latest doctor

# Target a specific harness explicitly
npx @cortexkit/magic-context@latest doctor --harness opencode
npx @cortexkit/magic-context@latest doctor --harness pi
npx @cortexkit/magic-context@latest doctor --harness omp
```

The OpenCode doctor checks: installation, CLI version vs npm latest, plugin registration (preserves local dev paths), `magic-context.jsonc` parses + loads through the schema, conflicts (compaction, DCP, OMO hooks), TUI sidebar configuration, embedding endpoint, shared-DB existence + `PRAGMA integrity_check` + row counts, plugin npm cache, and historian debug dumps.

The Pi doctor checks: Pi binary + version (requires `>= 0.71.0`), CLI version vs npm latest, settings registration, config validity, embedding endpoint reachability, shared-DB integrity, stale Pi extension caches, and historian debug dumps.

Both report `PASS X / WARN Y / FAIL Z` summary counts. Use `--force` to auto-fix what doctor can (clears stale plugin cache, repairs config) and `--issue` to produce a sanitized issue report.
The OMP doctor checks the OMP version, effective plugin enable state, `PI_CODING_AGENT_DIR`/profile/XDG path agreement, native compaction and automatic-memory conflicts, config validity, and shared DB integrity. `--force` installs/enables the plugin and repairs conflicting OMP settings.

All doctors report `PASS X / WARN Y / FAIL Z` summary counts. Use `--force` for safe repairs and `--issue` to produce a sanitized issue report.

### SQLite backend

Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Magic Context gives them one. It is the **hippocampus** for coding agents, the p

- **Capture.** As the historian compresses your history, it lifts the durable knowledge (decisions, constraints, conventions) into project memory. You get a memory system for free, from work you are already doing.
- **Consolidate.** Overnight, dreamer agents do what sleep does for you: verify memories against the codebase, curate duplicates and stale entries, and promote what recurs.
- **Recall.** The right memories surface automatically every turn, and the agent can search across memories, past conversations, and git history on demand. Across sessions, and across OpenCode and Pi.
- **Recall.** The right memories surface automatically every turn, and the agent can search across memories, past conversations, and git history on demand. Across sessions, and across OpenCode, Pi, and OMP.

Two promises: your agent **never stops to manage its context** (no compaction pauses, no broken flow) and it **never forgets**.

Expand All @@ -96,7 +96,7 @@ irm https://raw.githubusercontent.com/cortexkit/magic-context/master/scripts/ins
npx @cortexkit/magic-context@latest setup
```

The wizard auto-detects which harnesses you have (OpenCode, Pi, or both), adds the plugin, disables built-in compaction, helps you pick models for the historian, dreamer, and sidekick, and resolves conflicts with other context-management plugins. Target a specific harness with `--harness opencode` or `--harness pi`.
The wizard auto-detects which harnesses you have (OpenCode, Pi, OMP, or any combination), adds the plugin, disables built-in compaction, helps you pick models for the historian, dreamer, and sidekick, and resolves conflicts with other context-management plugins. Target one with `--harness opencode`, `--harness pi`, or `--harness omp`.

> **Why disable built-in compaction?** Magic Context manages context itself. The host's compaction would interfere with its cache-aware deferred operations and double-compress.

Expand All @@ -111,9 +111,11 @@ The wizard auto-detects which harnesses you have (OpenCode, Pi, or both), adds t

**Pi:** `npx @cortexkit/magic-context@latest setup --harness pi` (requires Pi `>= 0.74.0`). The Pi extension shares the same database as OpenCode; project memories and embeddings pool across both.

**Troubleshooting:** `npx @cortexkit/magic-context@latest doctor` auto-detects your harnesses, checks for conflicts (compaction, OMO hooks, DCP), verifies the plugin and TUI sidebar, runs an integrity check on the database, and fixes what it can. Add `--issue` to file a ready-to-submit bug report.
**Oh My Pi (OMP):** `npx @cortexkit/magic-context@latest setup --harness omp` (requires OMP `>= 17.1.7`). Setup installs the Pi-compatible extension through `omp plugin`, disables OMP native compaction and automatic memory, and honors OMP profiles, `PI_CODING_AGENT_DIR`, and initialized XDG layouts.

Works the same on a brand-new or a long-running project: install, restart the harness, and Magic Context captures context from that point forward. It does not backfill OpenCode or Pi sessions from before it was installed.
**Troubleshooting:** `npx @cortexkit/magic-context@latest doctor` auto-detects your harnesses, checks host-specific conflicts, verifies plugin registration and database integrity, and fixes what it can. Add `--issue` to file a ready-to-submit bug report.

Works the same on a brand-new or a long-running project: install, restart the harness, and Magic Context captures context from that point forward. It does not backfill OpenCode, Pi, or OMP sessions from before it was installed.

<details>
<summary><strong>Compatibility with other context-management plugins</strong></summary>
Expand All @@ -123,6 +125,8 @@ Works the same on a brand-new or a long-running project: install, restart the ha
Magic Context owns context management end to end, so it **disables itself** if another plugin is already doing that job. Running two context managers at once would double-compress your history and thrash the prompt cache. On startup it checks for the following; setup and `doctor` help you resolve each, and until they're resolved Magic Context stays off (fail-safe) and tells you why:

- **OpenCode built-in compaction** (`compaction.auto` / `compaction.prune`) — Magic Context replaces it. Setup turns it off.
- **OMP native compaction** (`compaction.enabled`) — Magic Context replaces it. OMP setup turns it off transactionally.
- **OMP automatic memory** (`memory.backend`) — a second memory injector duplicates recall and retention. OMP setup sets it to `off`; existing data is not deleted.
- **DCP** (`opencode-dcp`) — a separate context-pruning plugin. The two cannot run together; remove it from your `plugin` list.
- **oh-my-opencode (OMO)** — setup offers to disable the three hooks that overlap:
- `preemptive-compaction` — triggers compaction that conflicts with the historian.
Expand Down Expand Up @@ -215,7 +219,7 @@ Because it runs during idle time, the dreamer pairs well with local models, even
- **`ctx_expand`**: pull a compressed history range back to the original `U:`/`A:` transcript when the agent needs the exact details.
- **`ctx_note`**: a scratchpad for deferred intentions. Notes resurface at natural boundaries (after commits, after historian runs, when todos finish). **Smart notes** carry an open-ended condition the dreamer watches for.

Recall works **across sessions** (a new session inherits everything) and **across harnesses** (write a memory in OpenCode, retrieve it in Pi).
Recall works **across sessions** (a new session inherits everything) and **across harnesses** (write a memory in OpenCode, retrieve it in Pi or OMP).

> **Auto search hints** *(on by default)* run a background `ctx_search` each turn and whisper a "vague recall" when something relevant exists — like almost remembering a note you took. It appends only compact fragments, never full content; set `memory.auto_search.enabled: false` to turn it off. **Git commit indexing** *(opt-in)* makes your project history semantically searchable as an additional `ctx_search` source — enable with `memory.git_commit_indexing.enabled: true`.

Expand Down
4 changes: 3 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
{
"name": "@cortexkit/magic-context",
"version": "0.33.0",
"description": "Unified CLI for Magic Context — setup, doctor, and migration across OpenCode and Pi",
"description": "Unified CLI for Magic Context — setup, doctor, and migration across OpenCode, Pi, and OMP",
"keywords": [
"opencode",
"opencode-plugin",
"pi",
"pi-extension",
"omp",
"oh-my-pi",
"magic-context",
"cli",
"setup",
Expand Down
5 changes: 3 additions & 2 deletions packages/cli/src/adapters/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { OmpAdapter } from "./omp";
import { OpenCodeAdapter } from "./opencode";
import { PiAdapter } from "./pi";
import type { HarnessAdapter, HarnessKind } from "./types";

export type { HarnessAdapter, HarnessKind } from "./types";
export { OpenCodeAdapter, PiAdapter };
export { OmpAdapter, OpenCodeAdapter, PiAdapter };

const ALL: HarnessAdapter[] = [new OpenCodeAdapter(), new PiAdapter()];
const ALL: HarnessAdapter[] = [new OpenCodeAdapter(), new PiAdapter(), new OmpAdapter()];

/** Look up an adapter by kind. Throws on unknown kind. */
export function getAdapter(kind: HarnessKind): HarnessAdapter {
Expand Down
48 changes: 48 additions & 0 deletions packages/cli/src/adapters/omp.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { afterEach, describe, expect, it } from "bun:test";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { OmpAdapter } from "./omp";

const original = {
HOME: process.env.HOME,
PATH: process.env.PATH,
PI_CODING_AGENT_DIR: process.env.PI_CODING_AGENT_DIR,
XDG_DATA_HOME: process.env.XDG_DATA_HOME,
};
const roots: string[] = [];

afterEach(() => {
for (const [key, value] of Object.entries(original)) {
if (value === undefined) delete process.env[key];
else process.env[key] = value;
}
for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true });
});

describe("OmpAdapter", () => {
it("detects an enabled Magic Context plugin from omp plugin list", () => {
const root = mkdtempSync(join(tmpdir(), "mc-omp-adapter-"));
roots.push(root);
const bin = join(root, "bin");
mkdirSync(bin, { recursive: true });
const omp = join(bin, "omp");
writeFileSync(
omp,
`#!/bin/sh
if [ "$1 $2 $3" = "plugin list --json" ]; then
printf '%s' '{"npm":[{"name":"@cortexkit/pi-magic-context","version":"0.33.0","enabled":true}],"marketplace":[]}'
fi
`,
{ mode: 0o755 },
);
process.env.PATH = bin;
process.env.HOME = root;
delete process.env.XDG_DATA_HOME;

const adapter = new OmpAdapter();
expect(adapter.isInstalled()).toBe(true);
expect(adapter.hasPluginEntry()).toBe(true);
expect(adapter.getInstalledPluginVersion()).toBe("0.33.0");
});
});
Loading