You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: DOCS.md
+23-7Lines changed: 23 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -583,13 +583,13 @@ This envelope is used consistently by `/sync/push` validation/control failures a
583
583
584
584
## MCP Project Resolution
585
585
586
-
Engram resolves the project at MCP tool call time from the **server process working directory** (cwd), not at MCP startup and not from arbitrary LLM arguments. This eliminates project drift caused by agents supplying different names for the same repo.
586
+
Engram resolves the project at MCP tool call time. The default source is the **server process working directory** (cwd), not MCP startup state, but some write tools have stronger context: `mem_session_start(directory=...)` resolves from the provided directory, and `mem_save` may use a validated explicit `project` or an existing `session_id` project before falling back to cwd detection. The explicit field is treated as a **validated selection**, not a free-form creation hint. This eliminates project drift caused by agents supplying different names for the same repo.
587
587
588
588
### Detection algorithm
589
589
590
590
| Case | Condition | Source | Project |
591
591
|------|-----------|--------|---------|
592
-
| 1 |`.engram/config.json` exists at the repo root, or at cwd outside git |`config`|`project_name` from config |
592
+
| 1 |nearest `.engram/config.json` exists within the enclosing git root, or at cwd outside git |`config`|`project_name` from config |
593
593
| 2 | cwd is a git root with `origin` remote |`git_remote`| repo name from remote URL |
594
594
| 3 | cwd is inside a git repo (subdirectory) |`git_root`| git root's directory basename |
595
595
| 4 | cwd has exactly one git-repo child |`git_child`| child repo name (warning included) |
@@ -617,13 +617,28 @@ Exceptions:
617
617
-`mem_current_project` returns detection fields directly (`project`, `project_source`, `project_path`, `cwd`, `available_projects`, optional `warning` / `error_hint`) and does not wrap them in `result`.
618
618
-`mem_doctor` returns the same JSON report shape as `engram doctor --json`; it uses read-project resolution before running diagnostics but does not wrap the report in the common MCP envelope.
`mem_session_start`, `mem_session_end`, `mem_session_summary`, and `mem_capture_passive` auto-detect project from cwd. Any `project` argument the LLM sends is ignored.
622
+
`mem_session_start` resolves from its explicit `directory` argument when supplied; otherwise it auto-detects from cwd. `mem_session_end`, `mem_session_summary`, and `mem_capture_passive` auto-detect project from cwd. Any `project` argument the LLM sends to these tools is ignored.
623
623
624
624
`mem_update` uses ID-based updates and auto-detects project only for response envelope metadata. Its public schema does not expose `project`; raw legacy clients may still send a non-empty `project` argument, and the handler tolerates it as an observation project update for compatibility.
625
625
626
-
`mem_save` and `mem_save_prompt` also auto-detect project from cwd by default, but they accept one narrow recovery override: after a previous `ambiguous_project` error, the agent may retry with `project=<one of available_projects>` and `project_choice_reason=user_selected_after_ambiguous_project`. Without that exact reason, LLM-supplied `project` is ignored so routine writes cannot drift across project names.
626
+
`mem_save` resolves writes by precedence: validated explicit `project`, project already associated with `session_id`, repo/cwd detection (nearest `.engram/config.json` within the enclosing git root, git remote/root/child), then directory-basename fallback.
- Valid-looking explicit `project` names are accepted only when backed by known context: an existing local project in the store, a matching existing session project, the nearest resolvable `.engram/config.json`, or exact ambiguous-project recovery after the user selected one available project.
631
+
- An unbacked explicit `project` fails loudly and does not create a new bucket.
632
+
- If a non-empty `session_id` is supplied and no session exists, `mem_save` fails with a structured error and does not write.
633
+
- If both explicit `project` and `session_id` are supplied, they must resolve to the same normalized project or `mem_save` fails with a structured error and does not write.
634
+
-`project_choice_reason=user_selected_after_ambiguous_project` is only honored when cwd resolution is actually ambiguous. On a non-ambiguous cwd, stale recovery flags do not override explicit-project precedence or session mismatch validation.
635
+
- If ambiguous-project recovery is active, `project` must exactly match one of the previously returned `available_projects`; invented or normalized guesses are rejected.
636
+
- Exact ambiguous-project choices can still fail with `project_name_collision` when multiple available names collapse to the same stored project bucket after normalization. Rename or disambiguate the colliding projects before retrying.
637
+
- Ordinary explicit `mem_save(project=...)` calls can also fail with `project_name_collision` when the raw explicit name collapses into an existing config-backed, session-backed, or store-backed project bucket, such as `foo--bar` colliding with `foo-bar`.
638
+
639
+
For monorepos, detection now honors the **nearest**`.engram/config.json` at or below the enclosing git root. That lets `repo/backend/.engram/config.json` and `repo/frontend/.engram/config.json` behave as independent projects without letting `~/.engram/config.json` leak into nested workspaces.
640
+
641
+
`mem_save_prompt` keeps the older cwd/default behavior by default and only uses `project` for the narrow ambiguous-project recovery override: after a previous `ambiguous_project` error, the agent may retry with `project=<one of available_projects>` and `project_choice_reason=user_selected_after_ambiguous_project`.
627
642
628
643
### Read tools (optional project override)
629
644
@@ -729,6 +744,7 @@ Save comprehensive end-of-session summary:
729
744
## Instructions
730
745
## Discoveries
731
746
## Accomplished
747
+
## Next Steps
732
748
## Relevant Files
733
749
```
734
750
@@ -900,7 +916,7 @@ All project names are normalized on write and read: **lowercase**, **trimmed**,
900
916
### Auto-detection
901
917
902
918
MCP tools resolve project names at call time using the shared detection chain:
903
-
1.`.engram/config.json``project_name`at the repo root, or at cwd outside git
919
+
1.Nearest `.engram/config.json``project_name`within the enclosing git root, or at cwd outside git
904
920
2. Git remote origin URL (extracts repo name)
905
921
3. Git repository root directory name
906
922
4. Single git-repo child of cwd
@@ -990,7 +1006,7 @@ Instead of a separate LLM service, the agent itself compresses observations. The
Copy file name to clipboardExpand all lines: docs/AGENT-SETUP.md
+52-21Lines changed: 52 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -27,7 +27,9 @@ Engram works with **any MCP-compatible agent**. Pick your agent below.
27
27
28
28
### Project auto-detection (important)
29
29
30
-
**Do not pass `project` to write tools during normal operation.** Engram auto-detects the project from the server's working directory (cwd) using `.engram/config.json`, git remote URL, repo root name, or directory basename. Agents that include `project` in `mem_save` or similar calls will have that argument ignored unless they are using the explicit ambiguous-project recovery flow below.
30
+
`mem_save` resolves its write project in this order: validated explicit `project`, existing `session_id` association, repo `.engram/config.json`/cwd detection, then directory-basename fallback. Use an explicit `project` when you intentionally want to target a known project; invalid or unbacked names fail loudly instead of silently falling back.
31
+
32
+
Other write tools still primarily use cwd/repo detection unless their schema says otherwise. Start the MCP server from the repo or add `.engram/config.json` when you want deterministic default writes.
31
33
32
34
To lock write tools to the canonical project for a repo, add `.engram/config.json` at the repo root:
33
35
@@ -37,7 +39,9 @@ To lock write tools to the canonical project for a repo, add `.engram/config.jso
37
39
}
38
40
```
39
41
40
-
When present, `project_name` is used for writes from the repo and its subdirectories and overrides lower-confidence cwd/git detection. This is a write lock only: read tools can still use an explicit `project` filter when you need to query another existing project. Empty or invalid `project_name` values fail writes loudly instead of falling back silently.
42
+
When present, `project_name` is the default auto-detected target for writes from the repo and its subdirectories and overrides lower-confidence cwd/git detection. It is NOT an unbreakable lock against an explicit `mem_save(project=...)`, but explicit project writes are still validated against known context before they are accepted. Read tools can still use an explicit `project` filter when you need to query another existing project. Empty or invalid `project_name` values fail writes loudly instead of falling back silently.
43
+
44
+
For monorepos, prefer subproject configs such as `backend/.engram/config.json` and `frontend/.engram/config.json`. Engram uses the **nearest** config under the enclosing git root, so backend/frontend can resolve as separate projects while still blocking `$HOME/.engram/config.json` ancestor leakage.
41
45
42
46
**Recommended first call:**`mem_current_project` — confirms which project Engram detected before you start writing. Returns `project_source` (how it was detected) and `available_projects` (if cwd is ambiguous).
43
47
@@ -63,7 +67,7 @@ The first write fails with an error like:
63
67
}
64
68
```
65
69
66
-
Ask the user to choose exactly one value from `available_projects`, then retry only `mem_save`or `mem_save_prompt`with both recovery fields:
70
+
Ask the user to choose exactly one value from `available_projects`. For ambiguous-project recovery, retry `mem_save` with BOTH fields:
67
71
68
72
```json
69
73
{
@@ -72,7 +76,7 @@ Ask the user to choose exactly one value from `available_projects`, then retry o
72
76
}
73
77
```
74
78
75
-
On success, Engram writes to the selected project and reports the recovery source:
79
+
On success, `mem_save` writes to the selected project and reports the recovery source:
76
80
77
81
```json
78
82
{
@@ -82,36 +86,63 @@ On success, Engram writes to the selected project and reports the recovery sourc
82
86
}
83
87
```
84
88
89
+
If the exact choices normalize to the same stored project bucket, Engram returns `project_name_collision` instead of writing. Ask the user to rename or disambiguate the colliding projects before retrying.
90
+
85
91
### Ambiguous-project recovery rules
86
92
87
-
This is a narrow rescue path, not a free-form project override:
93
+
Normal `mem_save` precedence:
94
+
95
+
- explicit `project`
96
+
- existing `session_id` project
97
+
- repo `.engram/config.json` / cwd detection
98
+
- directory-basename fallback
88
99
89
-
- Recovery is accepted only after cwd detection failed with `ambiguous_project`.
90
-
-`project_choice_reason` must be exactly `user_selected_after_ambiguous_project`.
91
-
-`project`, after trimming surrounding whitespace, must exactly match one of the reported `available_projects`.
92
-
- Normalized variants and guesses are rejected: if `available_projects` contains `foo--bar`, retry with `foo--bar`, not `foo-bar`.
93
-
- Empty or whitespace-only choices are rejected.
94
-
- In all non-ambiguous cases, `.engram/config.json`/git/cwd detection remains authoritative and the explicit `project` field is ignored.
100
+
Additional rules:
101
+
102
+
-`project`, after trimming surrounding whitespace, must be a name, not a path.
103
+
- Empty, whitespace-only, path-like, or control-character names are rejected.
104
+
- Names are normalized the same way the store normalizes projects.
105
+
- Invalid explicit `project` names fail loudly.
106
+
- Valid-looking explicit `project` names are accepted only when backed by known context: an existing local project in the store, a matching existing session project, the nearest resolvable repo/subproject `.engram/config.json`, or exact ambiguous-project recovery.
107
+
- Unbacked explicit `project` values are rejected; `mem_save(project=...)` is a validated selection, not an arbitrary project-creation path.
108
+
- If `session_id` is provided and no session exists, `mem_save` fails loudly instead of falling back to cwd/config detection.
109
+
- If both explicit `project` and `session_id` are supplied, they must match after normalization or the write is rejected.
110
+
-`project_choice_reason=user_selected_after_ambiguous_project` is only valid when cwd detection is actually ambiguous; stale flags on a non-ambiguous cwd do not override explicit `project` precedence or session mismatch checks.
111
+
- When ambiguous-project recovery is active, `project` must exactly match one of `available_projects`; invented or normalized guesses are rejected.
112
+
- Exact choices may still fail with `project_name_collision` when two available names collapse to the same normalized storage bucket, such as `foo--bar` and `foo-bar`.
113
+
- Ordinary explicit `mem_save(project=...)` calls may also fail with `project_name_collision` when the raw explicit name collapses into an existing config-backed, session-backed, or store-backed project bucket, such as `foo--bar` versus `foo-bar`.
114
+
115
+
`mem_save_prompt` keeps the older cwd/default behavior. Its `project` field is only for ambiguous-project recovery together with `project_choice_reason=user_selected_after_ambiguous_project`.
95
116
96
117
Mental model:
97
118
98
119
```text
99
-
mem_save fails with ambiguous_project
120
+
normal mem_save call
100
121
↓
101
-
Engram returns available_projects
122
+
explicit project wins when valid
102
123
↓
103
-
agent asks the user to choose one exact value
124
+
otherwise existing session project wins
104
125
↓
105
-
agent retries with project + project_choice_reason
126
+
otherwise repo/cwd detection picks the default target
127
+
```
128
+
129
+
Ambiguous recovery:
130
+
131
+
```text
132
+
write fails with ambiguous_project
106
133
↓
107
-
Engram validates the choice came from ambiguity
134
+
user chooses one exact value from available_projects
108
135
↓
109
-
Engram saves to the selected project
136
+
agent retries with project + project_choice_reason
137
+
↓
138
+
Engram validates the exact choice and writes to that repo
110
139
```
111
140
141
+
If validation returns `project_name_collision`, do not guess. Ask the user to disambiguate the project names first.
142
+
112
143
Alternatives: `cd` into the target repo before starting the MCP server, or add repo `.engram/config.json`.
113
144
114
-
**Read tools** (`mem_search`, `mem_context`, `mem_get_observation`, `mem_stats`, `mem_timeline`) accept an optional `project` override validated against the store. Omit it to auto-detect.
145
+
**Read tools** (`mem_search`, `mem_context`, `mem_stats`, `mem_timeline`, `mem_doctor`) accept an optional `project` override validated against the store. Omit it to auto-detect. `mem_get_observation` is ID-based and does not accept a `project` override.
115
146
116
147
---
117
148
@@ -127,7 +158,7 @@ engram setup opencode
127
158
128
159
This does three things:
129
160
1. Copies the plugin to `~/.config/opencode/plugins/engram.ts` (session tracking, Memory Protocol, compaction recovery)
130
-
2. Adds the `engram` MCP server entry to your `opencode.json` with `--tools=agent` (14 agent-facing tools)
161
+
2. Adds the `engram` MCP server entry to your `opencode.json` with `--tools=agent` (15 agent-facing tools)
131
162
3. Adds `opencode-subagent-statusline` to your `tui.json` or `tui.jsonc` so OpenCode shows sub-agent activity in the sidebar/home footer
132
163
133
164
The plugin auto-starts the HTTP server if needed for session tracking. If your environment blocks background processes, run it manually:
@@ -138,7 +169,7 @@ engram serve &
138
169
139
170
> **Windows**: OpenCode uses `~/.config/opencode/` on Windows too (it does not read `%APPDATA%\opencode\`). `engram setup opencode` writes to `~/.config/opencode/plugins/` and `~/.config/opencode/opencode.json`. To run the server in the background: `Start-Process engram -ArgumentList "serve" -WindowStyle Hidden` (PowerShell) or just run `engram serve` in a separate terminal.
140
171
141
-
**Alternative: Manual MCP-only setup** (no plugin, all 18 tools by default):
172
+
**Alternative: Manual MCP-only setup** (no plugin, all 19 tools by default):
142
173
143
174
Add to your `opencode.json` (global: `~/.config/opencode/opencode.json` on all platforms, or project-level):
144
175
@@ -179,7 +210,7 @@ engram setup claude-code
179
210
180
211
During setup, you'll be asked whether to add engram's agent-profile MCP tools to `~/.claude/settings.json``permissions.allow`. The setup writes entries for both the durable user-level MCP server id (`mcp__engram__...`) and the plugin-scoped server id used by older Claude Code plugin installs, so re-running setup repairs stale or incomplete allowlists without adding startup delay.
181
212
182
-
**Option C: Bare MCP** — all 18 tools by default, no session management:
213
+
**Option C: Bare MCP** — all 19 tools by default, no session management:
183
214
184
215
Add to your `.claude/settings.json` (project) or `~/.claude/settings.json` (global):
0 commit comments