@kawacode/mcp 5.2.2 → 6.1.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/CLAUDE.md.example +11 -3
- package/README.md +54 -198
- package/build/index.js +10 -1
- package/build/index.js.map +1 -1
- package/build/kawacode-on-pre-edit.d.ts +27 -0
- package/build/kawacode-on-pre-edit.js +201 -0
- package/build/kawacode-on-pre-edit.js.map +1 -0
- package/build/kawacode-on-stop.d.ts +33 -0
- package/build/kawacode-on-stop.js +88 -0
- package/build/kawacode-on-stop.js.map +1 -0
- package/build/pre-edit/path-resolve.d.ts +32 -0
- package/build/pre-edit/path-resolve.js +52 -0
- package/build/pre-edit/path-resolve.js.map +1 -0
- package/build/pre-edit/path-resolve.test.d.ts +1 -0
- package/build/pre-edit/path-resolve.test.js +105 -0
- package/build/pre-edit/path-resolve.test.js.map +1 -0
- package/build/prompts/intent-first-workflow.js +2 -2
- package/build/services/muninn-ipc.js +11 -3
- package/build/services/muninn-ipc.js.map +1 -1
- package/build/tools/_fork-fields.d.ts +84 -0
- package/build/tools/_fork-fields.js +65 -0
- package/build/tools/_fork-fields.js.map +1 -0
- package/build/tools/activate-intent.d.ts +66 -0
- package/build/tools/activate-intent.js +59 -3
- package/build/tools/activate-intent.js.map +1 -1
- package/build/tools/check-active-intent.d.ts +64 -0
- package/build/tools/check-active-intent.js +16 -2
- package/build/tools/check-active-intent.js.map +1 -1
- package/build/tools/complete-intent.d.ts +115 -4
- package/build/tools/complete-intent.js +138 -12
- package/build/tools/complete-intent.js.map +1 -1
- package/build/tools/create-intent.d.ts +73 -1
- package/build/tools/create-intent.js +105 -7
- package/build/tools/create-intent.js.map +1 -1
- package/build/tools/detect-intent-conflicts.d.ts +52 -0
- package/build/tools/detect-intent-conflicts.js +14 -10
- package/build/tools/detect-intent-conflicts.js.map +1 -1
- package/build/tools/edit-session-decision.d.ts +76 -12
- package/build/tools/edit-session-decision.js +11 -2
- package/build/tools/edit-session-decision.js.map +1 -1
- package/build/tools/evolve-decisions.d.ts +52 -0
- package/build/tools/evolve-decisions.js +14 -15
- package/build/tools/evolve-decisions.js.map +1 -1
- package/build/tools/get-intent-changes.d.ts +52 -0
- package/build/tools/get-intent-changes.js +4 -1
- package/build/tools/get-intent-changes.js.map +1 -1
- package/build/tools/get-intents-for-file.d.ts +52 -0
- package/build/tools/get-intents-for-file.js +4 -1
- package/build/tools/get-intents-for-file.js.map +1 -1
- package/build/tools/get-intents-for-lines.d.ts +52 -0
- package/build/tools/get-intents-for-lines.js +4 -1
- package/build/tools/get-intents-for-lines.js.map +1 -1
- package/build/tools/get-project-decisions.d.ts +52 -0
- package/build/tools/get-project-decisions.js +4 -1
- package/build/tools/get-project-decisions.js.map +1 -1
- package/build/tools/get-relevant-context.d.ts +54 -0
- package/build/tools/get-relevant-context.js +19 -24
- package/build/tools/get-relevant-context.js.map +1 -1
- package/build/tools/get-session-decisions.d.ts +53 -0
- package/build/tools/get-session-decisions.js +6 -2
- package/build/tools/get-session-decisions.js.map +1 -1
- package/build/tools/index.d.ts +628 -18
- package/build/tools/index.js +12 -3
- package/build/tools/index.js.map +1 -1
- package/build/tools/infer-history.d.ts +6 -0
- package/build/tools/infer-history.js +28 -15
- package/build/tools/infer-history.js.map +1 -1
- package/build/tools/list-team-intents.d.ts +58 -6
- package/build/tools/list-team-intents.js +5 -2
- package/build/tools/list-team-intents.js.map +1 -1
- package/build/tools/log-work.d.ts +52 -0
- package/build/tools/log-work.js +4 -1
- package/build/tools/log-work.js.map +1 -1
- package/build/tools/pre-edit-acknowledge.d.ts +92 -0
- package/build/tools/pre-edit-acknowledge.js +48 -0
- package/build/tools/pre-edit-acknowledge.js.map +1 -0
- package/build/tools/pre-edit-decision-check.d.ts +141 -0
- package/build/tools/pre-edit-decision-check.js +77 -0
- package/build/tools/pre-edit-decision-check.js.map +1 -0
- package/build/tools/record-decision.d.ts +94 -12
- package/build/tools/record-decision.js +18 -1
- package/build/tools/record-decision.js.map +1 -1
- package/build/tools/update-intent.d.ts +60 -8
- package/build/tools/update-intent.js +6 -1
- package/build/tools/update-intent.js.map +1 -1
- package/package.json +6 -3
package/CLAUDE.md.example
CHANGED
|
@@ -42,8 +42,16 @@ For exploration turns, still call `get_relevant_context` to enrich your answer
|
|
|
42
42
|
`create_and_activate_intent` auto-detects conflicts. When the tool returns `action: "conflict"`:
|
|
43
43
|
|
|
44
44
|
1. Present each conflict to the user — severity, the conflicting intent's title/author, nature of the overlap.
|
|
45
|
-
2.
|
|
46
|
-
|
|
45
|
+
2. **Classify the conflict**:
|
|
46
|
+
- **Supersession** — the new work *replaces* or *retargets* the conflicting intent (same problem area, different approach; the old intent's assumptions no longer hold).
|
|
47
|
+
- **Independent overlap** — the conflict is structural (same files / domain) but the new work is unrelated to the old one's purpose.
|
|
48
|
+
3. Ask the user for the disposition. **For supersession**, prefer this flow:
|
|
49
|
+
- Create the new intent with `force: true`.
|
|
50
|
+
- Then `complete_intent(intentId=<old>, status="superseded", supersededBy=<new>)`. This requires the old intent to be active, so: `activate_intent(<old>, force: true)` → `complete_intent(... status="superseded" ...)` → `activate_intent(<new>)`.
|
|
51
|
+
- The lineage is durably recorded and queryable from either side.
|
|
52
|
+
4. **For independent overlap**, just retry `create_and_activate_intent` with `force: true`. Bypassed conflict IDs are recorded for audit, but no formal relationship is stored — the two intents remain unrelated in lineage walks.
|
|
53
|
+
|
|
54
|
+
`force: true` only bypasses the conflict-detection block; it does NOT record any relationship. Always reach for supersession first when the new work genuinely replaces the old.
|
|
47
55
|
|
|
48
56
|
---
|
|
49
57
|
|
|
@@ -90,7 +98,7 @@ Trivial standalone changes (typos, formatting) can be committed without an inten
|
|
|
90
98
|
|
|
91
99
|
## Code blocks are auto-captured on commit
|
|
92
100
|
|
|
93
|
-
When `complete_intent` runs with a `commitSha`, the
|
|
101
|
+
When `complete_intent` runs with a `commitSha`, the modified code blocks for that commit are captured and attached to the intent in the same call that updates the intent status. **There is no manual "assign blocks" step.**
|
|
94
102
|
|
|
95
103
|
Implication: an intent completed without a `commitSha` will have an empty `blocks` array. For `abandoned` intents that's fine. For `committed` / `pushed` / `done`, **always pass the commit SHA** so auto-capture runs.
|
|
96
104
|
|
package/README.md
CHANGED
|
@@ -1,28 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Kawa Code MCP
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Team-aware memory for AI coding assistants. Track intent, record decisions, and see when a teammate is editing the same code — in real time, before commit.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`@kawacode/mcp` is the official [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for [Kawa Code](https://kawacode.ai). It lets Claude Code, Cursor, and any MCP-compatible AI assistant:
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
It enables:
|
|
12
|
-
|
|
13
|
-
• Persistent AI reasoning context
|
|
14
|
-
• Intent tracking during development workflows
|
|
15
|
-
• Alignment between human and AI decisions over time
|
|
16
|
-
|
|
17
|
-
This repository contains the reference implementation of the
|
|
18
|
-
Kawa MCP server used by Kawa Code tools.
|
|
19
|
-
|
|
20
|
-
This MCP server enables AI coding assistants to understand what you're working on and maintain context across sessions. It connects to the Kawa Code desktop application to provide:
|
|
21
|
-
|
|
22
|
-
- **Intent tracking**: Create and manage development intents with decision history
|
|
23
|
-
- **Team collaboration**: See what teammates are working on, detect conflicts
|
|
24
|
-
- **Decision recording**: Track architectural decisions and trade-offs with constraint validation
|
|
25
|
-
- **Code block assignment**: Associate code changes with intents for better commit history
|
|
7
|
+
- **Remember what you're working on** across sessions, branches, and machines — no more re-explaining the architecture every morning.
|
|
8
|
+
- **Surface team conflicts before they happen** — know when a teammate is editing the same file or function in their working copy *right now*, before either of you commits.
|
|
9
|
+
- **Capture architectural decisions with their reasoning** — future you (and future AI sessions) inherit the team's accumulated context instead of relitigating choices.
|
|
10
|
+
- **Link commits to intent automatically** — every commit gets the *why* attached, not just the diff.
|
|
26
11
|
|
|
27
12
|
## Prerequisites
|
|
28
13
|
|
|
@@ -38,34 +23,34 @@ This MCP server enables AI coding assistants to understand what you're working o
|
|
|
38
23
|
|
|
39
24
|
## Installation
|
|
40
25
|
|
|
41
|
-
Add the MCP
|
|
26
|
+
Add the MCP in your AI configuration, for example on Claude Code:
|
|
42
27
|
|
|
43
|
-
|
|
44
|
-
claude mcp add kawa-intents --scope user -- npx -y @kawacode/mcp
|
|
45
|
-
```
|
|
28
|
+
`claude mcp add -s user kawa-intents -- npx -y @kawacode/mcp`
|
|
46
29
|
|
|
47
|
-
|
|
30
|
+
For Cursor AI, install the MCP with `npm install -g @kawacode/mcp` and add it to `~/.cursor/mcp.json`.
|
|
48
31
|
|
|
49
32
|
```json
|
|
50
33
|
{
|
|
51
34
|
"mcpServers": {
|
|
52
35
|
"kawa-intents": {
|
|
53
|
-
"
|
|
54
|
-
"command": "npx",
|
|
55
|
-
"args": ["-y", "@kawacode/mcp"]
|
|
36
|
+
"command": "kawacode-mcp"
|
|
56
37
|
}
|
|
57
38
|
}
|
|
58
39
|
}
|
|
59
40
|
```
|
|
60
41
|
|
|
61
|
-
|
|
42
|
+
Note that the MCP will not be automatically updated to future versions in this scenario.
|
|
43
|
+
To upgrade to a newer release, run `npm update -g @kawacode/mcp`.
|
|
62
44
|
|
|
63
|
-
|
|
45
|
+
## Manual Installation
|
|
46
|
+
|
|
47
|
+
For the project you want Kawa Code to run on, create a `.mcp.json` file in your project root (recommended for teams — commit it to git):
|
|
64
48
|
|
|
65
49
|
```json
|
|
66
50
|
{
|
|
67
51
|
"mcpServers": {
|
|
68
52
|
"kawa-intents": {
|
|
53
|
+
"type": "stdio",
|
|
69
54
|
"command": "npx",
|
|
70
55
|
"args": ["-y", "@kawacode/mcp"]
|
|
71
56
|
}
|
|
@@ -73,178 +58,58 @@ Add to your Cursor MCP configuration (`~/.cursor/mcp.json`):
|
|
|
73
58
|
}
|
|
74
59
|
```
|
|
75
60
|
|
|
76
|
-
## Quick Start
|
|
77
|
-
|
|
78
|
-
1. **Start Kawa Code**: Launch the Kawa Code desktop app and log in
|
|
79
|
-
2. **Install MCP**: Run `claude mcp add kawa-intents --scope user -- npx -y @kawacode/mcp`
|
|
80
|
-
3. **Restart AI**: Restart Claude Code or Cursor to load the MCP server
|
|
81
|
-
4. **Test connection**: The server will try to connect to Kawa Code on startup
|
|
82
|
-
5. **Start coding**: You'll start seeing `check_active_intent` at the start of your work with Claude Code
|
|
83
|
-
|
|
84
|
-
## Setting Up CLAUDE.md
|
|
85
|
-
|
|
86
|
-
#### Quick prompt to tell Claude Code to set up everything:
|
|
87
|
-
|
|
88
|
-
```
|
|
89
|
-
Read the CLAUDE.md.example file from the @kawacode/mcp package and create a CLAUDE.md in this project's root. Fill in the repoOrigin and repoPath with the actual values from this repository's git config. Fill in the Project Overview with a brief description of this project.
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
After this, you can start working using your usual workflow. Kawa Code will automatically start improving your LLM's code generation quality.
|
|
93
|
-
|
|
94
|
-
To benefit from Kawa Code's intent-driven development immediately, tell Claude Code to infer code decisions from your git history:
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
Please run infer_history with max 3000 commits.
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Tier 5 (the default) extracts the most context. Tiers are cumulative — each includes all data from lower tiers. Tiers 2 and 4 add PR/issue context from GitHub/GitLab and require the `gh` or `glab` CLI; they're automatically skipped if unavailable.
|
|
101
|
-
|
|
102
|
-
This can take a while, depending on how many commits you asked it to analyze. You'll see a progress bar in Kawa Code application.
|
|
103
|
-
Once this is done, you can open the project in Kawa Code (or you can use one of Kawa Code extensions for Visual Studio Code, emacs, or vim) to see the intents at every step in the code evolution.
|
|
104
|
-
Kawa Code will now select the relevant intents and micro-decisions made to speed up code generation, issue troubleshooting, bug fixing etc.
|
|
105
|
-
This relevant context will also help generating a more correct solution to your prompt request.
|
|
106
|
-
|
|
107
61
|
## Usage
|
|
108
62
|
|
|
109
|
-
The MCP server works together with Kawa Code, AI code generators such as Cursor
|
|
110
|
-
and the Kawa Code extensions.
|
|
111
|
-
|
|
112
|
-
## Key Features
|
|
113
|
-
|
|
114
|
-
- **Context Persistence**: Never lose track of what you were working on across AI sessions
|
|
115
|
-
- **Smart Context Retrieval**: Relevance-based context loading - only fetch what's needed for the current task
|
|
116
|
-
- **Zero-Knowledge Encryption**: Code blocks encrypted client-side before cloud sync, API cannot decrypt
|
|
117
|
-
- **Team Conflict Detection**: Know when teammates are working on the same files/lines
|
|
118
|
-
- **Decision Tracking**: Record architectural decisions with constraint validation and conflict detection
|
|
119
|
-
- **Commit Integration**: Link all code changes to intent context for better git history
|
|
120
|
-
- **Cross-Platform**: Works with Claude Code and Cursor AI via MCP protocol
|
|
121
|
-
|
|
122
|
-
## Available Tools
|
|
123
|
-
|
|
124
|
-
### Context & Discovery
|
|
63
|
+
The MCP server works together with the Kawa Code application, Kawa Code IDE extensions, and AI code generators such as Cursor AI and Claude Code.
|
|
125
64
|
|
|
126
|
-
|
|
127
|
-
|------------------------|-----------------------------------------|
|
|
128
|
-
| `get_relevant_context` | Get context relevant to a specific task |
|
|
65
|
+
## Pre-edit decision check (Claude Code hook)
|
|
129
66
|
|
|
130
|
-
|
|
67
|
+
Optional. When the agent is about to edit code that has prior recorded reasoning attached (an overlapping intent's blocks, or a constraint with the file in `relatedFiles`), the hook surfaces it before the Edit fires. Recommendation maps to action: silent (proceed), advisory context injected (review), or blocked with stderr message (`investigate-upstream`).
|
|
131
68
|
|
|
132
|
-
|
|
133
|
-
|------------------------------|------------------------------------------------------------|
|
|
134
|
-
| `check_active_intent` | Check if there's an active intent before starting new work |
|
|
135
|
-
| `create_and_activate_intent` | Create and activate a new intent for a development task |
|
|
136
|
-
| `get_intents_for_file` | Get intents (team and self) affecting a specific file |
|
|
137
|
-
| `get_intents_for_lines` | Get intents affecting specific line ranges in a file |
|
|
138
|
-
| `assign_blocks_to_intent` | Assign modified line ranges to the active intent |
|
|
139
|
-
| `get_intent_changes` | Get uncommitted changes for the active intent |
|
|
140
|
-
| `complete_intent` | Complete an intent (committed/done/abandoned) |
|
|
141
|
-
| `list_team_intents` | List what teammates are currently working on |
|
|
69
|
+
Wire it as a Claude Code `PreToolUse` hook in your `~/.claude/settings.json` or project `.claude/settings.json`:
|
|
142
70
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|--------------------|------------------------------------------------------------------------|
|
|
157
|
-
| `infer_history` | Analyze git commit history to extract development stories and decisions |
|
|
158
|
-
| `evolve_decisions` | Build a decision evolution graph from previously extracted stories |
|
|
159
|
-
|
|
160
|
-
### Lightweight Logging
|
|
161
|
-
|
|
162
|
-
| Tool | Description |
|
|
163
|
-
|------------|------------------------------------------------------------------------------------------------|
|
|
164
|
-
| `log_work` | Log completed work without the full intent lifecycle — use for quick fixes and trivial changes |
|
|
165
|
-
|
|
166
|
-
## MCP Capabilities
|
|
167
|
-
|
|
168
|
-
### Prompts
|
|
169
|
-
|
|
170
|
-
The server exposes prompts that can be loaded into your AI coding session:
|
|
171
|
-
|
|
172
|
-
- **`implementation_workflow`**: Standard workflow for implementing code changes with intent tracking. Provides step-by-step guidance on checking for active intents, creating new intents, checking for conflicts, and assigning blocks.
|
|
173
|
-
|
|
174
|
-
### Resources
|
|
175
|
-
|
|
176
|
-
The server exposes resources that can be monitored:
|
|
177
|
-
|
|
178
|
-
- **`kawa://intent/active`**: Real-time view of the currently active intent for the connected repository (JSON format)
|
|
179
|
-
|
|
180
|
-
## History Inference
|
|
181
|
-
|
|
182
|
-
Two MCP tools analyze git commit history to extract structured development knowledge — useful for bootstrapping a repository with historical context.
|
|
183
|
-
|
|
184
|
-
### `infer_history`
|
|
185
|
-
|
|
186
|
-
Runs the full pipeline automatically: **infer → evolve → persist**.
|
|
187
|
-
|
|
188
|
-
1. **Pass 1**: Groups commits into coherent development stories with value hints (high/low/none)
|
|
189
|
-
2. **Pass 2**: Deep analysis of high/low-value stories to extract architectural decisions and lessons learned
|
|
190
|
-
3. **Evolution**: Curates decisions by finding relationships (supersedes, reinforces, contradicts, specializes)
|
|
191
|
-
4. **Persist**: Stores curated stories as intents with decisions and lessons (auto-syncs to cloud)
|
|
192
|
-
|
|
193
|
-
The pipeline runs asynchronously inside Kawa Code. Progress is shown in the Kawa Code desktop app via a progress bar. The pipeline supports checkpointing — if interrupted, re-running resumes from where it left off.
|
|
194
|
-
|
|
195
|
-
**Usage in Claude Code:**
|
|
196
|
-
|
|
197
|
-
```
|
|
198
|
-
Use the infer_history tool with estimateOnly: true to preview the cost first,
|
|
199
|
-
then run it with estimateOnly: false.
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"hooks": {
|
|
74
|
+
"PreToolUse": [
|
|
75
|
+
{
|
|
76
|
+
"matcher": "Edit|Write",
|
|
77
|
+
"hooks": [
|
|
78
|
+
{ "type": "command", "command": "npx -y @kawacode/mcp kawacode-pre-edit-decision-check" }
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
200
84
|
```
|
|
201
85
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
| Parameter | Type | Default | Description |
|
|
205
|
-
|------------------------|---------|----------------------------|------------------------------------------------------------------------|
|
|
206
|
-
| `repoPath` | string | *(required)* | Local path to the repository root |
|
|
207
|
-
| `apiKey` | string | *(required)* | Your Anthropic API key |
|
|
208
|
-
| `commits` | number | 50 | Number of recent commits to analyze |
|
|
209
|
-
| `tier` | number | 4 | Data enrichment tier (1-5, see below) |
|
|
210
|
-
| `model` | string | claude-sonnet-4-20250514 | Anthropic model to use |
|
|
211
|
-
| `maxStories` | number | 0 | Limit stories to analyze in Pass 2 (0 = unlimited) |
|
|
212
|
-
| `allowCommitSplitting` | boolean | false | Allow splitting a commit into multiple stories when it contains unrelated changes (recommended for repos with messy commit history) |
|
|
213
|
-
| `contextIssues` | boolean | false | Include context issues from commit date range (tier 4 only) |
|
|
214
|
-
| `estimateOnly` | boolean | false | Preview token cost without running the pipeline |
|
|
215
|
-
|
|
216
|
-
### `evolve_decisions`
|
|
86
|
+
Override paths when blocked:
|
|
217
87
|
|
|
218
|
-
|
|
88
|
+
- **Persistent (recommended):** record a fork decision that supersedes the existing one and retry the Edit.
|
|
89
|
+
```
|
|
90
|
+
record_decision(type: "fork", supersedes: ["<surfaced-decision-id>"], rationale: "...")
|
|
91
|
+
```
|
|
92
|
+
- **One-off escape hatch:** add `force: true` to the Edit tool args. The hook acks the surfaced decisions in the session cache and allows the edit. Cache resets when the Kawa Code daemon restarts.
|
|
219
93
|
|
|
220
|
-
|
|
221
|
-
2. **Edge classification**: Uses LLM to identify relationships (supersedes, reinforces, contradicts, specializes)
|
|
222
|
-
3. **Annotation**: Labels each decision as stable, orphan, evolved, or abandoned
|
|
223
|
-
4. **Curation**: Keeps stable + orphan decisions, drops evolved + abandoned
|
|
94
|
+
Disable the hook for a session with `KAWA_PRE_EDIT_CHECK=off`.
|
|
224
95
|
|
|
225
|
-
|
|
96
|
+
### Local telemetry (logs)
|
|
226
97
|
|
|
227
|
-
**
|
|
98
|
+
Every pre-edit check fire (and force-override) appends a JSON line to a daily-rotated file at `~/.kawa-code/logs/pre-edit-decision-check-YYYY-MM-DD.jsonl`. Logs are **local only** — nothing leaves your machine. The defaults keep the last 30 days, capped at 100 MB total (oldest files dropped first).
|
|
228
99
|
|
|
229
|
-
|
|
230
|
-
|--------------|--------|-------------------------------|--------------------------------------------------------------------|
|
|
231
|
-
| `stories` | array | *(required)* | Story objects from a previous `infer_history` run |
|
|
232
|
-
| `apiKey` | string | *(required)* | Your Anthropic API key |
|
|
233
|
-
| `model` | string | claude-haiku-4-5-20251001 | Anthropic model (cheaper model recommended) |
|
|
234
|
-
| `repoPath` | string | *(optional)* | Local path to repository root (required for auto-persist) |
|
|
235
|
-
| `repoOrigin` | string | *(optional)* | Git remote origin URL (auto-detected from repoPath if not provided)|
|
|
100
|
+
Each line records what fired, why, and what was filtered out — useful for tuning the recommendation thresholds and spotting false positives over time.
|
|
236
101
|
|
|
237
|
-
|
|
102
|
+
Disable telemetry with `KAWA_PRE_EDIT_TELEMETRY=off`.
|
|
238
103
|
|
|
239
|
-
|
|
104
|
+
## Key Features
|
|
240
105
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
106
|
+
- **Real-time team conflict detection** — see when a teammate is editing the same files or lines in their working copy, *before either of you commits*. Most version-control tooling shows you this after the merge conflict; Kawa shows you before.
|
|
107
|
+
- **Cross-session AI memory** — your AI assistant picks up where it left off across days, branches, and machines. No re-explaining the architecture every morning.
|
|
108
|
+
- **Decision history with reasoning** — record forks, trade-offs, and abandoned approaches with their *why*. Future sessions and teammates inherit the context instead of re-deriving it.
|
|
109
|
+
- **Commit ↔ intent linkage** — every commit is automatically associated with the intent that drove it. `git log` shows what changed; Kawa shows why.
|
|
110
|
+
- **Smart context retrieval** — relevance-based loading; only what the current task needs.
|
|
111
|
+
- **Zero-knowledge encryption** — code blocks encrypted client-side before sync. The Kawa cloud cannot decrypt your team's code.
|
|
112
|
+
- **Cross-platform** — works with Claude Code, Cursor, and any MCP-compatible AI assistant.
|
|
248
113
|
|
|
249
114
|
## Development
|
|
250
115
|
|
|
@@ -285,21 +150,12 @@ Claude Code / Cursor AI
|
|
|
285
150
|
kawa.mcp (this server)
|
|
286
151
|
↓ Huginn IPC (Unix socket / Named pipe)
|
|
287
152
|
Kawa Code Desktop App
|
|
288
|
-
├─ Gardener Module (Rust)
|
|
289
|
-
│ └─ Intent/Decision storage
|
|
290
153
|
└─ HTTP Client
|
|
291
154
|
↓ REST + SSE
|
|
292
155
|
Kawa API (cloud)
|
|
293
|
-
└─ Team sync & encryption
|
|
156
|
+
└─ Team sync & zero-knowledge encryption
|
|
294
157
|
```
|
|
295
158
|
|
|
296
|
-
The MCP server communicates with Kawa Code using the Huginn IPC protocol:
|
|
297
|
-
- **Context queries**: Intents, decisions, relevant context
|
|
298
|
-
- **Intent operations**: Create, update, assign blocks, complete
|
|
299
|
-
- **Decision tracking**: Record, retrieve, edit, conflict detection
|
|
300
|
-
|
|
301
|
-
Kawa Code's Gardener module handles all git operations, diff generation, and local storage of encrypted data.
|
|
302
|
-
|
|
303
159
|
## Contributing
|
|
304
160
|
|
|
305
161
|
Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTION.md) and [CLA.md](CLA.md).
|
package/build/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
4
|
import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import { connectToMuninn, ensureRepo } from './services/muninn-ipc.js';
|
|
6
|
-
import { allTools, getRelevantContext, checkActiveIntent, createAndActivateIntent, activateIntent, getIntentsForFile, getIntentsForLines, listTeamIntents, getIntentChanges, completeIntent, logWork, recordDecision, getSessionDecisions, getProjectDecisions, editSessionDecision, detectIntentConflicts, inferHistory, evolveDecisions } from './tools/index.js';
|
|
6
|
+
import { allTools, getRelevantContext, checkActiveIntent, createAndActivateIntent, activateIntent, getIntentsForFile, getIntentsForLines, listTeamIntents, getIntentChanges, completeIntent, updateIntent, logWork, recordDecision, getSessionDecisions, getProjectDecisions, editSessionDecision, detectIntentConflicts, inferHistory, evolveDecisions, preEditDecisionCheck, preEditAcknowledge } from './tools/index.js';
|
|
7
7
|
import { prompts } from './prompts/intent-first-workflow.js';
|
|
8
8
|
import { resources, readActiveIntentResource } from './resources/active-intent.js';
|
|
9
9
|
// Create MCP server
|
|
@@ -76,6 +76,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
76
76
|
case 'complete_intent':
|
|
77
77
|
result = await completeIntent(args);
|
|
78
78
|
break;
|
|
79
|
+
case 'update_intent':
|
|
80
|
+
result = await updateIntent(args);
|
|
81
|
+
break;
|
|
79
82
|
case 'log_work':
|
|
80
83
|
result = await logWork(args);
|
|
81
84
|
break;
|
|
@@ -100,6 +103,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
100
103
|
case 'evolve_decisions':
|
|
101
104
|
result = await evolveDecisions(args);
|
|
102
105
|
break;
|
|
106
|
+
case 'pre_edit_decision_check':
|
|
107
|
+
result = await preEditDecisionCheck(args);
|
|
108
|
+
break;
|
|
109
|
+
case 'pre_edit_acknowledge':
|
|
110
|
+
result = await preEditAcknowledge(args);
|
|
111
|
+
break;
|
|
103
112
|
default:
|
|
104
113
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
105
114
|
}
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,SAAS,EACT,QAAQ,EACT,MAAM,oCAAoC,CAAA;AAE3C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAEtE,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,eAAe,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* kawacode-on-pre-edit — Claude Code PreToolUse hook dispatcher.
|
|
4
|
+
*
|
|
5
|
+
* Reads the PreToolUse hook payload from stdin (session_id, cwd, tool_name,
|
|
6
|
+
* tool_input). For Edit, resolves the touched line range from old_string
|
|
7
|
+
* against the file content on disk. For Write, targets the whole current
|
|
8
|
+
* file (skipping new files entirely).
|
|
9
|
+
*
|
|
10
|
+
* Sends ONE IPC to Muninn: `pre-edit-check:evaluate` — Muninn does the
|
|
11
|
+
* full evaluation (4-way data fan-out, supersedes computation, evaluator,
|
|
12
|
+
* enclosing-symbol enrichment, telemetry). Replaces the ~450-LOC legacy
|
|
13
|
+
* hook that did all of that locally.
|
|
14
|
+
*
|
|
15
|
+
* Maps recommendation to Claude Code's hook protocol:
|
|
16
|
+
* - "investigate-upstream" → exit 2 + stderr message (block)
|
|
17
|
+
* UNLESS tool_input.force === true → pre-edit-cache:add + exit 0
|
|
18
|
+
* - "review" → exit 0 + JSON on stdout (advisory)
|
|
19
|
+
* - "proceed" / silent → exit 0, no output
|
|
20
|
+
*
|
|
21
|
+
* Failure discipline: every error path exits 0. Hook must not block
|
|
22
|
+
* Claude Code's turn loop on infra issues. (Same fail-soft carve-out
|
|
23
|
+
* as kawacode-on-stop — see that file's header for the rule.)
|
|
24
|
+
*
|
|
25
|
+
* Opt out with KAWA_PRE_EDIT_CHECK=off.
|
|
26
|
+
*/
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* kawacode-on-pre-edit — Claude Code PreToolUse hook dispatcher.
|
|
4
|
+
*
|
|
5
|
+
* Reads the PreToolUse hook payload from stdin (session_id, cwd, tool_name,
|
|
6
|
+
* tool_input). For Edit, resolves the touched line range from old_string
|
|
7
|
+
* against the file content on disk. For Write, targets the whole current
|
|
8
|
+
* file (skipping new files entirely).
|
|
9
|
+
*
|
|
10
|
+
* Sends ONE IPC to Muninn: `pre-edit-check:evaluate` — Muninn does the
|
|
11
|
+
* full evaluation (4-way data fan-out, supersedes computation, evaluator,
|
|
12
|
+
* enclosing-symbol enrichment, telemetry). Replaces the ~450-LOC legacy
|
|
13
|
+
* hook that did all of that locally.
|
|
14
|
+
*
|
|
15
|
+
* Maps recommendation to Claude Code's hook protocol:
|
|
16
|
+
* - "investigate-upstream" → exit 2 + stderr message (block)
|
|
17
|
+
* UNLESS tool_input.force === true → pre-edit-cache:add + exit 0
|
|
18
|
+
* - "review" → exit 0 + JSON on stdout (advisory)
|
|
19
|
+
* - "proceed" / silent → exit 0, no output
|
|
20
|
+
*
|
|
21
|
+
* Failure discipline: every error path exits 0. Hook must not block
|
|
22
|
+
* Claude Code's turn loop on infra issues. (Same fail-soft carve-out
|
|
23
|
+
* as kawacode-on-stop — see that file's header for the rule.)
|
|
24
|
+
*
|
|
25
|
+
* Opt out with KAWA_PRE_EDIT_CHECK=off.
|
|
26
|
+
*/
|
|
27
|
+
import { readFileSync } from 'node:fs';
|
|
28
|
+
import { connectToMuninn, request, disconnect } from './services/muninn-ipc.js';
|
|
29
|
+
import { resolveOrigin } from './tools/resolve-origin.js';
|
|
30
|
+
import { resolvePaths } from './pre-edit/path-resolve.js';
|
|
31
|
+
function readStdin() {
|
|
32
|
+
try {
|
|
33
|
+
return readFileSync(0, 'utf8');
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Find the first occurrence of `needle` in `haystack` and return its 1-based
|
|
41
|
+
* inclusive line range. Returns null if not found.
|
|
42
|
+
*/
|
|
43
|
+
function locateLineRange(haystack, needle) {
|
|
44
|
+
if (!needle)
|
|
45
|
+
return null;
|
|
46
|
+
const idx = haystack.indexOf(needle);
|
|
47
|
+
if (idx < 0)
|
|
48
|
+
return null;
|
|
49
|
+
let startLine = 1;
|
|
50
|
+
for (let i = 0; i < idx; i += 1) {
|
|
51
|
+
if (haystack.charCodeAt(i) === 10)
|
|
52
|
+
startLine += 1;
|
|
53
|
+
}
|
|
54
|
+
let extraLines = 0;
|
|
55
|
+
for (let i = 0; i < needle.length; i += 1) {
|
|
56
|
+
if (needle.charCodeAt(i) === 10)
|
|
57
|
+
extraLines += 1;
|
|
58
|
+
}
|
|
59
|
+
return { startLine, endLine: startLine + extraLines };
|
|
60
|
+
}
|
|
61
|
+
function resolveTarget(payload) {
|
|
62
|
+
const cwd = payload.cwd;
|
|
63
|
+
const toolName = payload.tool_name;
|
|
64
|
+
const input = payload.tool_input;
|
|
65
|
+
if (!cwd || !toolName || !input)
|
|
66
|
+
return null;
|
|
67
|
+
const filePath = input.file_path;
|
|
68
|
+
if (!filePath)
|
|
69
|
+
return null;
|
|
70
|
+
// Cross-platform path resolution. Returns null for files outside the repo.
|
|
71
|
+
const resolved = resolvePaths(cwd, filePath);
|
|
72
|
+
if (!resolved)
|
|
73
|
+
return null;
|
|
74
|
+
const { absolutePath, relativePath } = resolved;
|
|
75
|
+
let fileContent;
|
|
76
|
+
try {
|
|
77
|
+
fileContent = readFileSync(absolutePath, 'utf8');
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Either Write to a new file (no prior history) or read failure — skip.
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
if (toolName === 'Edit') {
|
|
84
|
+
const oldString = input.old_string;
|
|
85
|
+
if (!oldString)
|
|
86
|
+
return null;
|
|
87
|
+
const range = locateLineRange(fileContent, oldString);
|
|
88
|
+
if (!range)
|
|
89
|
+
return null;
|
|
90
|
+
return { filePath: relativePath, repoPath: cwd, ...range };
|
|
91
|
+
}
|
|
92
|
+
if (toolName === 'Write') {
|
|
93
|
+
const lines = fileContent.split('\n').length;
|
|
94
|
+
return { filePath: relativePath, repoPath: cwd, startLine: 1, endLine: Math.max(1, lines) };
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
function formatBlockMessage(target, res) {
|
|
99
|
+
const lines = [];
|
|
100
|
+
const symbol = res.enclosingSymbol?.name ? ` (in ${res.enclosingSymbol.name})` : '';
|
|
101
|
+
lines.push(`Pre-edit decision check: prior reasoning is attached to ${target.filePath}:${target.startLine}-${target.endLine}${symbol}.`);
|
|
102
|
+
for (const d of res.decisions ?? []) {
|
|
103
|
+
lines.push(` • [${d.type}] ${d.summary ?? ''}`);
|
|
104
|
+
if (d.rationale)
|
|
105
|
+
lines.push(` ${d.rationale}`);
|
|
106
|
+
}
|
|
107
|
+
lines.push('');
|
|
108
|
+
lines.push('Override options:');
|
|
109
|
+
lines.push(' 1) record_decision(type:"fork", supersedes:[<id>], rationale:"...") then retry the Edit.');
|
|
110
|
+
lines.push(' 2) Add `force: true` to the Edit args as a one-off escape hatch (acks the surfaced decisions for this session).');
|
|
111
|
+
return lines.join('\n');
|
|
112
|
+
}
|
|
113
|
+
async function main() {
|
|
114
|
+
if (process.env.KAWA_PRE_EDIT_CHECK === 'off') {
|
|
115
|
+
process.exit(0);
|
|
116
|
+
}
|
|
117
|
+
const raw = readStdin();
|
|
118
|
+
if (!raw)
|
|
119
|
+
process.exit(0);
|
|
120
|
+
let payload;
|
|
121
|
+
try {
|
|
122
|
+
payload = JSON.parse(raw);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
process.exit(0);
|
|
126
|
+
}
|
|
127
|
+
const target = resolveTarget(payload);
|
|
128
|
+
if (!target)
|
|
129
|
+
process.exit(0);
|
|
130
|
+
const sessionToken = payload.session_id || 'default';
|
|
131
|
+
// Resolve origin from the repo path. Falls back silently to exit 0
|
|
132
|
+
// when git isn't available or the path isn't a repo.
|
|
133
|
+
let repoOrigin;
|
|
134
|
+
try {
|
|
135
|
+
repoOrigin = resolveOrigin(undefined, target.repoPath);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
process.exit(0);
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
await connectToMuninn();
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
process.exit(0);
|
|
145
|
+
}
|
|
146
|
+
let res;
|
|
147
|
+
try {
|
|
148
|
+
res = await request('pre-edit-check', 'evaluate', {
|
|
149
|
+
repoOrigin,
|
|
150
|
+
repoPath: target.repoPath,
|
|
151
|
+
filePath: target.filePath,
|
|
152
|
+
startLine: target.startLine,
|
|
153
|
+
endLine: target.endLine,
|
|
154
|
+
sessionToken,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
disconnect();
|
|
159
|
+
process.exit(0);
|
|
160
|
+
}
|
|
161
|
+
if (res?.recommendation === 'investigate-upstream') {
|
|
162
|
+
const force = payload.tool_input?.force === true;
|
|
163
|
+
if (force) {
|
|
164
|
+
// Acknowledge surfaced decisions for this session, then allow.
|
|
165
|
+
const ids = (res.decisions ?? []).map(d => d.decisionId).filter(Boolean);
|
|
166
|
+
if (ids.length > 0) {
|
|
167
|
+
try {
|
|
168
|
+
await request('pre-edit-cache', 'add', {
|
|
169
|
+
sessionToken,
|
|
170
|
+
decisionIds: ids,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
/* best-effort */
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
disconnect();
|
|
178
|
+
process.exit(0);
|
|
179
|
+
}
|
|
180
|
+
// Block: exit 2 with stderr message. Claude Code surfaces it to the user.
|
|
181
|
+
process.stderr.write(formatBlockMessage(target, res) + '\n');
|
|
182
|
+
disconnect();
|
|
183
|
+
process.exit(2);
|
|
184
|
+
}
|
|
185
|
+
if (res?.recommendation === 'review') {
|
|
186
|
+
const out = {
|
|
187
|
+
hookSpecificOutput: {
|
|
188
|
+
hookEventName: 'PreToolUse',
|
|
189
|
+
additionalContext: formatBlockMessage(target, res),
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
process.stdout.write(JSON.stringify(out) + '\n');
|
|
193
|
+
disconnect();
|
|
194
|
+
process.exit(0);
|
|
195
|
+
}
|
|
196
|
+
// Silent — proceed.
|
|
197
|
+
disconnect();
|
|
198
|
+
process.exit(0);
|
|
199
|
+
}
|
|
200
|
+
main().catch(() => process.exit(0));
|
|
201
|
+
//# sourceMappingURL=kawacode-on-pre-edit.js.map
|