agentcache 0.4.0 → 0.4.1
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 +151 -221
- package/dist/{chunk-ESDTP63R.js → chunk-PSASDZQE.js} +8 -2
- package/dist/cli.js +10 -10
- package/dist/{compile-all-GFWXWRPX.js → compile-all-7ESDEBFG.js} +1 -1
- package/dist/mcp.js +47 -5
- package/dist/postinstall.js +1 -1
- package/dist/{pre-tool-use-D3GM3GEQ.js → pre-tool-use-7F7NTHCS.js} +1 -1
- package/dist/{session-start-2OKCIAGB.js → session-start-EIHYCS3J.js} +1 -1
- package/dist/{setup-HE7ZHOEI.js → setup-45BVUDXN.js} +1 -1
- package/dist/{sqlite-MHG4WEHL.js → sqlite-NM2BVHUY.js} +1 -1
- package/dist/{stop-YDXXQJCE.js → stop-TPCRE7RE.js} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
# AgentCache
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Your AI coding agents forget everything between sessions. AgentCache fixes that — it learns what you know, remembers it across sessions, and injects it into every future agent automatically, across every IDE.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> "Don't mock the database in integration tests — we got burned when mocked tests passed but prod migration failed"
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
That lesson, learned once, becomes a permanent rule. Every future session with every IDE gets it. You never say it again.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## What it does
|
|
10
10
|
|
|
11
|
-
AgentCache
|
|
12
|
-
|
|
11
|
+
AgentCache observes your coding sessions and compiles reusable knowledge — rules, lessons, architectural decisions, project context — into a local database. Every future session gets that knowledge injected at the start, regardless of IDE or LLM.
|
|
12
|
+
|
|
13
|
+
- **Learns** from what your agents discover during sessions
|
|
13
14
|
- **Injects** relevant knowledge at the start of every new session
|
|
14
15
|
- **Works everywhere** — any IDE, any LLM, simultaneously
|
|
15
|
-
- **Stays local** — SQLite
|
|
16
|
+
- **Stays local** — SQLite on your machine, nothing leaves your disk
|
|
16
17
|
|
|
17
18
|
## Install
|
|
18
19
|
|
|
@@ -20,294 +21,223 @@ AgentCache fixes this. It's a persistent knowledge layer that:
|
|
|
20
21
|
npm install -g agentcache
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
Done. Start a
|
|
24
|
+
Done. Start a session in any IDE — AgentCache is already running.
|
|
25
|
+
|
|
26
|
+
No init. No setup. No config. The install:
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
1. Creates `~/.agentcache/agentcache.db` (your knowledge store)
|
|
28
|
+
1. Creates `~/.agentcache/agentcache.db`
|
|
27
29
|
2. Detects installed IDEs (Claude Code, Cursor, Roo Code, Windsurf, Continue, Codex)
|
|
28
30
|
3. Registers itself as an MCP server in each
|
|
29
31
|
4. Sets up Claude Code hooks for automatic transcript recovery
|
|
30
|
-
5. Spawns `compile-all` in background
|
|
32
|
+
5. Spawns `compile-all` in background to process your existing transcript history
|
|
31
33
|
|
|
32
|
-
##
|
|
34
|
+
## Team knowledge — without a sync server
|
|
35
|
+
|
|
36
|
+
Compiled project knowledge is written to `<repo>/.agentcache/skills/project-knowledge/SKILL.md`. Commit it. Every teammate gets your team's accumulated decisions and context on clone, automatically picked up by any Agent Skills-compatible tool.
|
|
37
|
+
|
|
38
|
+
```markdown
|
|
39
|
+
## Decisions
|
|
40
|
+
- Using Drizzle ORM over Prisma for raw SQL escape hatches
|
|
41
|
+
- PostgreSQL for all persistent state, Redis for ephemeral cache only
|
|
42
|
+
|
|
43
|
+
## Current Context
|
|
44
|
+
- Migrating from REST to GraphQL, both coexist until Q3
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
No sync server. No accounts. Just git.
|
|
48
|
+
|
|
49
|
+
## How it works
|
|
33
50
|
|
|
34
51
|
```
|
|
35
52
|
┌────────────────────────────────────────────────────────────────────────┐
|
|
36
53
|
│ Your Machine │
|
|
37
54
|
│ │
|
|
38
|
-
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
39
|
-
│ │ Claude │ │ Cursor │ │ Roo │ │ Codex │ ...
|
|
40
|
-
│ │ Code │ │ │ │ Code │ │ │
|
|
41
|
-
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
|
|
42
|
-
│ │
|
|
43
|
-
│
|
|
44
|
-
│
|
|
45
|
-
│
|
|
55
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
56
|
+
│ │ Claude │ │ Cursor │ │ Roo │ │ Codex │ ... │
|
|
57
|
+
│ │ Code │ │ │ │ Code │ │ │ │
|
|
58
|
+
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
|
|
59
|
+
│ └─────────────┴─────────────┴─────────────┘ │
|
|
60
|
+
│ │ MCP Protocol (stdio) │
|
|
61
|
+
│ ┌────────────┴────────────┐ │
|
|
62
|
+
│ │ AgentCache MCP Server │ │
|
|
63
|
+
│ └────────────┬────────────┘ │
|
|
46
64
|
│ │ │
|
|
47
|
-
│
|
|
48
|
-
│
|
|
49
|
-
│
|
|
50
|
-
│
|
|
51
|
-
│
|
|
52
|
-
│ │ when pending > 20 │ │ Uses: claude, │ │
|
|
53
|
-
│ └────────────┬────────────┘ │ codex, gemini, │ │
|
|
54
|
-
│ │ │ ollama, API keys │ │
|
|
55
|
-
│ │ └─────────┬──────────┘ │
|
|
56
|
-
│ │ │ │
|
|
57
|
-
│ ┌─────────┴────────────────────────────┘ │
|
|
58
|
-
│ │ │
|
|
59
|
-
│ ▼ │
|
|
60
|
-
│ ┌────────────────────┐ │
|
|
61
|
-
│ │ ~/.agentcache/ │ │
|
|
62
|
-
│ │ agentcache.db │ │
|
|
63
|
-
│ │ compile-all.lock │ │
|
|
64
|
-
│ │ (SQLite + WAL) │ │
|
|
65
|
-
│ └────────────────────┘ │
|
|
65
|
+
│ ┌─────────┴──────────┐ │
|
|
66
|
+
│ │ ~/.agentcache/ │ │
|
|
67
|
+
│ │ agentcache.db │ │
|
|
68
|
+
│ │ (SQLite + WAL) │ │
|
|
69
|
+
│ └────────────────────┘ │
|
|
66
70
|
└────────────────────────────────────────────────────────────────────────┘
|
|
67
71
|
```
|
|
68
72
|
|
|
69
|
-
### The
|
|
73
|
+
### The cycle
|
|
70
74
|
|
|
71
|
-
1. **Session starts** — agent calls `inject_context` →
|
|
75
|
+
1. **Session starts** — agent calls `inject_context` → receives compiled rules, lessons, decisions
|
|
72
76
|
2. **During session** — agent calls `compile_submit` incrementally as it learns things
|
|
73
|
-
3. **Session ends** —
|
|
77
|
+
3. **Session ends** — observations are already saved. If the session terminates unexpectedly, transcript recovery handles it next time.
|
|
74
78
|
|
|
75
|
-
### Knowledge
|
|
79
|
+
### Knowledge types
|
|
76
80
|
|
|
77
81
|
| Type | Scope | Example |
|
|
78
82
|
|------|-------|---------|
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
+
| Rule | Global | "Always use snake_case for database columns" |
|
|
84
|
+
| Lesson | Global | "Don't mock the database in integration tests — mocked tests passed but prod migration failed" |
|
|
85
|
+
| Decision | Project | "Using Drizzle ORM over Prisma because we need raw SQL escape hatches" |
|
|
86
|
+
| Context | Project | "Currently migrating from REST to GraphQL, both coexist" |
|
|
83
87
|
|
|
84
|
-
Rules and lessons are
|
|
88
|
+
Rules and lessons are global — they apply to all your projects. Decisions and context are project-scoped.
|
|
85
89
|
|
|
86
|
-
##
|
|
90
|
+
## Security model
|
|
87
91
|
|
|
88
|
-
AgentCache
|
|
92
|
+
AgentCache creates a persistent feedback loop: agents write observations → observations compile into knowledge → knowledge injects into future sessions. This is the product's core value **and** its main attack surface. Both are the same thing.
|
|
89
93
|
|
|
90
|
-
|
|
91
|
-
|------|---------|
|
|
92
|
-
| `inject_context` | Load compiled knowledge at session start |
|
|
93
|
-
| `compile_submit` | Submit observations incrementally during session |
|
|
94
|
-
| `compile_cluster` | Resolve clustering when observations overlap existing knowledge |
|
|
95
|
-
| `compile_extract` | Process queued transcripts from previous sessions |
|
|
96
|
-
| `enforce` | Check tool calls against enforced policy rules |
|
|
97
|
-
| `save_observation` | Save a permanent observation (USER authority, never auto-deprecated) |
|
|
98
|
-
| `get_knowledge` | Query the knowledge database |
|
|
99
|
-
| `deprecate_knowledge` | Mark knowledge as deprecated when it's no longer valid |
|
|
94
|
+
### What the security model guarantees
|
|
100
95
|
|
|
101
|
-
|
|
96
|
+
- **Quarantine by default** — AUTO observations (agent-submitted) are never injected until confirmed across 2+ independent sessions. A single prompt-injected `compile_submit` call cannot poison your knowledge base — it lands in quarantine and requires independent reinforcement before it's ever served.
|
|
97
|
+
- **Enforced rules are human-only** — The enforce mechanism (which blocks agent tool calls) can only be set via CLI (`agentcache add-rule --enforce`). No MCP tool can create policy an agent is subject to.
|
|
98
|
+
- **Scope gate** — Agent-submitted observations are always project-scoped. Promotion to global scope requires explicit human action (USER authority). An agent cannot write a global rule.
|
|
99
|
+
- **Quarantine ≠ absent** — Quarantined items are captured and visible in `agentcache review`. They just don't inject. The review command is how you clear or promote them.
|
|
102
100
|
|
|
103
|
-
|
|
104
|
-
agentcache status # Show knowledge stats for current project
|
|
105
|
-
agentcache compile-all # Batch-compile all unprocessed transcripts
|
|
106
|
-
agentcache setup # Re-register with IDEs (only if postinstall failed)
|
|
107
|
-
```
|
|
101
|
+
### What the security model does not guarantee
|
|
108
102
|
|
|
109
|
-
|
|
103
|
+
- `compile-all` processes raw transcripts that may contain injected content. Extraction prompt hardening raises the bar, but a sufficiently crafted transcript can still produce a quarantined (non-injecting) entry. Review your pending queue periodically.
|
|
104
|
+
- `locked` mode disables `compile_submit` entirely and requires human-triggered batch compilation. It reduces the attack surface significantly but `compile-all` against a poisoned transcript is still a vector.
|
|
110
105
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
agentcache compile-all
|
|
115
|
-
```
|
|
106
|
+
### Security modes
|
|
116
107
|
|
|
117
|
-
|
|
118
|
-
1. CLI tools with stored auth: `claude`, `codex`, `gemini`, `copilot`, `aider`, `goose`
|
|
119
|
-
2. Ollama running locally (`localhost:11434`)
|
|
120
|
-
3. `ANTHROPIC_API_KEY` environment variable
|
|
121
|
-
4. `OPENAI_API_KEY` environment variable
|
|
108
|
+
Configure in `~/.agentcache/config.json`:
|
|
122
109
|
|
|
123
|
-
|
|
110
|
+
```json
|
|
111
|
+
{ "security": "auto" }
|
|
112
|
+
```
|
|
124
113
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
114
|
+
| Mode | Behavior | For |
|
|
115
|
+
|------|----------|-----|
|
|
116
|
+
| `auto` (default) | Quarantine — AUTO items inject after 2+ session confirmations | Solo devs, indie shops |
|
|
117
|
+
| `review` | All new items land in quarantine. Nothing injects until `agentcache review` approves it | BFSI, healthcare, regulated environments |
|
|
118
|
+
| `locked` | `compile_submit` disabled. Compile-all only, human-triggered batch review | Maximum control |
|
|
129
119
|
|
|
130
|
-
|
|
120
|
+
## CLI commands
|
|
131
121
|
|
|
132
|
-
Internal commands (called by hooks automatically, never by users):
|
|
133
122
|
```bash
|
|
134
|
-
agentcache
|
|
135
|
-
agentcache
|
|
136
|
-
agentcache
|
|
137
|
-
agentcache
|
|
123
|
+
agentcache status # Knowledge stats for current project
|
|
124
|
+
agentcache doctor # Diagnose installation problems
|
|
125
|
+
agentcache review # List quarantined items, approve or reject
|
|
126
|
+
agentcache promote <id> # Promote a single item past quarantine
|
|
127
|
+
agentcache add-rule "never commit secrets" --enforce # Create enforced policy (human only)
|
|
128
|
+
agentcache add-rule "use tabs" --global # Global rule across all projects
|
|
129
|
+
agentcache compile-all # Batch-compile all unprocessed transcripts
|
|
130
|
+
agentcache setup # Re-register with IDEs (only if postinstall failed)
|
|
138
131
|
```
|
|
139
132
|
|
|
140
|
-
##
|
|
141
|
-
|
|
142
|
-
### Zero Config
|
|
143
|
-
|
|
144
|
-
`npm install -g agentcache` is the only step. It detects your IDEs, registers itself, and starts working. No dotfiles in your project. No init commands. No config to maintain.
|
|
133
|
+
## compile-all — batch compilation
|
|
145
134
|
|
|
146
|
-
|
|
135
|
+
Processes all pending transcripts without depending on active MCP sessions.
|
|
147
136
|
|
|
148
|
-
|
|
137
|
+
**LLM backend (first available wins):**
|
|
149
138
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
### Resilient to Abrupt Exits
|
|
155
|
-
|
|
156
|
-
Sessions can end without warning (crash, ctrl-c, network drop, MCP pipe death). AgentCache handles this through:
|
|
157
|
-
- **Incremental submission** — observations are saved as they happen, not batched at the end
|
|
158
|
-
- **Transcript recovery** — transcripts persist on disk across 5 IDEs (Claude Code, Continue, Codex, Roo Code, Goose) and are compiled by `compile-all`
|
|
159
|
-
- **Pipe-independent compilation** — `compile-all` runs as a standalone process, not through MCP stdio pipes that can break during long operations
|
|
160
|
-
- **Pending queue in SQLite** — concurrent access is safe, nothing lost to race conditions
|
|
161
|
-
|
|
162
|
-
### Anti-Bloat
|
|
163
|
-
|
|
164
|
-
AgentCache prevents knowledge from growing unbounded:
|
|
165
|
-
- **Confidence promotion** — observations need repeated confirmation before becoming high-confidence
|
|
166
|
-
- **Decay** — auto-compiled items not seen in 30 days get archived
|
|
167
|
-
- **Budget caps** — max 20 rules, 10 lessons, 10 decisions, 5 context items injected per session
|
|
168
|
-
- **Priority ranking** — USER authority first, then by confidence and recency
|
|
169
|
-
|
|
170
|
-
## Supported IDEs
|
|
171
|
-
|
|
172
|
-
| IDE | MCP | Auto-Approve | Transcript Recovery | Hooks |
|
|
173
|
-
|-----|-----|-------------|--------------------|----|
|
|
174
|
-
| Claude Code | Yes | Yes (automatic) | Full (JSONL) | Stop, SessionStart, PreToolUse |
|
|
175
|
-
| Cursor | Yes | Yes (automatic) | Incremental only | — |
|
|
176
|
-
| Roo Code | Yes | Yes (automatic) | Full (JSON via compile-all) | — |
|
|
177
|
-
| Windsurf | Yes | Yes (automatic) | Incremental only | — |
|
|
178
|
-
| Continue | Yes | Yes (automatic) | Full (JSON) | — |
|
|
179
|
-
| Codex | Yes | Yes (automatic) | Full (JSONL via compile-all) | — |
|
|
180
|
-
| Goose | — | — | Full (SQLite via compile-all) | — |
|
|
139
|
+
1. CLI tools with stored auth: `claude`, `codex`, `gemini`, `copilot`, `aider`, `goose`
|
|
140
|
+
2. Ollama at `localhost:11434`
|
|
141
|
+
3. `ANTHROPIC_API_KEY` or `OPENAI_API_KEY`
|
|
181
142
|
|
|
182
|
-
|
|
143
|
+
**Triggers automatically:**
|
|
183
144
|
|
|
184
|
-
|
|
145
|
+
- After `npm install -g agentcache` (clears initial backlog)
|
|
146
|
+
- When pending transcripts exceed 20 (background janitor)
|
|
147
|
+
- Lockfile prevents concurrent runs
|
|
185
148
|
|
|
186
|
-
|
|
149
|
+
## MCP tools
|
|
187
150
|
|
|
188
|
-
|
|
151
|
+
| Tool | Purpose |
|
|
152
|
+
|------|---------|
|
|
153
|
+
| `inject_context` | Load compiled knowledge at session start |
|
|
154
|
+
| `compile_submit` | Submit observations incrementally during session |
|
|
155
|
+
| `compile_cluster` | Resolve clustering when observations overlap existing knowledge |
|
|
156
|
+
| `compile_extract` | Process queued transcripts from previous sessions |
|
|
157
|
+
| `enforce` | Check tool calls against enforced policy rules |
|
|
158
|
+
| `save_observation` | Save a permanent observation (USER authority, never auto-deprecated) |
|
|
159
|
+
| `get_knowledge` | Query the knowledge database |
|
|
160
|
+
| `deprecate_knowledge` | Mark knowledge as deprecated |
|
|
189
161
|
|
|
190
|
-
|
|
162
|
+
## How knowledge compiles
|
|
191
163
|
|
|
192
164
|
```
|
|
193
|
-
|
|
194
|
-
|
|
165
|
+
Observations (raw)
|
|
166
|
+
│
|
|
167
|
+
▼
|
|
168
|
+
Extract → Normalize → Canonicalize → Cluster → Detect Contradictions → Compile
|
|
169
|
+
│
|
|
170
|
+
┌───────────────────────────────────────────┘
|
|
171
|
+
│
|
|
172
|
+
PENDING store
|
|
173
|
+
│
|
|
174
|
+
┌─────────┴──────────┐
|
|
175
|
+
│ │
|
|
176
|
+
AUTO items USER items
|
|
177
|
+
(quarantine gate) (inject immediately)
|
|
178
|
+
2+ sessions before
|
|
179
|
+
injection
|
|
195
180
|
```
|
|
196
181
|
|
|
197
|
-
**
|
|
198
|
-
|
|
199
|
-
**Project skill** (`<repo>/.agentcache/skills/`) — project-specific decisions, context, and rules. Git-trackable. Team members get it on clone. **This is team knowledge sharing without a sync server — just git.**
|
|
200
|
-
|
|
201
|
-
Skills auto-refresh on every compilation. Each file stays under 5,000 tokens (Agent Skills budget limit). High-confidence items appear first.
|
|
182
|
+
**Two compilation paths:**
|
|
202
183
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
name: project-knowledge
|
|
207
|
-
description: "Project-specific decisions, rules, context, and lessons — compiled automatically from coding sessions by AgentCache"
|
|
208
|
-
---
|
|
184
|
+
- **In-session** — agent processes extraction via MCP tools in your IDE
|
|
185
|
+
- **Batch** — `compile-all` runs independently, processes full backlog
|
|
209
186
|
|
|
210
|
-
|
|
187
|
+
**Two output formats:**
|
|
211
188
|
|
|
212
|
-
|
|
189
|
+
- **MCP injection** — structured context via `inject_context`
|
|
190
|
+
- **SKILL.md** — Agent Skills spec files auto-discovered by 38+ tools without MCP
|
|
213
191
|
|
|
214
|
-
|
|
215
|
-
- Never commit .env files [ENFORCED]
|
|
192
|
+
## Design principles
|
|
216
193
|
|
|
217
|
-
|
|
194
|
+
**Zero config** — `npm install -g agentcache` is the only step. No dotfiles, no init, no config to maintain.
|
|
218
195
|
|
|
219
|
-
|
|
196
|
+
**Universal** — MCP is the only interface. Any IDE, any LLM. No IDE-specific code paths.
|
|
220
197
|
|
|
221
|
-
-
|
|
222
|
-
- PostgreSQL for all persistent state, Redis for ephemeral cache only
|
|
198
|
+
**Developer-scoped** — One database per developer, not per project. Global knowledge (rules, lessons) benefits all your projects. Project knowledge stays scoped.
|
|
223
199
|
|
|
224
|
-
|
|
200
|
+
**Resilient to abrupt exits** — Incremental submission + transcript recovery + pipe-independent compilation means knowledge survives crashes, ctrl-c, and MCP disconnects.
|
|
225
201
|
|
|
226
|
-
|
|
202
|
+
**Anti-bloat** — Confidence promotion, 30-day decay on unused items, budget caps (20 rules / 10 lessons / 10 decisions / 5 context per session), priority ranking.
|
|
227
203
|
|
|
228
|
-
|
|
229
|
-
```
|
|
204
|
+
## Supported IDEs
|
|
230
205
|
|
|
231
|
-
|
|
206
|
+
| IDE | MCP | Auto-Approve | Transcript Recovery | Hooks |
|
|
207
|
+
|-----|-----|-------------|-------------------|-------|
|
|
208
|
+
| Claude Code | Yes | Yes | Full (JSONL) | Stop, SessionStart, PreToolUse |
|
|
209
|
+
| Cursor | Yes | Yes | Incremental only | — |
|
|
210
|
+
| Roo Code | Yes | Yes | Full (JSON via compile-all) | — |
|
|
211
|
+
| Windsurf | Yes | Yes | Incremental only | — |
|
|
212
|
+
| Continue | Yes | Yes | Full (JSON) | — |
|
|
213
|
+
| Codex | Yes | Yes | Full (JSONL via compile-all) | — |
|
|
214
|
+
| Goose | — | — | Full (SQLite via compile-all) | — |
|
|
215
|
+
| Aider | Coming soon | | | |
|
|
216
|
+
| GitHub Copilot | Coming soon | | | |
|
|
217
|
+
| Zed AI | Coming soon | | | |
|
|
232
218
|
|
|
233
|
-
|
|
219
|
+
## Data storage
|
|
234
220
|
|
|
235
221
|
```
|
|
236
222
|
~/.agentcache/
|
|
237
223
|
├── agentcache.db # Knowledge, observations, sessions, pending queue
|
|
224
|
+
├── config.json # Security mode and settings
|
|
238
225
|
├── compile-all.lock # Prevents concurrent compilation
|
|
239
226
|
└── skills/developer-knowledge/SKILL.md # Global skill (auto-generated)
|
|
240
227
|
```
|
|
241
228
|
|
|
242
229
|
No data leaves your machine. No network calls. No telemetry. No accounts.
|
|
243
230
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
```
|
|
247
|
-
Observations (raw)
|
|
248
|
-
│
|
|
249
|
-
▼
|
|
250
|
-
Extract → Normalize → Canonicalize → Cluster → Detect Contradictions → Compile
|
|
251
|
-
│ │
|
|
252
|
-
│ "Always use ESLint" │
|
|
253
|
-
│ "Always use ESLint" ──→ deduplicated, confidence promoted │
|
|
254
|
-
│ "Use Prettier not ESLint" ──→ contradiction detected │
|
|
255
|
-
│ ▼
|
|
256
|
-
Knowledge Items (compiled)
|
|
257
|
-
- status: active/deprecated/superseded
|
|
258
|
-
- confidence: low/medium/high
|
|
259
|
-
- authority: AUTO/USER
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
**Two compilation paths:**
|
|
263
|
-
- **In-session** — the agent in your IDE processes extraction prompts via MCP tools (no separate LLM calls needed)
|
|
264
|
-
- **Batch (`compile-all`)** — runs independently using any available LLM CLI or API, processes the full backlog without depending on active sessions
|
|
265
|
-
|
|
266
|
-
**Two output formats:**
|
|
267
|
-
- **MCP injection** — structured context served to agents at session start via `inject_context`
|
|
268
|
-
- **SKILL.md files** — Agent Skills spec-compliant files auto-discovered by 38+ tools without MCP
|
|
269
|
-
|
|
270
|
-
## Project Identity
|
|
231
|
+
### Project identity
|
|
271
232
|
|
|
272
|
-
Projects are identified by a hash of their full filesystem path
|
|
273
|
-
- `/work/api` and `/personal/api` are different projects
|
|
274
|
-
- Renaming a folder creates a new project identity
|
|
275
|
-
- Knowledge doesn't leak between same-named projects
|
|
233
|
+
Projects are identified by a hash of their full filesystem path. `/work/api` and `/personal/api` are different projects. Knowledge never leaks between same-named projects in different locations.
|
|
276
234
|
|
|
277
235
|
## Roadmap
|
|
278
236
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
| Claude Code | Supported |
|
|
284
|
-
| Cursor | Supported |
|
|
285
|
-
| Roo Code | Supported |
|
|
286
|
-
| Windsurf | Supported |
|
|
287
|
-
| Continue | Supported |
|
|
288
|
-
| Codex | Supported |
|
|
289
|
-
| Goose | Supported (transcript recovery via SQLite) |
|
|
290
|
-
| Aider | Coming soon |
|
|
291
|
-
| GitHub Copilot | Coming soon |
|
|
292
|
-
| Zed AI | Coming soon |
|
|
293
|
-
|
|
294
|
-
Any tool that supports MCP can use AgentCache today via `agentcache serve`. Native integrations for the above are planned to ensure zero-config setup.
|
|
295
|
-
|
|
296
|
-
### Native Plugins
|
|
297
|
-
|
|
298
|
-
Marketplace listings and deeper UI integrations for all supported IDEs — surfacing knowledge inline, showing compilation status, and providing one-click management of rules and decisions.
|
|
299
|
-
|
|
300
|
-
### Team Knowledge Sharing
|
|
301
|
-
|
|
302
|
-
Share compiled knowledge across your team. Rules and lessons that work for one developer benefit everyone.
|
|
303
|
-
|
|
304
|
-
### Cloud Sync
|
|
305
|
-
|
|
306
|
-
Sync your knowledge database across machines. Same developer, different computers, same knowledge.
|
|
307
|
-
|
|
308
|
-
### Analytics Dashboard
|
|
309
|
-
|
|
310
|
-
Visibility into what AgentCache is learning — compilation stats, knowledge growth, most-referenced rules, and session coverage.
|
|
237
|
+
- **Native plugins** — Marketplace listings and deeper UI integrations for all supported IDEs
|
|
238
|
+
- **Team knowledge sharing** — Share compiled knowledge across your team
|
|
239
|
+
- **Cloud sync** — Same developer, different machines, same knowledge
|
|
240
|
+
- **Analytics dashboard** — Compilation stats, knowledge growth, most-referenced rules
|
|
311
241
|
|
|
312
242
|
## Contributing
|
|
313
243
|
|
|
@@ -277,16 +277,17 @@ var SqliteKnowledgeRepository = class {
|
|
|
277
277
|
if (!row) return null;
|
|
278
278
|
return this.mapKnowledgeItem(row);
|
|
279
279
|
}
|
|
280
|
-
getKnowledgeForContext(project) {
|
|
280
|
+
getKnowledgeForContext(project, opts) {
|
|
281
281
|
const decayThreshold = Date.now() - 30 * 24 * 60 * 60 * 1e3;
|
|
282
282
|
this.db.prepare(
|
|
283
283
|
`UPDATE knowledge_items SET status = 'archived', updated_at = ?
|
|
284
284
|
WHERE status = 'active' AND authority = 'AUTO' AND last_seen_at < ?`
|
|
285
285
|
).run(Date.now(), decayThreshold);
|
|
286
|
+
const authorityFilter = opts?.userOnly ? `AND authority = 'USER'` : `AND (authority = 'USER' OR observation_count >= 2)`;
|
|
286
287
|
const rows = this.db.prepare(
|
|
287
288
|
`SELECT * FROM knowledge_items WHERE status = 'active'
|
|
288
289
|
AND (scope = 'global' OR project = ?)
|
|
289
|
-
|
|
290
|
+
${authorityFilter}
|
|
290
291
|
ORDER BY
|
|
291
292
|
CASE authority WHEN 'USER' THEN 0 ELSE 1 END,
|
|
292
293
|
CASE confidence WHEN 'high' THEN 3 WHEN 'medium' THEN 2 ELSE 1 END DESC,
|
|
@@ -382,6 +383,11 @@ var SqliteKnowledgeRepository = class {
|
|
|
382
383
|
const row = this.db.prepare("SELECT COUNT(*) as count FROM pending_transcripts").get();
|
|
383
384
|
return row.count;
|
|
384
385
|
}
|
|
386
|
+
grandfatherExistingItems() {
|
|
387
|
+
this.db.prepare(
|
|
388
|
+
`UPDATE knowledge_items SET observation_count = 2 WHERE authority = 'AUTO' AND observation_count < 2 AND status = 'active'`
|
|
389
|
+
).run();
|
|
390
|
+
}
|
|
385
391
|
getQuarantinedItems(project) {
|
|
386
392
|
const sql = project ? `SELECT * FROM knowledge_items WHERE status = 'active' AND authority = 'AUTO' AND observation_count < 2 AND (scope = 'global' OR project = ?) ORDER BY created_at DESC` : `SELECT * FROM knowledge_items WHERE status = 'active' AND authority = 'AUTO' AND observation_count < 2 ORDER BY created_at DESC`;
|
|
387
393
|
const rows = project ? this.db.prepare(sql).all(project) : this.db.prepare(sql).all();
|
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Command } from "commander";
|
|
|
5
5
|
var program = new Command();
|
|
6
6
|
program.name("agentcache").description("Engineering Knowledge Compiler \u2014 universal, zero-config").version("0.3.1");
|
|
7
7
|
program.command("setup").description("Detect IDEs and register AgentCache (runs automatically on install)").action(async () => {
|
|
8
|
-
const { runSetup } = await import("./setup-
|
|
8
|
+
const { runSetup } = await import("./setup-45BVUDXN.js");
|
|
9
9
|
await runSetup();
|
|
10
10
|
});
|
|
11
11
|
program.command("serve").description("Start AgentCache MCP server (spawned by IDEs automatically)").action(async () => {
|
|
@@ -14,7 +14,7 @@ program.command("serve").description("Start AgentCache MCP server (spawned by ID
|
|
|
14
14
|
});
|
|
15
15
|
program.command("compile-session").description("Stop hook: queue transcript for compilation").action(async () => {
|
|
16
16
|
try {
|
|
17
|
-
const { handleStop } = await import("./stop-
|
|
17
|
+
const { handleStop } = await import("./stop-TPCRE7RE.js");
|
|
18
18
|
let payload;
|
|
19
19
|
try {
|
|
20
20
|
let data = "";
|
|
@@ -34,7 +34,7 @@ program.command("compile-session").description("Stop hook: queue transcript for
|
|
|
34
34
|
});
|
|
35
35
|
program.command("discover").description("SessionStart hook: discover uncompiled transcripts").action(async () => {
|
|
36
36
|
try {
|
|
37
|
-
const { handleSessionStart } = await import("./session-start-
|
|
37
|
+
const { handleSessionStart } = await import("./session-start-EIHYCS3J.js");
|
|
38
38
|
await handleSessionStart();
|
|
39
39
|
} catch (err) {
|
|
40
40
|
process.stderr.write(`agentcache discover: ${err.message}
|
|
@@ -47,7 +47,7 @@ program.command("enforce").description("PreToolUse hook: policy enforcement").ac
|
|
|
47
47
|
data += chunk;
|
|
48
48
|
}
|
|
49
49
|
try {
|
|
50
|
-
const { handlePreToolUse } = await import("./pre-tool-use-
|
|
50
|
+
const { handlePreToolUse } = await import("./pre-tool-use-7F7NTHCS.js");
|
|
51
51
|
const input = JSON.parse(data);
|
|
52
52
|
const result = handlePreToolUse(input);
|
|
53
53
|
process.stdout.write(JSON.stringify(result));
|
|
@@ -63,7 +63,7 @@ program.command("review").description("Review quarantined observations \u2014 ap
|
|
|
63
63
|
console.log("AgentCache not initialized. Run: agentcache setup");
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
|
-
const { SqliteKnowledgeRepository } = await import("./sqlite-
|
|
66
|
+
const { SqliteKnowledgeRepository } = await import("./sqlite-NM2BVHUY.js");
|
|
67
67
|
const repo = new SqliteKnowledgeRepository(getDbPath());
|
|
68
68
|
const project = getProjectId(findProjectRoot());
|
|
69
69
|
const items = repo.getQuarantinedItems(project);
|
|
@@ -108,7 +108,7 @@ program.command("promote <id>").description("Promote a specific quarantined item
|
|
|
108
108
|
console.log("AgentCache not initialized. Run: agentcache setup");
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
|
-
const { SqliteKnowledgeRepository } = await import("./sqlite-
|
|
111
|
+
const { SqliteKnowledgeRepository } = await import("./sqlite-NM2BVHUY.js");
|
|
112
112
|
const repo = new SqliteKnowledgeRepository(getDbPath());
|
|
113
113
|
const item = repo.getKnowledgeItem(id);
|
|
114
114
|
if (!item) {
|
|
@@ -127,7 +127,7 @@ program.command("add-rule <content>").description("Add an enforced policy rule (
|
|
|
127
127
|
console.log("AgentCache not initialized. Run: agentcache setup");
|
|
128
128
|
return;
|
|
129
129
|
}
|
|
130
|
-
const { SqliteKnowledgeRepository } = await import("./sqlite-
|
|
130
|
+
const { SqliteKnowledgeRepository } = await import("./sqlite-NM2BVHUY.js");
|
|
131
131
|
const { computeCanonicalHash } = await import("./3-canonicalizer-HIN2F7SZ.js");
|
|
132
132
|
const repo = new SqliteKnowledgeRepository(getDbPath());
|
|
133
133
|
const project = getProjectId(findProjectRoot());
|
|
@@ -185,7 +185,7 @@ program.command("doctor").description("Diagnose AgentCache installation and repo
|
|
|
185
185
|
const dbPath = getDbPath();
|
|
186
186
|
if (existsSync(dbPath)) {
|
|
187
187
|
try {
|
|
188
|
-
const { SqliteKnowledgeRepository } = await import("./sqlite-
|
|
188
|
+
const { SqliteKnowledgeRepository } = await import("./sqlite-NM2BVHUY.js");
|
|
189
189
|
const repo = new SqliteKnowledgeRepository(dbPath);
|
|
190
190
|
repo.close();
|
|
191
191
|
pass(`Database accessible: ${dbPath}`);
|
|
@@ -267,7 +267,7 @@ ${ok} passed, ${warn} warnings, ${fail} errors`);
|
|
|
267
267
|
if (fail > 0) process.exit(1);
|
|
268
268
|
});
|
|
269
269
|
program.command("compile-all").description("Batch-compile all unprocessed transcripts using an available LLM CLI").action(async () => {
|
|
270
|
-
const { runCompileAll } = await import("./compile-all-
|
|
270
|
+
const { runCompileAll } = await import("./compile-all-7ESDEBFG.js");
|
|
271
271
|
await runCompileAll();
|
|
272
272
|
});
|
|
273
273
|
program.command("status").description("Show AgentCache knowledge stats").action(async () => {
|
|
@@ -276,7 +276,7 @@ program.command("status").description("Show AgentCache knowledge stats").action(
|
|
|
276
276
|
console.log("AgentCache not initialized. Run: agentcache setup");
|
|
277
277
|
return;
|
|
278
278
|
}
|
|
279
|
-
const { SqliteKnowledgeRepository } = await import("./sqlite-
|
|
279
|
+
const { SqliteKnowledgeRepository } = await import("./sqlite-NM2BVHUY.js");
|
|
280
280
|
const repo = new SqliteKnowledgeRepository(getDbPath());
|
|
281
281
|
const projectRoot = findProjectRoot();
|
|
282
282
|
const project = getProjectId(projectRoot);
|
package/dist/mcp.js
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
} from "./chunk-T4COG3XD.js";
|
|
25
25
|
import {
|
|
26
26
|
SqliteKnowledgeRepository
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-PSASDZQE.js";
|
|
28
28
|
import "./chunk-KFQGP6VL.js";
|
|
29
29
|
|
|
30
30
|
// src/mcp.ts
|
|
@@ -92,9 +92,34 @@ function checkForUpdates() {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
// src/mcp.ts
|
|
95
|
-
import { existsSync as
|
|
95
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
96
|
+
|
|
97
|
+
// src/utils/config.ts
|
|
98
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
99
|
+
import { join as join2 } from "path";
|
|
100
|
+
var DEFAULT_CONFIG = {
|
|
101
|
+
security: "auto"
|
|
102
|
+
};
|
|
103
|
+
function getConfigPath() {
|
|
104
|
+
return join2(getDataDir(), "config.json");
|
|
105
|
+
}
|
|
106
|
+
function getConfig() {
|
|
107
|
+
const path = getConfigPath();
|
|
108
|
+
if (!existsSync2(path)) return { ...DEFAULT_CONFIG };
|
|
109
|
+
try {
|
|
110
|
+
const raw = JSON.parse(readFileSync2(path, "utf-8"));
|
|
111
|
+
return { ...DEFAULT_CONFIG, ...raw };
|
|
112
|
+
} catch {
|
|
113
|
+
return { ...DEFAULT_CONFIG };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function saveConfig(config) {
|
|
117
|
+
writeFileSync2(getConfigPath(), JSON.stringify(config, null, 2), "utf-8");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/mcp.ts
|
|
96
121
|
import { randomUUID } from "crypto";
|
|
97
|
-
var PKG_VERSION = JSON.parse(
|
|
122
|
+
var PKG_VERSION = JSON.parse(readFileSync3(new URL("../package.json", import.meta.url), "utf-8")).version;
|
|
98
123
|
function defaultScope(type) {
|
|
99
124
|
return type === "rule" || type === "lesson" ? "global" : "project";
|
|
100
125
|
}
|
|
@@ -117,6 +142,17 @@ function getResolvedProjectRoot() {
|
|
|
117
142
|
function getResolvedProjectId() {
|
|
118
143
|
return getProjectId(getResolvedProjectRoot());
|
|
119
144
|
}
|
|
145
|
+
function migrateToV04() {
|
|
146
|
+
const config = getConfig();
|
|
147
|
+
if (config.migrated_v04) return;
|
|
148
|
+
try {
|
|
149
|
+
const repo = new SqliteKnowledgeRepository(getDbPath());
|
|
150
|
+
repo.grandfatherExistingItems();
|
|
151
|
+
repo.close();
|
|
152
|
+
saveConfig({ ...config, migrated_v04: true });
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
}
|
|
120
156
|
async function startMcpServer() {
|
|
121
157
|
const server = new Server(
|
|
122
158
|
{ name: "agentcache", version: PKG_VERSION },
|
|
@@ -128,6 +164,7 @@ async function startMcpServer() {
|
|
|
128
164
|
server.oninitialized = async () => {
|
|
129
165
|
await resolveRoots(server);
|
|
130
166
|
checkForUpdates();
|
|
167
|
+
migrateToV04();
|
|
131
168
|
};
|
|
132
169
|
server.setNotificationHandler(RootsListChangedNotificationSchema, async () => {
|
|
133
170
|
await resolveRoots(server);
|
|
@@ -273,7 +310,8 @@ async function startMcpServer() {
|
|
|
273
310
|
case "inject_context": {
|
|
274
311
|
const args = request.params.arguments || {};
|
|
275
312
|
const project = args.project || detectedProject;
|
|
276
|
-
const
|
|
313
|
+
const securityMode = getConfig().security;
|
|
314
|
+
const items = repo.getKnowledgeForContext(project, { userOnly: securityMode === "review" });
|
|
277
315
|
const rules = items.filter((i) => i.type === "rule").slice(0, 20);
|
|
278
316
|
const lessons = items.filter((i) => i.type === "lesson").slice(0, 10);
|
|
279
317
|
const decisions = items.filter((i) => i.type === "decision").slice(0, 10);
|
|
@@ -322,6 +360,10 @@ ${quarantined.length} observation(s) pending review \u2014 run \`agentcache revi
|
|
|
322
360
|
return { content: [{ type: "text", text: output.trim() }] };
|
|
323
361
|
}
|
|
324
362
|
case "compile_submit": {
|
|
363
|
+
const securityMode = getConfig().security;
|
|
364
|
+
if (securityMode === "locked") {
|
|
365
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: "compile_submit disabled \u2014 security mode is 'locked'. Use compile-all for batch processing." }) }], isError: true };
|
|
366
|
+
}
|
|
325
367
|
const args = request.params.arguments;
|
|
326
368
|
const project = args.project || detectedProject;
|
|
327
369
|
const sessionId = `sess_${randomUUID().slice(0, 8)}`;
|
|
@@ -348,7 +390,7 @@ ${quarantined.length} observation(s) pending review \u2014 run \`agentcache revi
|
|
|
348
390
|
if (!entry) {
|
|
349
391
|
return { content: [{ type: "text", text: JSON.stringify({ message: "No pending sessions to compile." }) }] };
|
|
350
392
|
}
|
|
351
|
-
if (!
|
|
393
|
+
if (!existsSync3(entry.transcriptPath)) {
|
|
352
394
|
return { content: [{ type: "text", text: JSON.stringify({ message: `Transcript not found: ${entry.transcriptPath}, skipped.` }) }] };
|
|
353
395
|
}
|
|
354
396
|
const events = parseTranscript(entry.transcriptPath);
|
package/dist/postinstall.js
CHANGED