@bigknoxy/hashpilot 4.6.3
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/LICENSE +21 -0
- package/README.md +777 -0
- package/docs/ADAPTER-CONTRACT.md +1260 -0
- package/docs/ARCHITECTURE.md +846 -0
- package/docs/CLI-QUICKREF.md +827 -0
- package/docs/COMPETITIVE-ANALYSIS.md +307 -0
- package/docs/INSTALL.md +403 -0
- package/docs/INTEGRATION-CLAUDE.md +126 -0
- package/docs/INTEGRATION-MCP.md +196 -0
- package/docs/INTEGRATION-OPENCODE.md +136 -0
- package/docs/INTEGRATION-PI.md +195 -0
- package/package.json +77 -0
- package/scripts/build-site.sh +39 -0
- package/scripts/doctor.sh +218 -0
- package/scripts/gen-cli-quickref.ts +232 -0
- package/scripts/install-cli.sh +60 -0
- package/scripts/install.sh +466 -0
- package/scripts/roadmap-lint.ts +200 -0
- package/scripts/uninstall.sh +202 -0
- package/src/cli-node.cjs +51 -0
- package/src/cli.ts +209 -0
- package/src/commands/ast.ts +255 -0
- package/src/commands/diff.ts +98 -0
- package/src/commands/edit.ts +93 -0
- package/src/commands/hash.ts +64 -0
- package/src/commands/intent.ts +68 -0
- package/src/commands/maintenance.ts +191 -0
- package/src/commands/mcp.ts +28 -0
- package/src/commands/provenance.ts +111 -0
- package/src/commands/read.ts +117 -0
- package/src/commands/route.ts +42 -0
- package/src/commands/shared.ts +65 -0
- package/src/commands/telemetry.ts +126 -0
- package/src/commands/verify.ts +61 -0
- package/src/core/ast-edit.ts +2357 -0
- package/src/core/batch-edit.ts +185 -0
- package/src/core/config.ts +189 -0
- package/src/core/diff-engine.ts +474 -0
- package/src/core/doctor.ts +303 -0
- package/src/core/encoding.ts +116 -0
- package/src/core/envelope.ts +163 -0
- package/src/core/exit-codes.ts +198 -0
- package/src/core/format.ts +339 -0
- package/src/core/grep.ts +180 -0
- package/src/core/hash-edit.ts +416 -0
- package/src/core/index.ts +155 -0
- package/src/core/intent.ts +584 -0
- package/src/core/locking.ts +292 -0
- package/src/core/module-system.ts +142 -0
- package/src/core/operations.ts +557 -0
- package/src/core/output.ts +122 -0
- package/src/core/path-normalize.ts +61 -0
- package/src/core/paths.ts +326 -0
- package/src/core/plan-executor.ts +437 -0
- package/src/core/platform.ts +132 -0
- package/src/core/provenance.ts +214 -0
- package/src/core/read.ts +111 -0
- package/src/core/redact.ts +98 -0
- package/src/core/resolve-content.ts +12 -0
- package/src/core/router.ts +463 -0
- package/src/core/snapshot.ts +346 -0
- package/src/core/telemetry.ts +838 -0
- package/src/core/utils.ts +7 -0
- package/src/core/verify-baseline.ts +186 -0
- package/src/core/verify-scope.ts +282 -0
- package/src/core/verify.ts +753 -0
- package/src/mcp/server.ts +325 -0
- package/templates/claude-section.md +12 -0
- package/templates/opencode-agent.md +106 -0
- package/templates/opencode-skill.md +241 -0
- package/templates/pi-extension.ts +288 -0
- package/templates/pi-skill.md +123 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# HashPilot as an MCP server
|
|
2
|
+
|
|
3
|
+
HashPilot speaks the [Model Context Protocol](https://modelcontextprotocol.io) over
|
|
4
|
+
stdio. Point any MCP host at `hashpilot mcp --stdio` and every editing tier —
|
|
5
|
+
AST, hash-anchored, and diff — shows up as a typed tool, with the same advisory
|
|
6
|
+
locking, provenance, and snapshot/undo guarantees the CLI gets.
|
|
7
|
+
|
|
8
|
+
MCP is now the recommended integration path. The CLI remains fully supported and
|
|
9
|
+
is the fallback for hosts without MCP support, and for shell and CI use.
|
|
10
|
+
|
|
11
|
+
## Why MCP over the CLI
|
|
12
|
+
|
|
13
|
+
| | MCP | CLI |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| Multi-line content with quotes and backticks | Rides inside JSON; no escaping | Needs `@file` indirection to dodge the shell |
|
|
16
|
+
| Tool discovery | The host lists tools and schemas to the model | The model must be told the commands |
|
|
17
|
+
| Errors | Structured, with `code` and `recovery` the model can act on | Same envelope, but parsed out of stdout |
|
|
18
|
+
| Availability | Requires an MCP-capable host | Anywhere with a shell |
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g hashpilot # or: bun add -g hashpilot
|
|
24
|
+
hashpilot doctor # confirm the install is healthy
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Configure your host
|
|
28
|
+
|
|
29
|
+
### Claude Code
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
claude mcp add hashpilot -- hashpilot mcp --stdio
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or add it to `~/.claude.json` by hand:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"hashpilot": {
|
|
41
|
+
"command": "hashpilot",
|
|
42
|
+
"args": ["mcp", "--stdio"]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Claude Desktop
|
|
49
|
+
|
|
50
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS
|
|
51
|
+
(`%APPDATA%\Claude\claude_desktop_config.json` on Windows):
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"hashpilot": {
|
|
57
|
+
"command": "hashpilot",
|
|
58
|
+
"args": ["mcp", "--stdio"]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Restart Claude Desktop afterwards; it reads the config only at launch.
|
|
65
|
+
|
|
66
|
+
### Cursor
|
|
67
|
+
|
|
68
|
+
`.cursor/mcp.json` in the project, or `~/.cursor/mcp.json` globally:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mcpServers": {
|
|
73
|
+
"hashpilot": {
|
|
74
|
+
"command": "hashpilot",
|
|
75
|
+
"args": ["mcp", "--stdio"]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Zed, Continue, and other hosts
|
|
82
|
+
|
|
83
|
+
Any host that launches a stdio MCP server takes the same three fields — command
|
|
84
|
+
`hashpilot`, args `["mcp", "--stdio"]`, and no environment beyond your shell's.
|
|
85
|
+
If your host wants an absolute path, use `which hashpilot`.
|
|
86
|
+
|
|
87
|
+
### Running from a checkout
|
|
88
|
+
|
|
89
|
+
Without a global install, point the host at the repo:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"mcpServers": {
|
|
94
|
+
"hashpilot": {
|
|
95
|
+
"command": "bun",
|
|
96
|
+
"args": ["run", "/absolute/path/to/HashPilot/src/cli.ts", "mcp", "--stdio"]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Tools
|
|
103
|
+
|
|
104
|
+
Every tool is generated from the operation registry in
|
|
105
|
+
[`src/core/operations.ts`](../src/core/operations.ts), which is the same list the
|
|
106
|
+
CLI surface is verified against — the two cannot drift.
|
|
107
|
+
|
|
108
|
+
### Reading
|
|
109
|
+
|
|
110
|
+
| Tool | Use it for |
|
|
111
|
+
|---|---|
|
|
112
|
+
| `read_many` | Whole files plus a content hash per file. The hash is the anchor a later `replace_hash` verifies against. |
|
|
113
|
+
| `read_hash` | One line with context and its hash, when you already know the line. |
|
|
114
|
+
| `grep_many` | Regex search across paths. The cheapest way to locate code. |
|
|
115
|
+
| `symbol_lookup_many` | Where symbols are *defined* (not referenced). |
|
|
116
|
+
| `find_symbols` | Every symbol declared in one file. |
|
|
117
|
+
| `ast_capabilities` | Which languages and AST operations are supported. |
|
|
118
|
+
|
|
119
|
+
### Editing
|
|
120
|
+
|
|
121
|
+
| Tool | Tier | Use it for |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `rename_symbol` | AST | Binding-aware, file-scoped rename. |
|
|
124
|
+
| `replace_body` | AST | Swap a function body, keep the signature. |
|
|
125
|
+
| `add_import` / `remove_import` | AST | Imports, in the language's own style. |
|
|
126
|
+
| `insert_before` / `insert_after` | AST | Code anchored to a symbol, not a line number. |
|
|
127
|
+
| `replace_hash` | Hash | Verified replacement — refuses if the file changed since you read it. |
|
|
128
|
+
| `replace_content` | Diff | Exact-match fallback; refuses on an ambiguous match. |
|
|
129
|
+
| `route_edit` | auto | Any operation, letting HashPilot pick the strongest tier available. |
|
|
130
|
+
|
|
131
|
+
### Verification
|
|
132
|
+
|
|
133
|
+
`verify_changes` runs the project's own formatter, linter, type checker, and
|
|
134
|
+
tests, scoped to the files you edited. Pass `useBaseline: true` so tests that
|
|
135
|
+
were already failing do not get blamed on your edit.
|
|
136
|
+
|
|
137
|
+
Every mutating tool accepts `dryRun`, plus `actor`, `taskId`, and `reason` for
|
|
138
|
+
provenance — the same fields the CLI records, queryable afterwards with
|
|
139
|
+
`hashpilot provenance query <file>`.
|
|
140
|
+
|
|
141
|
+
## Error handling
|
|
142
|
+
|
|
143
|
+
A failed edit comes back as a normal MCP result with `isError: true`, not as a
|
|
144
|
+
JSON-RPC error. Protocol errors are the host's problem; tool errors are yours to
|
|
145
|
+
read and recover from. The payload is the standard envelope:
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"apiVersion": "1",
|
|
150
|
+
"ok": false,
|
|
151
|
+
"command": "replace_hash",
|
|
152
|
+
"data": null,
|
|
153
|
+
"error": {
|
|
154
|
+
"code": "STALE_ANCHOR",
|
|
155
|
+
"message": "the file changed since the hash was taken",
|
|
156
|
+
"recovery": "Re-read the file and retry with the new hash."
|
|
157
|
+
},
|
|
158
|
+
"warnings": []
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Act on `error.code`; `error.recovery` says what to do next. The codes are the
|
|
163
|
+
same ones the CLI reports — see [ADAPTER-CONTRACT.md](ADAPTER-CONTRACT.md).
|
|
164
|
+
|
|
165
|
+
Every tool response — success or failure — carries all five envelope fields,
|
|
166
|
+
byte-for-byte the shape the CLI writes: `command` names the tool that answered,
|
|
167
|
+
`data` and `error` are both present with one of them `null`, and `warnings`
|
|
168
|
+
reports route fallbacks and relocated hash anchors. That last one is the reason
|
|
169
|
+
this matters: an AST edit that quietly became a diff edit is otherwise
|
|
170
|
+
indistinguishable from one that stayed on the AST tier ([#104](../../issues/104)).
|
|
171
|
+
|
|
172
|
+
## Write boundary
|
|
173
|
+
|
|
174
|
+
The MCP server enforces exactly the same boundary as the CLI: writes are
|
|
175
|
+
confined to the project root, and credentials, shell config, and system paths
|
|
176
|
+
are refused unconditionally. A tool call cannot widen it. Widen the project's
|
|
177
|
+
own `allowedRoots` in `.hashpilot.json` if you legitimately need more.
|
|
178
|
+
|
|
179
|
+
## Troubleshooting
|
|
180
|
+
|
|
181
|
+
**The host shows no tools.** Check the binary runs: `hashpilot mcp --stdio`
|
|
182
|
+
should sit waiting on stdin rather than exiting. `hashpilot doctor` diagnoses a
|
|
183
|
+
broken install.
|
|
184
|
+
|
|
185
|
+
**Edits fail with `PATH_DENIED`.** The target is outside the project root. Start
|
|
186
|
+
the host from the project directory, or add the location to `allowedRoots`.
|
|
187
|
+
|
|
188
|
+
**AST tools fall back to hash or diff.** tree-sitter is a native module; if the
|
|
189
|
+
bindings did not build, parsers load as `null` and routing degrades silently.
|
|
190
|
+
Reinstall, then check `ast_capabilities`.
|
|
191
|
+
|
|
192
|
+
**Verify a host's view by hand:**
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | hashpilot mcp --stdio
|
|
196
|
+
```
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# HashPilot — OpenCode Integration Guide
|
|
2
|
+
|
|
3
|
+
## Integration Pattern
|
|
4
|
+
|
|
5
|
+
HashPilot integrates with OpenCode as a **skill** (for inline guidance) and a **subagent** (for delegated editing tasks).
|
|
6
|
+
|
|
7
|
+
## Installed Components
|
|
8
|
+
|
|
9
|
+
### Skill: `~/.config/opencode/skills/hashpilot/SKILL.md`
|
|
10
|
+
|
|
11
|
+
Provides instructions that OpenCode's AI can reference when deciding how to edit files. The skill triggers when:
|
|
12
|
+
- The user asks to edit files precisely
|
|
13
|
+
- Hash-anchored edits are appropriate
|
|
14
|
+
- TypeScript/TSX symbol-level edits are needed
|
|
15
|
+
|
|
16
|
+
### Agent: `~/.config/opencode/agent/hashpilot.md`
|
|
17
|
+
|
|
18
|
+
A subagent definition with full tool access (bash, write, edit, read, grep, glob) that:
|
|
19
|
+
- Prefers AST commands for TypeScript, TSX, JavaScript, Python, Go, Rust
|
|
20
|
+
- Uses hash-anchored edits for other files
|
|
21
|
+
- Verifies changes after editing
|
|
22
|
+
- Handles stale anchors by re-reading and retrying
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
The skill and agent are already installed. If you need to set them up manually:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Skill
|
|
30
|
+
mkdir -p ~/.config/opencode/skills/hashpilot
|
|
31
|
+
cp ~/.agentic-tools/structured-editing/templates/opencode-skill.md ~/.config/opencode/skills/hashpilot/SKILL.md
|
|
32
|
+
|
|
33
|
+
# Agent (already auto-discovered from ~/.config/opencode/agent/)
|
|
34
|
+
# No additional setup needed
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### PATH requirement
|
|
38
|
+
|
|
39
|
+
Ensure `~/.agentic-tools/bin` is in PATH before launching OpenCode:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Add to ~/.bashrc or ~/.zshrc
|
|
43
|
+
export PATH="$HOME/.agentic-tools/bin:$PATH"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage in OpenCode Sessions
|
|
47
|
+
|
|
48
|
+
### Inline skill usage
|
|
49
|
+
|
|
50
|
+
When OpenCode detects file editing tasks, it will reference the hashpilot skill and use `hashpilot` commands directly via bash tool:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# OpenCode agent using hash-anchored edit
|
|
54
|
+
HASH=$(hashpilot read-many src/config.ts | jq -r '.[0].hash')
|
|
55
|
+
hashpilot replace-hash src/config.ts "$HASH" "new content"
|
|
56
|
+
|
|
57
|
+
# OpenCode agent using AST edit for TypeScript
|
|
58
|
+
hashpilot ast rename-symbol src/api.ts oldFunc newFunc
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Subagent delegation
|
|
62
|
+
|
|
63
|
+
Use the HashPilot subagent for complex multi-file editing tasks:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
/agent hashpilot
|
|
67
|
+
|
|
68
|
+
Rename the function 'processData' to 'transformData' across all files
|
|
69
|
+
in src/ and update the imports accordingly.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The subagent will:
|
|
73
|
+
1. Find all files containing `processData`
|
|
74
|
+
2. Use `ast rename-symbol` for .ts files
|
|
75
|
+
3. Use `replace-hash` for other files
|
|
76
|
+
4. Run `verify-changes` on all modified files
|
|
77
|
+
|
|
78
|
+
## When to Use HashPilot vs Raw Editing
|
|
79
|
+
|
|
80
|
+
| Task | Use HashPilot | Use Direct |
|
|
81
|
+
|------|--------------|------------|
|
|
82
|
+
| Edit existing TS/JS/Python/Go/Rust files | ✅ AST commands | ❌ |
|
|
83
|
+
| Edit any file with hash safety | ✅ replace-hash | ❌ |
|
|
84
|
+
| Rename symbols across files | ✅ ast rename-symbol | ❌ |
|
|
85
|
+
| Add/remove imports | ✅ ast add-import / remove-import | ❌ |
|
|
86
|
+
| Replace function body | ✅ ast replace-body | ❌ |
|
|
87
|
+
| Batch read multiple files | ✅ read-many | ❌ |
|
|
88
|
+
| Verify changes (lint+test) | ✅ verify-changes | ❌ |
|
|
89
|
+
| Create new files | ❌ | ✅ write |
|
|
90
|
+
| Delete files/directories | ❌ | ✅ bash rm |
|
|
91
|
+
| Move/rename files | ❌ | ✅ bash mv |
|
|
92
|
+
| Simple one-line edits | optional | ✅ direct edit |
|
|
93
|
+
| Single-file exploration | optional | ✅ direct read |
|
|
94
|
+
|
|
95
|
+
**General rule**: HashPilot for precision edits to existing files; direct tools for creation, deletion, and file system operations.
|
|
96
|
+
|
|
97
|
+
## Key Advantages Over Raw Editing
|
|
98
|
+
|
|
99
|
+
| Aspect | Raw Edit | HashPilot |
|
|
100
|
+
|--------|----------|-----------|
|
|
101
|
+
| Line counting | Required, error-prone | Hash-anchored, robust |
|
|
102
|
+
| TypeScript edits | Text-based, imprecise | AST-aware, symbol-level |
|
|
103
|
+
| Conflict detection | None | Stale anchor rejection |
|
|
104
|
+
| Verification | Manual | Bundled formatter+linter+tests |
|
|
105
|
+
| Audit trail | None | Telemetry logging |
|
|
106
|
+
|
|
107
|
+
## Reference: Complete Command List
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
hashpilot read-many <files...>
|
|
111
|
+
hashpilot read-hash <file> <line> [-c <context>]
|
|
112
|
+
hashpilot grep-many <pattern> <paths...>
|
|
113
|
+
hashpilot symbol-lookup-many <paths...> --names n1,n2
|
|
114
|
+
hashpilot replace-hash <file> <hash> <content> [--range s:e] [--dry-run] [--actor] [--task-id] [--reason]
|
|
115
|
+
hashpilot ast find-symbols <file>
|
|
116
|
+
hashpilot ast capabilities
|
|
117
|
+
hashpilot ast rename-symbol <file> <old> <new> [--actor] [--task-id] [--reason]
|
|
118
|
+
hashpilot ast replace-body <file> <symbol> <body> [--actor] [--task-id] [--reason]
|
|
119
|
+
hashpilot ast add-import <file> '<spec>' [--actor] [--task-id] [--reason]
|
|
120
|
+
hashpilot ast remove-import <file> '<spec>' [--actor] [--task-id] [--reason]
|
|
121
|
+
hashpilot ast insert-before <file> <symbol> <content> [--actor] [--task-id] [--reason]
|
|
122
|
+
hashpilot ast insert-after <file> <symbol> <content> [--actor] [--task-id] [--reason]
|
|
123
|
+
hashpilot diff generate <file> <old> <new>
|
|
124
|
+
hashpilot diff apply <file> --patch <file> [--dry-run]
|
|
125
|
+
hashpilot route <file> <op> [--policy <json>]
|
|
126
|
+
hashpilot route-edit <file> <op> [--method <route>] [--dry-run]
|
|
127
|
+
hashpilot batch <op> <files...> [--serial] [--dry-run]
|
|
128
|
+
hashpilot intent '<json>' [--project-root <dir>] [--dry-run]
|
|
129
|
+
hashpilot config
|
|
130
|
+
hashpilot doctor
|
|
131
|
+
hashpilot verify-changes <files...> [--formatter] [--linter] [--typecheck] [--test-filter] [--auto-detect]
|
|
132
|
+
hashpilot provenance query <file> [<line>] [--human]
|
|
133
|
+
hashpilot provenance changeset <changeSetId> [--human]
|
|
134
|
+
hashpilot telemetry [show|summary|health|clear|sessions|export|prune]
|
|
135
|
+
hashpilot telemetry health [-w <days>] [--trend]
|
|
136
|
+
```
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# HashPilot — Pi Integration Guide
|
|
2
|
+
|
|
3
|
+
## Two Integration Modes
|
|
4
|
+
|
|
5
|
+
HashPilot integrates with Pi in two ways:
|
|
6
|
+
|
|
7
|
+
1. **Native Extension** (recommended) — Custom tools registered in Pi's tool system, available in every session
|
|
8
|
+
2. **CLI Mode** — Direct shell commands via `hashpilot`
|
|
9
|
+
|
|
10
|
+
## Mode 1: Native Pi Extension (Recommended)
|
|
11
|
+
|
|
12
|
+
The HashPilot Pi extension is installed at `~/.pi/agent/extensions/hashpilot.ts`. It registers 7 custom tools and a `/hp` slash command.
|
|
13
|
+
|
|
14
|
+
### Registered Tools
|
|
15
|
+
|
|
16
|
+
| Tool | Description |
|
|
17
|
+
|------|-------------|
|
|
18
|
+
| `hashpilot_read` | Batch read files with content hashes |
|
|
19
|
+
| `hashpilot_search` | Grep regex across paths |
|
|
20
|
+
| `hashpilot_read_hash` | Read line with hash anchor and context |
|
|
21
|
+
| `hashpilot_replace_hash` | Hash-anchored content replacement |
|
|
22
|
+
| `hashpilot_ast` | AST operations for supported languages (find-symbols, rename, replace-body, add/remove import, insert) |
|
|
23
|
+
| `hashpilot_verify` | Run formatter + linter + tests on files |
|
|
24
|
+
| `hashpilot_status` | Show routing info and telemetry summary |
|
|
25
|
+
|
|
26
|
+
### Slash Command
|
|
27
|
+
|
|
28
|
+
`/hp <subcommand>` — Quick access to HashPilot:
|
|
29
|
+
- `/hp route <file> <op>` — Show which edit route would be chosen
|
|
30
|
+
- `/hp telemetry` — Show telemetry summary
|
|
31
|
+
|
|
32
|
+
### Skill
|
|
33
|
+
|
|
34
|
+
The `hashpilot` skill at `~/.pi/agent/skills/hashpilot/SKILL.md` provides routing instructions and workflow guidance. Use `/skill:hashpilot` to load it.
|
|
35
|
+
|
|
36
|
+
### How It Works
|
|
37
|
+
|
|
38
|
+
The extension calls `hashpilot` CLI under the hood via `pi.exec()`. Each tool:
|
|
39
|
+
1. Validates parameters using TypeBox schemas
|
|
40
|
+
2. Calls the appropriate `hashpilot` command
|
|
41
|
+
3. Parses JSON output
|
|
42
|
+
4. Returns structured results to the LLM
|
|
43
|
+
|
|
44
|
+
For `hashpilot_replace_hash`, stale-anchor detection is built in — if the hash is stale, the tool returns a clear error message telling the agent to re-read and retry.
|
|
45
|
+
|
|
46
|
+
### Enabling/Disabling
|
|
47
|
+
|
|
48
|
+
The `hashpilot_enabled` flag controls whether tools appear in Pi's Available Tools. Default: enabled.
|
|
49
|
+
|
|
50
|
+
## Mode 2: CLI Direct Usage
|
|
51
|
+
|
|
52
|
+
If the extension isn't loaded, Pi can call `hashpilot` directly via shell:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Read files with hashes
|
|
56
|
+
hashpilot read-many src/main.ts src/worker.ts
|
|
57
|
+
|
|
58
|
+
# Read a line with context
|
|
59
|
+
hashpilot read-hash src/main.ts 42
|
|
60
|
+
|
|
61
|
+
# Hash-anchored replacement
|
|
62
|
+
HASH=$(hashpilot read-many src/config.py | jq -r '.[0].hash')
|
|
63
|
+
hashpilot replace-hash src/config.py "$HASH" "new content"
|
|
64
|
+
|
|
65
|
+
# AST operations (TypeScript, TSX, JavaScript, Python, Go, Rust)
|
|
66
|
+
hashpilot ast find-symbols src/main.ts
|
|
67
|
+
hashpilot ast rename-symbol src/main.ts oldFunc newFunc
|
|
68
|
+
hashpilot ast replace-body src/main.ts myFunc 'return 42;'
|
|
69
|
+
hashpilot ast add-import src/app.ts '{ Router } from express'
|
|
70
|
+
hashpilot ast remove-import src/app.ts './bar'
|
|
71
|
+
|
|
72
|
+
# Generate and apply unified diffs
|
|
73
|
+
hashpilot diff generate src/main.ts "$(cat old.ts)" "$(cat new.ts)"
|
|
74
|
+
hashpilot diff apply src/main.ts --patch changes.patch
|
|
75
|
+
|
|
76
|
+
# Route decisions and config
|
|
77
|
+
hashpilot route src/main.ts rename-symbol
|
|
78
|
+
hashpilot config
|
|
79
|
+
|
|
80
|
+
# Batch edit across files
|
|
81
|
+
hashpilot batch add-import src/*.ts --import-spec "{ z } from zod" --dry-run
|
|
82
|
+
|
|
83
|
+
# Edit provenance
|
|
84
|
+
hashpilot provenance query src/main.ts --human
|
|
85
|
+
|
|
86
|
+
# Verify changes (with auto-detection)
|
|
87
|
+
hashpilot verify-changes src/main.ts --auto-detect
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Routing Strategy
|
|
91
|
+
|
|
92
|
+
HashPilot uses a strict priority for edit method selection:
|
|
93
|
+
|
|
94
|
+
1. **AST** — For supported languages (TypeScript, TSX, JavaScript, Python, Go, Rust) with AST-compatible operations (rename, replace-body, add/remove import, insert)
|
|
95
|
+
2. **Hash** — For hash-anchored content identification (any file type)
|
|
96
|
+
3. **Diff** — Fallback for unsupported operations
|
|
97
|
+
|
|
98
|
+
Check routing: `hashpilot route <file> <operation> [--policy <json>]`
|
|
99
|
+
|
|
100
|
+
For detailed explanation with policy matches, use `--policy` to test override behavior:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
hashpilot route src/main.ts rename-symbol
|
|
104
|
+
# → { route: "ast", explanation: { reasons: ["Language 'typescript' supports AST operations"], ... } }
|
|
105
|
+
|
|
106
|
+
hashpilot route src/main.py rename-symbol --policy '{"languageOverrides":{"python":"hash"}}'
|
|
107
|
+
# → { route: "hash", explanation: { policyApplied: true, ... } }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Configuration
|
|
111
|
+
|
|
112
|
+
HashPilot supports layered configuration via files and environment variables:
|
|
113
|
+
|
|
114
|
+
| Source | Path | Priority |
|
|
115
|
+
|--------|------|----------|
|
|
116
|
+
| Global config | `~/.config/hashpilot/config.json` | Lowest (applied first) |
|
|
117
|
+
| Project config | `.hashpilot.json` in cwd | Medium |
|
|
118
|
+
| CLI override | `--config <path>` | Higher |
|
|
119
|
+
| Environment | `HASHPILOT_ROUTE_POLICY` env var | Highest |
|
|
120
|
+
|
|
121
|
+
Example project config (`.hashpilot.json`):
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"routePolicy": {
|
|
126
|
+
"languageOverrides": { "python": "hash" },
|
|
127
|
+
"operationOverrides": { "add-import": "diff" }
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
View current merged config: `hashpilot config`
|
|
133
|
+
|
|
134
|
+
## Stale Anchor Recovery
|
|
135
|
+
|
|
136
|
+
HashPilot has **auto-recovery** for stale anchors. When the file has changed since the hash was computed, `replace-hash` auto-recovers by applying the edit to the current content and returning `"retries": 1`. This is always safe for full-file replaces.
|
|
137
|
+
|
|
138
|
+
If auto-recovery fails or is disabled:
|
|
139
|
+
1. Re-read the file: `hashpilot read-many <file>`
|
|
140
|
+
2. Get the new hash from the response
|
|
141
|
+
3. Retry `replace-hash` with the updated hash
|
|
142
|
+
|
|
143
|
+
The native `hashpilot_replace_hash` tool surfaces stale-anchor status in its response details (`details.stale`), and the extension handles the result accordingly.
|
|
144
|
+
|
|
145
|
+
## Telemetry
|
|
146
|
+
|
|
147
|
+
All operations are logged to `~/.agentic-tools/logs/telemetry.jsonl`.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
hashpilot telemetry summary # Operation counts and timing
|
|
151
|
+
hashpilot telemetry show -n 50 # Last 50 events
|
|
152
|
+
hashpilot telemetry health -w 7 # Health report with per-language stats and warnings
|
|
153
|
+
hashpilot telemetry health -w 7 --trend # Compare to previous window
|
|
154
|
+
hashpilot telemetry sessions # List session-level summaries
|
|
155
|
+
hashpilot telemetry export --from 2026-01-01 # Export events as NDJSON
|
|
156
|
+
hashpilot telemetry prune --older-than 30 # Delete old rotated files
|
|
157
|
+
hashpilot telemetry clear # Clear log
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## When to Use HashPilot Tools vs Raw Commands
|
|
161
|
+
|
|
162
|
+
| Task | Use HashPilot | Use Direct |
|
|
163
|
+
|------|--------------|------------|
|
|
164
|
+
| Edit existing TS/JS/Python/Go/Rust files | ✅ ast commands | ❌ |
|
|
165
|
+
| Edit any file with hash safety | ✅ replace-hash | ❌ |
|
|
166
|
+
| Rename symbols across files | ✅ ast rename-symbol | ❌ |
|
|
167
|
+
| Add/remove imports | ✅ ast add-import / remove-import | ❌ |
|
|
168
|
+
| Replace function body | ✅ ast replace-body | ❌ |
|
|
169
|
+
| Batch read multiple files | ✅ hashpilot_read | ❌ |
|
|
170
|
+
| Verify changes | ✅ hashpilot_verify | ❌ |
|
|
171
|
+
| Create new files | ❌ | ✅ raw write |
|
|
172
|
+
| Delete files/dirs | ❌ | ✅ bash |
|
|
173
|
+
| Move/rename files | ❌ | ✅ bash |
|
|
174
|
+
| Simple one-line edits | optional | ✅ direct edit |
|
|
175
|
+
| Single-file exploration | optional | ✅ direct read |
|
|
176
|
+
|
|
177
|
+
## Key Benefits
|
|
178
|
+
|
|
179
|
+
1. **Reduced token usage** — Hash anchoring eliminates line-counting and re-reading
|
|
180
|
+
2. **Fewer retries** — Stale anchor detection catches conflicts before corruption
|
|
181
|
+
3. **Structured output** — JSON responses parse easily in agent logic
|
|
182
|
+
4. **Verification batching** — One command to run all checks
|
|
183
|
+
5. **Audit trail** — Telemetry logs every operation for debugging
|
|
184
|
+
6. **Native Pi integration** — Custom tools appear in Pi's tool system with proper schemas and guidelines
|
|
185
|
+
|
|
186
|
+
## Troubleshooting
|
|
187
|
+
|
|
188
|
+
| Issue | Solution |
|
|
189
|
+
|-------|----------|
|
|
190
|
+
| `hashpilot: command not found` | Add `~/.agentic-tools/bin` to PATH in `~/.bashrc` |
|
|
191
|
+
| `Module not found` errors | Run `bun install` in `~/.agentic-tools/structured-editing/` |
|
|
192
|
+
| Tree-sitter errors | `bun add tree-sitter tree-sitter-typescript` in the structured-editing dir |
|
|
193
|
+
| Pi extension not loading | Check `~/.pi/agent/extensions/hashpilot.ts` exists and has no syntax errors |
|
|
194
|
+
| Tools not appearing | Restart Pi; check `~/.pi/agent/settings.json` doesn't disable extensions |
|
|
195
|
+
| Stale hash errors | Re-read the file with `read-many` or `read-hash` and use the fresh hash |
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bigknoxy/hashpilot",
|
|
3
|
+
"version": "4.6.3",
|
|
4
|
+
"description": "HashPilot — Global Tool-Agnostic Structured Editing Core for Coding Agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"bun": ">=1.2.0"
|
|
8
|
+
},
|
|
9
|
+
"bin": {
|
|
10
|
+
"hashpilot": "./src/cli-node.cjs"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "bun test",
|
|
14
|
+
"build": "bun build src/cli.ts --outdir dist --target bun",
|
|
15
|
+
"install-cli": "bash scripts/install-cli.sh",
|
|
16
|
+
"semantic-release": "semantic-release",
|
|
17
|
+
"gen:cli-quickref": "bun run scripts/gen-cli-quickref.ts",
|
|
18
|
+
"gen:cli-quickref:check": "bun run scripts/gen-cli-quickref.ts --check",
|
|
19
|
+
"lint:roadmap": "bun run scripts/roadmap-lint.ts",
|
|
20
|
+
"lint:docs": "bun run gen:cli-quickref:check && bun run lint:roadmap",
|
|
21
|
+
"bench": "bun run bench/runner.ts"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"src/",
|
|
25
|
+
"scripts/",
|
|
26
|
+
"templates/",
|
|
27
|
+
"docs/",
|
|
28
|
+
"LICENSE",
|
|
29
|
+
"package.json",
|
|
30
|
+
"tsconfig.json"
|
|
31
|
+
],
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/bigknoxy/HashPilot.git"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"structured-editing",
|
|
38
|
+
"coding-agents",
|
|
39
|
+
"tree-sitter",
|
|
40
|
+
"claude",
|
|
41
|
+
"opencode",
|
|
42
|
+
"pi"
|
|
43
|
+
],
|
|
44
|
+
"author": "bigknoxy",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/bigknoxy/HashPilot/issues"
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://github.com/bigknoxy/HashPilot#readme",
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"chalk": "^6.0.0",
|
|
55
|
+
"commander": "^15.0.0",
|
|
56
|
+
"glob": "^13.0.6",
|
|
57
|
+
"tree-sitter": "^0.25.1",
|
|
58
|
+
"tree-sitter-go": "0.25.0",
|
|
59
|
+
"tree-sitter-javascript": "0.25.0",
|
|
60
|
+
"tree-sitter-python": "^0.25.0",
|
|
61
|
+
"tree-sitter-rust": "^0.24.0",
|
|
62
|
+
"tree-sitter-typescript": "^0.23.2"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@semantic-release/changelog": "^7.0.0",
|
|
66
|
+
"@semantic-release/commit-analyzer": "^13.0.0",
|
|
67
|
+
"@semantic-release/git": "^11.0.1",
|
|
68
|
+
"@semantic-release/github": "^12.0.9",
|
|
69
|
+
"@semantic-release/npm": "^13.1.5",
|
|
70
|
+
"@semantic-release/release-notes-generator": "^14.0.0",
|
|
71
|
+
"@types/bun": "^1.1.0",
|
|
72
|
+
"@types/node": "^26.4.0",
|
|
73
|
+
"conventional-changelog-conventionalcommits": "^10.4.0",
|
|
74
|
+
"fast-check": "^4.9.0",
|
|
75
|
+
"semantic-release": "^25.0.9"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Build the GitHub Pages site into site/.
|
|
3
|
+
#
|
|
4
|
+
# The Pages workflow used to publish the repository root, which served internal
|
|
5
|
+
# planning documents (M5_PLAN.md, M6_AUTOPLAN_REVIEW.md, AUDIT-2026-08.md),
|
|
6
|
+
# workflow files, and the whole source tree under the docs domain (#49). The
|
|
7
|
+
# site is now an explicit allowlist: anything not named here is not published.
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
11
|
+
OUT="$ROOT/site"
|
|
12
|
+
|
|
13
|
+
rm -rf "$OUT"
|
|
14
|
+
mkdir -p "$OUT/docs"
|
|
15
|
+
|
|
16
|
+
cp "$ROOT/index.html" "$OUT/index.html"
|
|
17
|
+
cp "$ROOT/README.md" "$OUT/README.md"
|
|
18
|
+
cp "$ROOT/LICENSE" "$OUT/LICENSE"
|
|
19
|
+
|
|
20
|
+
# Docs the landing page links to, or that are written for public consumption.
|
|
21
|
+
PUBLIC_DOCS=(
|
|
22
|
+
ADAPTER-CONTRACT.md
|
|
23
|
+
ARCHITECTURE.md
|
|
24
|
+
CLI-QUICKREF.md
|
|
25
|
+
COMPETITIVE-ANALYSIS.md
|
|
26
|
+
INSTALL.md
|
|
27
|
+
INTEGRATION-CLAUDE.md
|
|
28
|
+
INTEGRATION-MCP.md
|
|
29
|
+
INTEGRATION-OPENCODE.md
|
|
30
|
+
INTEGRATION-PI.md
|
|
31
|
+
)
|
|
32
|
+
for doc in "${PUBLIC_DOCS[@]}"; do
|
|
33
|
+
cp "$ROOT/docs/$doc" "$OUT/docs/$doc"
|
|
34
|
+
done
|
|
35
|
+
|
|
36
|
+
# Jekyll would otherwise skip files and directories beginning with an underscore.
|
|
37
|
+
touch "$OUT/.nojekyll"
|
|
38
|
+
|
|
39
|
+
echo "Built site/ with $(find "$OUT" -type f | wc -l | tr -d ' ') files"
|