greprag 5.20.0 → 5.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -12
- package/dist/codex-steering.d.ts +29 -0
- package/dist/codex-steering.js +168 -0
- package/dist/codex-steering.js.map +1 -0
- package/dist/commands/codex.d.ts +33 -0
- package/dist/commands/codex.js +418 -0
- package/dist/commands/codex.js.map +1 -0
- package/dist/commands/corpus/client.d.ts +1 -0
- package/dist/commands/corpus/client.js.map +1 -1
- package/dist/commands/corpus/search.js +36 -6
- package/dist/commands/corpus/search.js.map +1 -1
- package/dist/commands/corpus/upload.js +24 -1
- package/dist/commands/corpus/upload.js.map +1 -1
- package/dist/commands/discover.d.ts +1 -1
- package/dist/commands/discover.js +1 -1
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +7 -2
- package/dist/commands/init.js +479 -59
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/status.d.ts +22 -10
- package/dist/commands/status.js +159 -69
- package/dist/commands/status.js.map +1 -1
- package/dist/hook.js +120 -13
- package/dist/hook.js.map +1 -1
- package/dist/index.js +20 -10
- package/dist/index.js.map +1 -1
- package/dist/opencode-plugin.d.ts +2 -2
- package/dist/opencode-plugin.js +47 -14
- package/dist/opencode-plugin.js.map +1 -1
- package/dist/project-anchor.d.ts +11 -9
- package/dist/project-anchor.js +58 -27
- package/dist/project-anchor.js.map +1 -1
- package/package.json +4 -2
- package/scripts/postinstall.js +51 -46
- package/skill/greprag/SKILL.md +22 -4
- package/skill/greprag/docs/doctor.md +1 -1
- package/skill/greprag/docs/setup.md +93 -6
- package/skill/lore-advisor/SKILL.md +38 -34
package/scripts/postinstall.js
CHANGED
|
@@ -1,30 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Runs automatically after `npm install -g greprag`.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
4
|
+
// Public UX contract:
|
|
5
|
+
// * `greprag/` — the package's front-door skill. Always installed/refreshed
|
|
6
|
+
// for detected Claude Code and Codex homes so users can type `/greprag`
|
|
7
|
+
// immediately after installing the npm package.
|
|
8
|
+
// * Other bundled skills — refresh-only. If the operator opted in earlier,
|
|
9
|
+
// keep them current; otherwise leave their skill registry alone.
|
|
10
|
+
// * Claude chip-spawn doc — refresh-only, because it is Claude-specific.
|
|
5
11
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// the agent has no idea how to drive `greprag` verbs. Treated as
|
|
9
|
-
// part of the package's identity, not an opt-in advisor.
|
|
10
|
-
//
|
|
11
|
-
// * Every other bundled skill (`discord/`, `content-advisor/`,
|
|
12
|
-
// `lore-advisor/`, future advisors) — REFRESH-ONLY. If the operator
|
|
13
|
-
// opted in (via `greprag skill install <name>` or by accepting the
|
|
14
|
-
// hint in `greprag init`'s closing summary), the dir exists locally
|
|
15
|
-
// and we keep it current with the bundle. If they never opted in,
|
|
16
|
-
// postinstall leaves it alone. Auto-installing every bundled advisor
|
|
17
|
-
// on upgrade was a design defect — extra skills crowd the agent's
|
|
18
|
-
// skill registry and should be consensual.
|
|
19
|
-
//
|
|
20
|
-
// * `chip-spawn.md` doc — refresh-only, same logic as opt-in skills.
|
|
21
|
-
//
|
|
22
|
-
// Closes the staleness gap where `npm i -g greprag@<new>` updated the
|
|
23
|
-
// CLI binary but left `~/.claude/skills/greprag/` files pointing at the
|
|
24
|
-
// old version's expected CLI surface. Without this, the agent's mental
|
|
25
|
-
// model of the CLI drifts away from what the installed binary actually
|
|
26
|
-
// does — see CHANGELOG v5.10.0 (odyssey verb shipped, but local skill
|
|
27
|
-
// stayed at 3.7.0 with no odyssey refs).
|
|
12
|
+
// OpenCode has no slash-skill directory in this package; `greprag init
|
|
13
|
+
// --opencode` installs the plugin.
|
|
28
14
|
|
|
29
15
|
const fs = require('fs');
|
|
30
16
|
const path = require('path');
|
|
@@ -32,8 +18,23 @@ const os = require('os');
|
|
|
32
18
|
|
|
33
19
|
const home = os.homedir();
|
|
34
20
|
const skillRoot = path.join(__dirname, '..', 'skill');
|
|
35
|
-
|
|
36
|
-
const
|
|
21
|
+
|
|
22
|
+
const platformTargets = [
|
|
23
|
+
{
|
|
24
|
+
name: 'Claude Code',
|
|
25
|
+
agentDir: path.join(home, '.claude'),
|
|
26
|
+
skillsTarget: path.join(home, '.claude', 'skills'),
|
|
27
|
+
docsTarget: path.join(home, '.claude', 'docs'),
|
|
28
|
+
refreshClaudeDocs: true,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'Codex',
|
|
32
|
+
agentDir: path.join(home, '.codex'),
|
|
33
|
+
skillsTarget: path.join(home, '.codex', 'skills'),
|
|
34
|
+
docsTarget: path.join(home, '.codex', 'docs'),
|
|
35
|
+
refreshClaudeDocs: false,
|
|
36
|
+
},
|
|
37
|
+
];
|
|
37
38
|
|
|
38
39
|
function copyDir(src, dest) {
|
|
39
40
|
fs.mkdirSync(dest, { recursive: true });
|
|
@@ -45,39 +46,43 @@ function copyDir(src, dest) {
|
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
// `greprag/` always syncs; everything else is opt-in (refresh-only).
|
|
49
49
|
const CORE_SKILL = 'greprag';
|
|
50
|
-
|
|
51
50
|
const refreshed = [];
|
|
52
51
|
const installed = [];
|
|
53
52
|
|
|
54
53
|
try {
|
|
55
|
-
if (fs.existsSync(skillRoot)
|
|
56
|
-
for (const
|
|
57
|
-
if (!
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
if (fs.existsSync(skillRoot)) {
|
|
55
|
+
for (const target of platformTargets) {
|
|
56
|
+
if (!fs.existsSync(target.agentDir)) continue;
|
|
57
|
+
for (const entry of fs.readdirSync(skillRoot, { withFileTypes: true })) {
|
|
58
|
+
if (!entry.isDirectory()) continue;
|
|
59
|
+
if (entry.name === 'templates') continue;
|
|
60
|
+
|
|
61
|
+
const dest = path.join(target.skillsTarget, entry.name);
|
|
62
|
+
const existed = fs.existsSync(dest);
|
|
63
|
+
const isCore = entry.name === CORE_SKILL;
|
|
64
|
+
if (!isCore && !existed) continue;
|
|
65
|
+
|
|
66
|
+
copyDir(path.join(skillRoot, entry.name), dest);
|
|
67
|
+
const label = `${target.name} skills/${entry.name}`;
|
|
68
|
+
if (existed) refreshed.push(label);
|
|
69
|
+
else installed.push(label);
|
|
70
|
+
}
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
} catch (err) {
|
|
70
|
-
// Postinstall must never break the install. Log and continue.
|
|
71
74
|
console.error(' greprag postinstall: skill sync skipped (' + err.message + ')');
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
// Refresh chip-spawn template doc if installed.
|
|
75
77
|
const chipSpawnSrc = path.join(skillRoot, 'templates', 'chip-spawn.md');
|
|
76
|
-
const chipSpawnDest = path.join(docsTarget, 'chip-spawn.md');
|
|
77
78
|
try {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
for (const target of platformTargets) {
|
|
80
|
+
if (!target.refreshClaudeDocs) continue;
|
|
81
|
+
const chipSpawnDest = path.join(target.docsTarget, 'chip-spawn.md');
|
|
82
|
+
if (fs.existsSync(chipSpawnSrc) && fs.existsSync(chipSpawnDest)) {
|
|
83
|
+
fs.copyFileSync(chipSpawnSrc, chipSpawnDest);
|
|
84
|
+
refreshed.push(`${target.name} docs/chip-spawn.md`);
|
|
85
|
+
}
|
|
81
86
|
}
|
|
82
87
|
} catch (err) {
|
|
83
88
|
console.error(' greprag postinstall: chip-spawn refresh skipped (' + err.message + ')');
|
|
@@ -88,5 +93,5 @@ if (changes.length > 0) {
|
|
|
88
93
|
const verb = installed.length > 0 ? 'Synced' : 'Refreshed';
|
|
89
94
|
console.log('\n greprag installed. ' + verb + ': ' + changes.join(', ') + '\n');
|
|
90
95
|
} else {
|
|
91
|
-
console.log('\n greprag installed. Run `greprag init` to connect Claude Code memory.\n');
|
|
96
|
+
console.log('\n greprag installed. Run `greprag init` to connect Claude Code, Codex, or OpenCode memory.\n');
|
|
92
97
|
}
|
package/skill/greprag/SKILL.md
CHANGED
|
@@ -25,7 +25,10 @@ license: MIT
|
|
|
25
25
|
|
|
26
26
|
Single source of truth: `greprag status --json`. Check it → fix any gaps via `docs/setup.md` → search or recap the project's memory.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
Platform setup is progressive:
|
|
29
|
+
- **Codex**: see `docs/setup.md § codex` after install (`greprag init --codex`, then `/hooks` trust review).
|
|
30
|
+
- **Claude Code**: see `docs/setup.md § claude-code` for the default hook/Monitor/conventions path (`greprag init --claude` or detected `greprag init`).
|
|
31
|
+
- **OpenCode**: see `docs/setup.md § opencode` for plugin install (`greprag init --opencode`).
|
|
29
32
|
|
|
30
33
|
## Step 1 — Status
|
|
31
34
|
|
|
@@ -38,7 +41,16 @@ Parse JSON. Inspect in order:
|
|
|
38
41
|
2. `project.anchor_found`
|
|
39
42
|
3. `project.memory_capture`, `project.session_start_recap`, `project.inbox_notify`
|
|
40
43
|
|
|
41
|
-
For Claude Code, also: `hooks.session_start_recap`, `hooks.stop_store`, `hooks.
|
|
44
|
+
For Claude Code, also: `platforms.claude.configured`, `platforms.claude.hooks.session_start_recap`, `platforms.claude.hooks.stop_store`, `platforms.claude.hooks.pre_tool_use_spawn_check`.
|
|
45
|
+
|
|
46
|
+
For OpenCode, also: `platforms.opencode.configured`, `platforms.opencode.plugin_installed`.
|
|
47
|
+
|
|
48
|
+
For Codex, also inspect:
|
|
49
|
+
```bash
|
|
50
|
+
node -e "const fs=require('fs'),os=require('os'),p=require('path');const hp=p.join(os.homedir(),'.codex','hooks.json');const envp=p.join(os.homedir(),'.greprag','.env');let h={};try{h=JSON.parse(fs.readFileSync(hp,'utf8'))}catch{};const has=(evt,cmd)=>((h.hooks&&h.hooks[evt])||[]).some(e=>(e.hooks||[]).some(x=>(x.command||'').includes(cmd)));console.log(fs.existsSync(envp)?'CODEX_ENV_OK':'CODEX_ENV_MISSING');console.log(has('UserPromptSubmit','codex-notify')?'CODEX_NOTIFY_OK':'CODEX_NOTIFY_MISSING');console.log(has('PostToolUse','codex-inbox')?'CODEX_INBOX_OK':'CODEX_INBOX_MISSING');console.log(has('Stop','codex-store')?'CODEX_STORE_OK':'CODEX_STORE_MISSING');console.log(has('SessionStart','recap')?'CODEX_RECAP_OK':'CODEX_RECAP_MISSING');"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
If any Codex check is missing, route to `docs/setup.md § codex`. If hooks exist but memory is not being captured, remind the user to run Codex `/hooks`, trust the GrepRAG commands, and start a fresh session.
|
|
42
54
|
|
|
43
55
|
Chip-spawn convention marker (in `~/.claude/CLAUDE.md`):
|
|
44
56
|
```bash
|
|
@@ -59,6 +71,7 @@ node -e "const s=JSON.parse(require('fs').readFileSync(require('os').homedir()+'
|
|
|
59
71
|
|---|---|
|
|
60
72
|
| `auth.api_key_present === false` | `docs/setup.md § auth` |
|
|
61
73
|
| Any hook is false | `docs/setup.md § hooks` |
|
|
74
|
+
| Any Codex check is missing, or hooks installed but not firing | `docs/setup.md § codex` |
|
|
62
75
|
| Convention marker missing/outdated, or `DOC_MISSING` | `docs/setup.md § conventions` |
|
|
63
76
|
| `MON_MISSING` | `docs/setup.md § permissions` |
|
|
64
77
|
| `project.anchor_found === false` | `docs/setup.md § anchor` |
|
|
@@ -106,13 +119,18 @@ Aliases (silent back-compat): `greprag memory briefing` → `recap` (renamed v5.
|
|
|
106
119
|
|
|
107
120
|
## Proactive-fire rules
|
|
108
121
|
|
|
109
|
-
**ABOUT TO BACKGROUND A `greprag inbox watch`? USE THE `Monitor` AGENT TOOL, NOT `Bash(run_in_background: true)`.** Bash background notifies only on process completion; watchers run forever, so the agent gets zero events until it manually reads the output file. Wrap with `while true; do greprag inbox watch ...; done` so the loop survives inner crashes. Full pattern: `docs/inbox-watch.md`.
|
|
122
|
+
**Claude Code: ABOUT TO BACKGROUND A `greprag inbox watch`? USE THE `Monitor` AGENT TOOL, NOT `Bash(run_in_background: true)`.** Bash background notifies only on process completion; watchers run forever, so the agent gets zero events until it manually reads the output file. Wrap with `while true; do greprag inbox watch ...; done` so the loop survives inner crashes. Full pattern: `docs/inbox-watch.md`.
|
|
123
|
+
|
|
124
|
+
**Codex: DO NOT CLAIM HOOKS ARE ACTIVE JUST BECAUSE `~/.codex/hooks.json` EXISTS.** Codex requires `/hooks` trust review before command hooks run automatically. If turn capture is missing after `greprag init --codex`, tell the user: run `/hooks`, trust the GrepRAG hooks, then start a fresh Codex session.
|
|
125
|
+
|
|
126
|
+
**Codex live inbox push requires the startup watcher.** Hooks only fire at Codex turn/tool/session boundaries. Run `greprag codex startup install` for public/user installs; use `greprag codex watch --session <id>` only for foreground testing. The sidecar listens to GrepRAG inbox SSE and wakes Codex via `codex exec resume`. Without it, messages are stored but idle Codex is not woken.
|
|
110
127
|
|
|
111
128
|
**ABOUT TO SEND TO A `@gmail.com` / `@anthropic.com` / REAL EMAIL ADDRESS? STOP — `users.email` IS NEVER A ROUTING ADDRESS.** Use the numeric handle (`1834729@greprag.com`) or claimed vanity alias (`travis@greprag.com`). If you don't know the recipient's handle, ASK — don't guess from their email. adr: adr/numeric-handles.md. Full grammar: `docs/inbox.md § address`.
|
|
112
129
|
|
|
113
130
|
## Reference index
|
|
114
131
|
|
|
115
|
-
- `docs/setup.md` — auth · hooks · conventions · permissions · channels · anchor ·
|
|
132
|
+
- `docs/setup.md` — codex · claude-code · opencode · auth · hooks · conventions · permissions · channels · anchor · bulk-register
|
|
133
|
+
- `docs/platforms.md` — exact platform paths for Claude Code · Codex · OpenCode
|
|
116
134
|
- `docs/per-project-flags.md` — flip `memory_capture` / `session_start_recap` / `inbox_notify`
|
|
117
135
|
- `docs/inbox.md` — `greprag send`, `greprag inbox`, address grammar, retract
|
|
118
136
|
- `docs/inbox-watch.md` — SSE watcher patterns, liveness model, parent-side / post-send patterns
|
|
@@ -11,7 +11,7 @@ What it does:
|
|
|
11
11
|
2. Computes what the git-derived UUID *would* be (if in a git repo with commits)
|
|
12
12
|
3. Queries the API for sibling project_ids under the same profile name (orphans — usually from old anchor files lost to gitignore or a hash-fallback period before init)
|
|
13
13
|
4. Presents findings and offers actions:
|
|
14
|
-
- **Migrate to git-derived UUID** (recommended on drift) — moves current + orphan rows onto the git-derived ID and strips `project_id` from
|
|
14
|
+
- **Migrate to git-derived UUID** (recommended on drift) — moves current + orphan rows onto the git-derived ID and strips `project_id` from the project anchor so identity flows from git history going forward
|
|
15
15
|
- **Consolidate orphans into current UUID** — keeps current identity but pulls orphan rows in
|
|
16
16
|
- **Dry-run** — runs the recommended action through the API with `dry_run: true` so the user sees exactly what would change before committing
|
|
17
17
|
|
|
@@ -2,6 +2,82 @@
|
|
|
2
2
|
|
|
3
3
|
Routes for each gap surfaced by `greprag status --json`. Re-run status after each fix and continue down the list.
|
|
4
4
|
|
|
5
|
+
## codex
|
|
6
|
+
|
|
7
|
+
Codex users install once:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
greprag init --codex
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This writes `~/.greprag/.env` plus `~/.codex/hooks.json`. The Codex hooks are:
|
|
14
|
+
|
|
15
|
+
- `SessionStart` → `greprag-hook recap`
|
|
16
|
+
- `SessionStart` → `greprag-hook session-id`
|
|
17
|
+
- `UserPromptSubmit` → `greprag-hook codex-notify`
|
|
18
|
+
- `PostToolUse` → `greprag-hook codex-inbox`
|
|
19
|
+
- `Stop` → `greprag-hook codex-store`
|
|
20
|
+
- `PostCompact` → `greprag-hook session-id`
|
|
21
|
+
|
|
22
|
+
It also installs the bundled `/greprag` skill at
|
|
23
|
+
`~/.codex/skills/greprag` and refreshes the shared identity cache at
|
|
24
|
+
`~/.greprag/identity.json`.
|
|
25
|
+
|
|
26
|
+
Interactive init offers to install the live inbox watcher at login. In
|
|
27
|
+
non-interactive contexts, run it explicitly:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
greprag codex startup install
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
After install, Codex still requires trust review. Tell the user:
|
|
34
|
+
|
|
35
|
+
> Run `/hooks`, trust the GrepRAG hooks, then start a fresh Codex session.
|
|
36
|
+
|
|
37
|
+
Do not try to approve `/hooks` on the user's behalf. It is Codex's trust gate
|
|
38
|
+
for local command execution.
|
|
39
|
+
|
|
40
|
+
Codex-specific diagnostics:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
test -f ~/.greprag/.env && echo CODEX_ENV_OK || echo CODEX_ENV_MISSING
|
|
44
|
+
test -f ~/.codex/hooks.json && echo CODEX_HOOKS_FILE_OK || echo CODEX_HOOKS_FILE_MISSING
|
|
45
|
+
node -e "const fs=require('fs'),os=require('os'),p=require('path');const hp=p.join(os.homedir(),'.codex','hooks.json');let h={};try{h=JSON.parse(fs.readFileSync(hp,'utf8'))}catch{};const has=(evt,cmd)=>((h.hooks&&h.hooks[evt])||[]).some(e=>(e.hooks||[]).some(x=>(x.command||'').includes(cmd)));console.log(has('UserPromptSubmit','codex-notify')?'CODEX_NOTIFY_OK':'CODEX_NOTIFY_MISSING');console.log(has('PostToolUse','codex-inbox')?'CODEX_INBOX_OK':'CODEX_INBOX_MISSING');console.log(has('Stop','codex-store')?'CODEX_STORE_OK':'CODEX_STORE_MISSING');console.log(has('SessionStart','recap')?'CODEX_RECAP_OK':'CODEX_RECAP_MISSING');console.log(has('PostCompact','session-id')?'CODEX_POSTCOMPACT_OK':'CODEX_POSTCOMPACT_MISSING');"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If hook entries are missing, re-run `greprag init --codex`. If entries exist
|
|
49
|
+
but turns are not saving, the most likely cause is untrusted hooks or an old
|
|
50
|
+
session that started before trust. Tell the user to run `/hooks`, trust the
|
|
51
|
+
GrepRAG commands, and restart Codex.
|
|
52
|
+
|
|
53
|
+
Codex live inbox delivery requires the sidecar. Public installs should use the
|
|
54
|
+
startup helper above. For foreground/manual testing:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
greprag codex watch --session <8hex-or-full-codex-session-id>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
If `--session` is omitted, it uses the latest Codex session recorded in
|
|
61
|
+
`~/.codex/session_index.jsonl`. The sidecar stays attached to GrepRAG inbox SSE
|
|
62
|
+
and wakes Codex with `codex exec resume <session> -` whenever a message arrives.
|
|
63
|
+
Use `greprag codex startup status` to inspect the login entry and
|
|
64
|
+
`greprag codex startup remove` to uninstall it.
|
|
65
|
+
|
|
66
|
+
`codex-notify` and `codex-inbox` remain fallback steering. If the sidecar is not
|
|
67
|
+
running, messages are stored and can surface on the next user prompt or after a
|
|
68
|
+
later tool call, but they do not wake idle Codex.
|
|
69
|
+
|
|
70
|
+
## claude-code
|
|
71
|
+
|
|
72
|
+
Claude Code users install once:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
greprag init --claude
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Bare `greprag init` may auto-detect Claude Code or ask which platform to
|
|
79
|
+
configure. The explicit flag is best for docs and scripts.
|
|
80
|
+
|
|
5
81
|
## opencode
|
|
6
82
|
|
|
7
83
|
OpenCode users install once:
|
|
@@ -10,7 +86,12 @@ OpenCode users install once:
|
|
|
10
86
|
greprag init --opencode
|
|
11
87
|
```
|
|
12
88
|
|
|
13
|
-
Plugin at `~/.config/opencode/plugins/greprag-memory.
|
|
89
|
+
Plugin at `~/.config/opencode/plugins/greprag-memory.js` runs silently:
|
|
90
|
+
injects recap via system prompt and stores turns automatically. It reads
|
|
91
|
+
`~/.greprag/.env` first and falls back to `~/.claude/settings.json` for older
|
|
92
|
+
installs. All platforms share the same anchor (`.greprag/project.json` or
|
|
93
|
+
git-derived identity). Legacy `.claude/project.json` anchors still read and
|
|
94
|
+
migrate on init.
|
|
14
95
|
|
|
15
96
|
## bulk-register
|
|
16
97
|
|
|
@@ -45,11 +126,17 @@ Trigger: `auth.api_key_present === false`.
|
|
|
45
126
|
```
|
|
46
127
|
Response: `{"ok":true,"apiKey":"grp_live_...","userId":"...","tenantId":"..."}`.
|
|
47
128
|
|
|
48
|
-
5. Write the key into
|
|
129
|
+
5. Write the key into the platform's config:
|
|
130
|
+
- Claude Code: `~/.claude/settings.json` under `env.GREPRAG_API_KEY`; also set `env.MEMORY_HOOK_ENABLED = "true"`.
|
|
131
|
+
- Codex/OpenCode: `~/.greprag/.env` with `GREPRAG_API_KEY=<key>` and `MEMORY_HOOK_ENABLED=true`.
|
|
132
|
+
|
|
133
|
+
Prefer re-running the platform init command (`greprag init --claude`, `--codex`, or `--opencode`) because it writes the right files and refreshes identity/platform assets.
|
|
49
134
|
|
|
50
135
|
## hooks
|
|
51
136
|
|
|
52
|
-
Trigger: any of `hooks.session_start_recap`,
|
|
137
|
+
Trigger: any of `platforms.claude.hooks.session_start_recap`,
|
|
138
|
+
`platforms.claude.hooks.stop_store`, or
|
|
139
|
+
`platforms.claude.hooks.pre_tool_use_spawn_check` is false.
|
|
53
140
|
|
|
54
141
|
Append missing entries to the existing arrays in `~/.claude/settings.json` (create the arrays if absent). Don't overwrite hooks from other tools.
|
|
55
142
|
|
|
@@ -69,7 +156,7 @@ Append missing entries to the existing arrays in `~/.claude/settings.json` (crea
|
|
|
69
156
|
|
|
70
157
|
The legacy `user_prompt_submit_notify` hook was removed in v5.6.1 — live inbox delivery is now the Monitor watcher's job. Do not install it.
|
|
71
158
|
|
|
72
|
-
**Removing the legacy PostToolUse spawn-reminder hook** (only on upgrade from v0.x → v0.12+): if `hooks.PostToolUse` contains an entry with `matcher: "mcp__ccd_session__spawn_task"` and `command: "greprag-hook spawn-reminder"`, delete it. The behavior is now
|
|
159
|
+
**Removing the legacy PostToolUse spawn-reminder hook** (only on upgrade from v0.x → v0.12+): if `hooks.PostToolUse` contains an entry with `matcher: "mcp__ccd_session__spawn_task"` and `command: "greprag-hook spawn-reminder"`, delete it. The behavior is now handled by `UserPromptSubmit` watcher steering plus the PreToolUse validator.
|
|
73
160
|
|
|
74
161
|
## conventions
|
|
75
162
|
|
|
@@ -184,8 +271,8 @@ If yes, use the existing `project_id` in the new anchor. If no, mint fresh: `nod
|
|
|
184
271
|
|
|
185
272
|
Write the file:
|
|
186
273
|
```bash
|
|
187
|
-
mkdir -p <cwd>/.
|
|
188
|
-
cat > <cwd>/.
|
|
274
|
+
mkdir -p <cwd>/.greprag
|
|
275
|
+
cat > <cwd>/.greprag/project.json <<EOF
|
|
189
276
|
{
|
|
190
277
|
"project_id": "<UUID>",
|
|
191
278
|
"project_name": "<basename, lowercased>",
|
|
@@ -9,16 +9,20 @@ description: |
|
|
|
9
9
|
"lore is stale", "prune lore", "mine episodic for lore".
|
|
10
10
|
metadata:
|
|
11
11
|
author: travsteward
|
|
12
|
-
version: "1.
|
|
12
|
+
version: "1.1.0"
|
|
13
13
|
repository: https://github.com/travsteward/greprag
|
|
14
14
|
license: MIT
|
|
15
15
|
---
|
|
16
16
|
|
|
17
17
|
# Lore Advisor
|
|
18
18
|
|
|
19
|
-
Project lore = LEARNINGS
|
|
19
|
+
Project lore = durable LEARNINGS — reusable system properties, constraints, and gotchas worth re-surfacing in a future session. Seeded via `greprag lore add`, mined from episodic memory's `learned` / `ruled_out` claims. Distinct from static project knowledge (CLAUDE.md, docs, code) AND from session narration / transient run-state. Lore decays — paths change, conventions die, "learned that X" stops being true. This skill keeps the substrate healthy.
|
|
20
20
|
|
|
21
|
-
The skill is
|
|
21
|
+
**The advisor's core skill is one judgment: durable lore vs ephemeral noise.** Episodic memory is a firehose — only ~1 claim in 10 is durable lore; the rest is session narration, run-state, or docs material. No regex finds the keepers; the advisor's read does. The durability gate below makes that judgment explicit.
|
|
22
|
+
|
|
23
|
+
Lore is moving from a passive list toward **event-bound / semantic injection** — pushed at the agent when relevant, not browsed (greprag design: `docs/lore-triggers.md`). Until PUSH ships, add lore durable-first so it is injection-ready.
|
|
24
|
+
|
|
25
|
+
The skill is **conversational**, not autonomous. Every prune / promote / edit / add decision goes through the operator one at a time. Bulk actions are forbidden.
|
|
22
26
|
|
|
23
27
|
## Trigger phrases
|
|
24
28
|
|
|
@@ -28,10 +32,20 @@ The skill is **conversational**, not autonomous. Every prune / promote / edit de
|
|
|
28
32
|
|
|
29
33
|
Three phases, run in order. Operator may skip any phase. Each phase walks one entry at a time — never bulk-prune.
|
|
30
34
|
|
|
31
|
-
- **Phase A — Drift check.**
|
|
32
|
-
- **Phase B — Episodic mining.**
|
|
35
|
+
- **Phase A — Drift check.** Scan current lore for rot: stale file paths, conventions the codebase no longer follows (derived live, NOT from a static list), misfiled static-knowledge, age-based decay.
|
|
36
|
+
- **Phase B — Episodic mining.** Mine episodic memory's `learned` / `ruled_out` claims; surface only candidates that pass the durability gate; offer to add.
|
|
33
37
|
- **Phase C — Global promotion.** Identify project-agnostic lore that belongs in `~/.claude/docs/chip-spawn.md` as a universal rule.
|
|
34
38
|
|
|
39
|
+
## The durability gate (core discipline)
|
|
40
|
+
|
|
41
|
+
Before lore is kept (Phase A), added (Phase B), or promoted (Phase C), it must pass three tests. Fail ANY → it is not lore.
|
|
42
|
+
|
|
43
|
+
1. **DURABLE** — a standing property, rule, constraint, or gotcha true beyond one session. NOT point-in-time state. ✗ "no watcher was running", "the id was still e582edf0", "the corpus is proven end-to-end".
|
|
44
|
+
2. **REUSABLE** — would help a FUTURE session understand the system or avoid a mistake. NOT narration of work done. ✗ "Chip C split corpus.ts into eight modules", "the CLI was bumped to v5.16.0". Abstract instances to rules: "sub 3006's price is archived" → "an inactive Stripe price blocks dunning-recovery".
|
|
45
|
+
3. **NON-OBVIOUS** — a property you could not read off the surface. ✓ "Postgres caps a statement at 65,535 bind parameters". ✗ "the API runs on Cloudflare Workers" (ambient project knowledge → belongs in docs, not lore).
|
|
46
|
+
|
|
47
|
+
This is the same gate the hourly compactor applies at write-time (greprag, 2026-06-01) — advisor and compactor converge on one filter.
|
|
48
|
+
|
|
35
49
|
## Forbidden practices (HARD RULES)
|
|
36
50
|
|
|
37
51
|
- **Never delete lore without explicit operator confirmation.** Each delete is its own y/n.
|
|
@@ -57,17 +71,13 @@ Three phases, run in order. Operator may skip any phase. Each phase walks one en
|
|
|
57
71
|
```
|
|
58
72
|
If MISSING → flag with `reason: "file-not-found:<path>"`.
|
|
59
73
|
|
|
60
|
-
- **Killed-convention check.**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
- `agent-coordination.md` (deep doc deleted in v5.6.0; replaced by `chip-spawn.md`)
|
|
66
|
-
- `inline-conventions` / `greprag-conventions:start v1`, `v2`, `v3`, `v4` (superseded by v5 pointer)
|
|
67
|
-
- `MEMORY_HOOK_ENABLED` legacy boolean (now ambient)
|
|
68
|
-
- `greprag fact` (renamed to `greprag lore` in v5.7.0 — the alias is removed in v5.8.0)
|
|
74
|
+
- **Killed-convention check.** A convention can die — a renamed command, a replaced address grammar, a removed hook. The drift signal is NOT a hardcoded list: a static list of dead conventions rots like any other frozen artifact (it has no provenance and no one maintains it — the exact failure this skill exists to fight). Derive it live instead. Cross-reference the lore text against recent `ruled_out` claims and the project CHANGELOG / releases:
|
|
75
|
+
```bash
|
|
76
|
+
greprag memory search "<key term> renamed OR removed OR replaced OR deprecated"
|
|
77
|
+
```
|
|
78
|
+
If the lore asserts a convention the codebase no longer follows → flag `reason: "dead-convention"`.
|
|
69
79
|
|
|
70
|
-
|
|
80
|
+
- **Misfiled-convention check.** Flag lore that is really *static project knowledge* — a build/deploy command, a file-path map, an architecture rule, a coding standard — which belongs in CLAUDE.md / `docs/`, not in decay-prone lore. This is the most common rot: a bulk seed of conventions poured into lore that then drifts out of sync with the docs (it fails the durability gate's REUSABLE/NON-OBVIOUS tests — it is ambient knowledge, usually already documented elsewhere). Flag `reason: "misfiled-convention"`.
|
|
71
81
|
|
|
72
82
|
- **Age check.** If `createdAt` is older than 90 days from today AND no other heuristic fired, flag with `reason: "age-90d:<days>"`. Not automatically stale — just worth re-verifying.
|
|
73
83
|
|
|
@@ -90,45 +100,38 @@ Three phases, run in order. Operator may skip any phase. Each phase walks one en
|
|
|
90
100
|
|
|
91
101
|
### Phase B — Episodic mining
|
|
92
102
|
|
|
103
|
+
The richest lore source is the compactor's structured `learned` / `ruled_out` claims (tagged nodes, one per durable learning). As of greprag 2026-06-01 the hourly compactor applies the durability gate at write-time, so these claims are already durable-first — but the advisor's read is still what separates lore-grade from the rest.
|
|
104
|
+
|
|
93
105
|
1. Resolve the current project's `projectId`:
|
|
94
106
|
```bash
|
|
95
107
|
greprag project-id
|
|
96
108
|
```
|
|
97
109
|
|
|
98
|
-
2. Pull
|
|
110
|
+
2. Pull recent episodic memory (last 30 days). Claims are not yet exposed via a dedicated CLI surface, so mine the daily/hourly summaries — which now carry the compactor's durable claims:
|
|
99
111
|
```bash
|
|
100
112
|
FROM=$(date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)
|
|
101
113
|
TO=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
102
114
|
curl -sf "https://api.greprag.com/v1/memory/by-period?projectId=<projectId>&type=daily&from=$FROM&to=$TO&limit=30" \
|
|
103
115
|
-H "Authorization: Bearer $GREPRAG_API_KEY"
|
|
104
116
|
```
|
|
105
|
-
Parse `rows[]
|
|
106
|
-
|
|
107
|
-
3. For each daily summary, scan the body for sentences containing any of these marker phrases (case-insensitive):
|
|
108
|
-
- `learned that`
|
|
109
|
-
- `the gotcha is`
|
|
110
|
-
- `won't work because`
|
|
111
|
-
- `had to`
|
|
112
|
-
- `discovered that`
|
|
113
|
-
- `turns out`
|
|
114
|
-
- `surprised that`
|
|
117
|
+
Parse `rows[]` (`created_at`, `body`). *(When a `greprag memory claims --tag learned,ruled_out` surface exists, prefer it — it returns the structured claims directly, no prose scan.)*
|
|
115
118
|
|
|
116
|
-
|
|
119
|
+
3. Find candidate learnings — sentences signalling a durable property. Markers: `learned that`, `the gotcha is`, `won't work because`, `turns out`, `requires`, `only … if`, `caps at`, `blocks`. Skip < 30 or > 300 chars.
|
|
117
120
|
|
|
118
|
-
4.
|
|
121
|
+
4. **Apply the durability gate to every candidate.** Most fail — that is correct and expected (~90% of raw learnings are not lore). Surface ONLY candidates that pass all three tests, one at a time:
|
|
119
122
|
```
|
|
120
|
-
|
|
123
|
+
Candidate (durable · reusable · non-obvious):
|
|
121
124
|
"<sentence>"
|
|
122
|
-
|
|
125
|
+
Add to lore? (a)dd / (e)dit / (s)kip
|
|
123
126
|
```
|
|
124
|
-
- **
|
|
127
|
+
- **add** → ask for scope (`general`; `env` for credentials/vars; or a `<subsystem>-touch` tag naming the moment it would be injected). Then:
|
|
125
128
|
```bash
|
|
126
129
|
greprag lore add "<sentence>" --scope <scope>
|
|
127
130
|
```
|
|
128
|
-
- **edit** →
|
|
131
|
+
- **edit** → polish to a clean standing rule (abstract any instance → rule), then add.
|
|
129
132
|
- **skip** → no-op.
|
|
130
133
|
|
|
131
|
-
5. Phase summary: `Phase B: scanned N
|
|
134
|
+
5. Phase summary: `Phase B: scanned N summaries, M passed the durability gate. Added A. Skipped S.`
|
|
132
135
|
|
|
133
136
|
### Phase C — Global promotion
|
|
134
137
|
|
|
@@ -179,5 +182,6 @@ If any phase was skipped (operator pressed q / Ctrl-C / typed "skip phase"), inc
|
|
|
179
182
|
## Notes
|
|
180
183
|
|
|
181
184
|
- This skill is operator-driven. Each phase pauses for input. Don't batch decisions — that defeats the purpose.
|
|
182
|
-
- For new lore added in Phase B, prefer the
|
|
185
|
+
- For new lore added in Phase B, prefer the compactor's phrasing — but rewrite to a clean standing rule when it embeds an instance ("sub 3006…") or transient framing.
|
|
183
186
|
- For Phase C promotions, prefer the original phrasing too — but rewrite if the lore embeds a project-specific noun that needs generalizing.
|
|
187
|
+
- **Convergence:** the compactor's write-time durability gate (greprag `docs/episodic-memory-changelog.md`, 2026-06-01) and this skill's gate are the same filter. As the compactor tightens, Phase B's yield rises and this skill shifts from "find lore" toward "wire lore to its injection trigger" (`docs/lore-triggers.md`).
|