@pipemd-core/pipemd 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI_SETUP_PIPEMD.md +184 -0
- package/CHANGELOG.md +47 -0
- package/LICENSE +15 -0
- package/README.md +535 -0
- package/dist/index.js +6647 -0
- package/dist/plugins/opencode-server.js +235 -0
- package/dist/plugins/opencode-tui.js +914 -0
- package/dist/templates/agent-decision-tree.md +113 -0
- package/dist/templates/static-rules.md +7 -0
- package/package.json +68 -0
- package/scripts/C-CPP/architecture/arch.sh +229 -0
- package/scripts/C-CPP/lib/limit.sh +146 -0
- package/scripts/C-CPP/project/class-diagram.sh +96 -0
- package/scripts/C-CPP/project/cmake-targets.sh +68 -0
- package/scripts/C-CPP/project/deps.sh +44 -0
- package/scripts/C-CPP/project/find-todos.sh +6 -0
- package/scripts/C-CPP/project/include-graph.sh +110 -0
- package/scripts/C-CPP/project/interfaces.sh +108 -0
- package/scripts/C-CPP/project/tree.sh +5 -0
- package/scripts/C-CPP/quality/lint.sh +14 -0
- package/scripts/C-CPP/quality/test-summary.sh +22 -0
- package/scripts/C-CPP/quality/type-check.sh +26 -0
- package/scripts/DevOps/architecture/arch.sh +186 -0
- package/scripts/DevOps/devops/aws-context.sh +34 -0
- package/scripts/DevOps/devops/docker-stats.sh +42 -0
- package/scripts/DevOps/devops/k8s-unhealthy.sh +41 -0
- package/scripts/DevOps/devops/tf-state.sh +65 -0
- package/scripts/DevOps/lib/limit.sh +143 -0
- package/scripts/Generic/architecture/arch.sh +570 -0
- package/scripts/Generic/lib/limit.sh +140 -0
- package/scripts/Go/architecture/arch.sh +79 -0
- package/scripts/Go/lib/limit.sh +142 -0
- package/scripts/Go/project/deps.sh +35 -0
- package/scripts/Go/project/find-todos.sh +6 -0
- package/scripts/Go/project/go-interfaces.sh +18 -0
- package/scripts/Go/project/go-packages.sh +28 -0
- package/scripts/Go/project/tree.sh +5 -0
- package/scripts/Go/quality/lint.sh +16 -0
- package/scripts/Go/quality/test-summary.sh +16 -0
- package/scripts/Go/quality/type-check.sh +16 -0
- package/scripts/Node-TypeScript/api/express-routes.sh +14 -0
- package/scripts/Node-TypeScript/api/nest-controllers.sh +18 -0
- package/scripts/Node-TypeScript/architecture/arch.sh +174 -0
- package/scripts/Node-TypeScript/frontend/angular-routes.sh +15 -0
- package/scripts/Node-TypeScript/frontend/nextjs-app-router.sh +13 -0
- package/scripts/Node-TypeScript/frontend/react-components.sh +20 -0
- package/scripts/Node-TypeScript/lib/limit.sh +146 -0
- package/scripts/Node-TypeScript/project/deps.sh +15 -0
- package/scripts/Node-TypeScript/project/find-todos.sh +6 -0
- package/scripts/Node-TypeScript/quality/lint.sh +10 -0
- package/scripts/Node-TypeScript/quality/test-summary.sh +39 -0
- package/scripts/Node-TypeScript/quality/type-check.sh +10 -0
- package/scripts/Python/api/fastapi-routes.sh +12 -0
- package/scripts/Python/architecture/arch.sh +220 -0
- package/scripts/Python/db/django-models.sh +12 -0
- package/scripts/Python/db/sqlalchemy.sh +17 -0
- package/scripts/Python/lib/limit.sh +144 -0
- package/scripts/Python/project/deps.sh +28 -0
- package/scripts/Python/project/find-todos.sh +6 -0
- package/scripts/Python/quality/lint.sh +13 -0
- package/scripts/Python/quality/test-summary.sh +11 -0
- package/scripts/Python/quality/type-check.sh +10 -0
- package/scripts/Rust/architecture/arch.sh +176 -0
- package/scripts/Rust/lib/limit.sh +142 -0
- package/scripts/Rust/project/cargo-deps.sh +42 -0
- package/scripts/Rust/project/cargo-features.sh +26 -0
- package/scripts/Rust/project/find-todos.sh +6 -0
- package/scripts/Rust/project/tree.sh +5 -0
- package/scripts/Rust/quality/lint.sh +16 -0
- package/scripts/Rust/quality/test-summary.sh +16 -0
- package/scripts/Rust/quality/type-check.sh +16 -0
- package/scripts/Shared/api/express-routes.sh +11 -0
- package/scripts/Shared/api/fastapi-routes.sh +10 -0
- package/scripts/Shared/api/nest-controllers.sh +22 -0
- package/scripts/Shared/architecture/normalize.sh +178 -0
- package/scripts/Shared/crew/crew.sh +15 -0
- package/scripts/Shared/db/django-models.sh +11 -0
- package/scripts/Shared/db/prisma.sh +33 -0
- package/scripts/Shared/db/sqlalchemy.sh +12 -0
- package/scripts/Shared/frontend/angular-routes.sh +11 -0
- package/scripts/Shared/frontend/nextjs-app-router.sh +13 -0
- package/scripts/Shared/frontend/react-components.sh +11 -0
- package/scripts/Shared/git/diff-stat.sh +6 -0
- package/scripts/Shared/git/git-branch.sh +16 -0
- package/scripts/Shared/git/git-log.sh +6 -0
- package/scripts/Shared/git/git-status.sh +6 -0
- package/scripts/Shared/lib/limit.sh +144 -0
- package/scripts/Shared/project/compose-md.sh +182 -0
- package/scripts/Shared/project/deps.sh +69 -0
- package/scripts/Shared/project/find-todos.sh +6 -0
- package/scripts/Shared/project/tree.sh +5 -0
- package/scripts/Shared/quality/lint.sh +81 -0
- package/scripts/Shared/quality/test-summary.sh +103 -0
- package/scripts/Shared/quality/type-check.sh +114 -0
- package/scripts/copy-plugins.mjs +4 -0
- package/scripts/copy-templates.mjs +5 -0
package/README.md
ADDED
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<img src="PipeMD.jpg" alt="PipeMD Banner" width="100%" style="border-radius: 8px; max-width: 800px;" />
|
|
4
|
+
</picture>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<h1 align="center">PipeMD</h1>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<strong>The Dynamic Context Harness for AI Coding Agents.</strong><br>
|
|
11
|
+
<em>Never let Claude, Cursor, or Aider hallucinate on stale project state again.</em>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<a href="#the-magic-render-on-read"><img src="https://img.shields.io/badge/Architecture-Render--on--Read%20%2B%20Smart%20Injection-blue?style=flat-square" alt="Architecture"></a>
|
|
16
|
+
<a href="#prompt-cache-optimization"><img src="https://img.shields.io/badge/Prompt%20Caching-Optimized-success?style=flat-square" alt="Prompt Cache Optimized"></a>
|
|
17
|
+
<a href="#compatibility"><img src="https://img.shields.io/badge/Works%20With-Claude%20%7C%20Cursor%20%7C%20Aider%20%7C%20Gemini-orange?style=flat-square" alt="Works With"></a>
|
|
18
|
+
<a href="https://opensource.org/licenses/ISC"><img src="https://img.shields.io/badge/License-ISC-purple?style=flat-square" alt="License"></a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 🛑 The Problem: Stale Context & Git Churn
|
|
24
|
+
|
|
25
|
+
AI coding agents need to know your current project state (git status, lint errors, TODOs) to be effective.
|
|
26
|
+
Currently, you have two bad options:
|
|
27
|
+
1. **Static Files:** You give the AI a `README.md` or `CONTEXT.md`. It goes stale after your first commit. The AI hallucinates.
|
|
28
|
+
2. **Automated Scripts:** You run a script to update `CONTEXT.md` continuously. Your `git status` is ruined, merge conflicts run rampant, and your file history is a mess.
|
|
29
|
+
|
|
30
|
+
## ⚡ The Solution: PipeMD
|
|
31
|
+
|
|
32
|
+
PipeMD uses a brilliantly simple OS-level trick: **Named Pipes**.
|
|
33
|
+
|
|
34
|
+
It creates an `AGENTS.md` file in your root directory that is actually a `mkfifo` pipe. When your AI agent attempts to read it, PipeMD intercepts the read, executes your bash scripts concurrently, injects real-time project state into a clean template, and streams it straight to the AI.
|
|
35
|
+
|
|
36
|
+
* **Zero Git Churn:** The template is clean. The live output is completely ephemeral.
|
|
37
|
+
* **Always Fresh:** The AI gets up-to-the-millisecond data *only* exactly when it reads.
|
|
38
|
+
* **Secure:** Commands run from your own `config.yml` — no need to grant the AI unsafe terminal execution permissions.
|
|
39
|
+
|
|
40
|
+
But named pipes only solve half the problem: most AI agents read their context file only once at session start, then cache it. PipeMD's **Smart Context Injection** solves this by installing lightweight hooks that inject fresh, scoped context directly into the agent's working memory on every tool call — crew locks before edits, file errors before edits, validation results after edits, and status updates during idle time.
|
|
41
|
+
|
|
42
|
+
PipeMD is a render-on-read daemon that uses OS-level named pipes (mkfifo) to serve real-time project context to
|
|
43
|
+
AI coding agents. The key innovation: the file the AI reads (AGENTS.md or AI_CONTEXT.md) is itself a named pipe --
|
|
44
|
+
when the AI opens it, the daemon intercepts the read, executes all configured shell commands concurrently,
|
|
45
|
+
assembles the output into a Markdown template, prepends any base instructions (from `.pipemd/base.md`), and streams it back.
|
|
46
|
+
|
|
47
|
+
Data flow:
|
|
48
|
+
|
|
49
|
+
The Full Data Flow
|
|
50
|
+
Agent tool call
|
|
51
|
+
→ Harness hook fires (Claude: settings.json entry, OpenCode: plugin handler, Gemini: settings.json entry)
|
|
52
|
+
→ `pmd inject --trigger <X> --file <Y> --session <Z> --format <F>`
|
|
53
|
+
→ `resolveInjections()` in injection-engine.ts
|
|
54
|
+
→ Loads injection.yml config
|
|
55
|
+
→ Gets rules for trigger
|
|
56
|
+
→ For each rule, runs the resolver (crew-status, file-errors, git-context, etc.)
|
|
57
|
+
→ `checkInjectionStatus()` in dedup.ts -- checks `.pipemd/cache/injected/<session>.json`
|
|
58
|
+
→ If "unchanged": skip (no payload returned)
|
|
59
|
+
→ If "new"/"changed": `recordInjection()` -- writes hash to `.pipemd/cache/injected/<session>.json`
|
|
60
|
+
→ Returns `InjectionPayload[]`
|
|
61
|
+
→ `bumpInjectStats()` in statusline-data.ts -- writes `.pipemd/.inject-stats.json`
|
|
62
|
+
→ Output in requested format (plain, claude-hook JSON, gemini JSON)
|
|
63
|
+
→ OpenCode only (plugin side):
|
|
64
|
+
→ Also calls `pushEvent()` which writes `.pipemd/.tui-stats.json`
|
|
65
|
+
→ TUI panel reads `.pipemd/.tui-stats.json` every 2s
|
|
66
|
+
→ `pmd statusline` (called by Claude Code automatically, or Gemini AfterAgent):
|
|
67
|
+
→ Reads `.pipemd/.inject-stats.json`, `.pipemd/.status.json`, `.pipemd/.crew-status.json`
|
|
68
|
+
→ Renders status line to developer
|
|
69
|
+
|
|
70
|
+
.pipemd/base.md (committed, agent's own instructions)
|
|
71
|
+
─────────────────────────────────────────────────────┐
|
|
72
|
+
│
|
|
73
|
+
.pipemd/template.md (committed, static) │
|
|
74
|
+
→ daemon reads tags like <!-- pmd: git-status --> │
|
|
75
|
+
→ runs commands concurrently via Promise.allSettled │
|
|
76
|
+
→ assembles rendered Markdown │
|
|
77
|
+
→ composes: base + "---\n\n<!-- pmd-context -->\n" + rendered template
|
|
78
|
+
→ serves via named pipe (AGENTS.md) on read │
|
|
79
|
+
|
|
80
|
+
Two operational modes:
|
|
81
|
+
|
|
82
|
+
1. Pipe Mode (macOS, Linux, WSL): Uses mkfifo to create named pipes. The root context file IS the pipe. Zero git
|
|
83
|
+
churn. Supports bidirectional write-back — edits above `<!-- pmd-context -->` are saved to `base.md`,
|
|
84
|
+
edits outside `<!-- pmd: -->` blocks in the template section are de-rendered and saved back to `template.md`.
|
|
85
|
+
|
|
86
|
+
2. Legacy Mode (native Windows fallback): Uses chokidar to watch template.md, writes rendered output to a regular
|
|
87
|
+
file marked read-only (0o444). This causes git churn. Also supports write-back via file watcher.
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## ✨ Features: Built for Vibe Coding
|
|
93
|
+
|
|
94
|
+
- **🔌 Universal AI Compatibility:** Claude Code, Gemini CLI, OpenCode, Cursor, Aider—it doesn't matter. If your AI agent can read a Markdown file, it works flawlessly with PipeMD. No plugins required.
|
|
95
|
+
- **🏗️ Architecture Maps:** PipeMD generates live Mermaid dependency graphs (`graph TD`) for 7 ecosystems. AI agents get an instant mental model of your project's module structure — no need to read dozens of files to understand how things connect.
|
|
96
|
+
- **🦾 Self-Improving Context:** Because your fetch scripts and templates live as plain text in `.pipemd/`, you can simply ask your AI to *edit its own context harness* to feed itself better data on the fly. Meta-coding at its finest.
|
|
97
|
+
- **🛡️ Non-Destructive Setup:** Worried about losing your carefully crafted system prompts? `pmd init` is completely non-destructive. If an `AGENTS.md` or `AI_CONTEXT.md` already exists, PipeMD saves your instructions to `.pipemd/base.md` and keeps them separate from the template. Nothing gets overwritten.
|
|
98
|
+
- **👻 Ephemeral & Git-Clean:** Output is generated in memory and streamed via the named pipe. The target file is automatically `.gitignored` and vanishes the second you stop the daemon. Zero commit noise.
|
|
99
|
+
- **🧠 Prompt Cache Optimized:** Static rules stay at the top; highly volatile data (like `git status`) is anchored to the bottom. Your LLM prefix cache stays warm, giving you instant responses and saving massive amounts of tokens.
|
|
100
|
+
- **🏎️ Concurrent & Fail-Safe:** Data-gathering scripts run concurrently so your AI isn't left waiting. Built-in 10-second timeouts and isolated failures mean one broken script won't crash your entire context stream.
|
|
101
|
+
- **🤖 Smart Scaffolding:** Run `pmd init` and watch it automatically detect your ecosystem (Node, Python, TS, etc.) to scaffold the exact bash scripts you need to hit flow state immediately.
|
|
102
|
+
- **🎯 Smart Context Injection:** Goes beyond render-on-read. Hooks inject fresh, scoped context into your agent's working memory on every tool call — crew locks, file errors, validation results — so the agent always knows the current state even mid-session.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 🚀 Quick Start
|
|
107
|
+
|
|
108
|
+
Get your dynamic context harness running in under 60 seconds:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# Option 1: Global Install
|
|
112
|
+
npm install -g pipemd
|
|
113
|
+
pmd init
|
|
114
|
+
pmd start
|
|
115
|
+
|
|
116
|
+
# Option 2: Run via NPX (No global install required)
|
|
117
|
+
npx pipemd init
|
|
118
|
+
npx pipemd start
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
> **Bash Required:** PipeMD's context scripts rely on a Bash environment. Windows users must use WSL or Git Bash.
|
|
122
|
+
|
|
123
|
+
*The setup wizard will auto-detect your ecosystem and configure the optimal `.pipemd/template.md` and context scripts for your workspace.*
|
|
124
|
+
|
|
125
|
+
*The setup wizard will also ask how to deliver context — **Active** (recommended for most agents) or **Passive** (for Cursor, Aider, or CI).*
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 🧠 How the Magic Works
|
|
130
|
+
|
|
131
|
+
PipeMD bridges the gap between your static developer notes and the dynamic reality of your repository.
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
┌────────────────────────────────────────────────────────┐
|
|
135
|
+
│ 1. You edit: .pipemd/template.md │
|
|
136
|
+
│ (Clean, committed to Git, your source of truth) │
|
|
137
|
+
│ │
|
|
138
|
+
│ ## Rules │
|
|
139
|
+
│ Never use `any` in TypeScript. │
|
|
140
|
+
│ │
|
|
141
|
+
│ ## Live Diff │
|
|
142
|
+
│ <!-- pmd: diff --> <── PipeMD placeholder │
|
|
143
|
+
└────────────────────────┬───────────────────────────────┘
|
|
144
|
+
│
|
|
145
|
+
(Agent reads AGENTS.md from root)
|
|
146
|
+
│
|
|
147
|
+
┌────────────────────────▼───────────────────────────────┐
|
|
148
|
+
│ 2. PipeMD Daemon (Intercepts read) │
|
|
149
|
+
│ Prepends base.md + separator, renders template... │
|
|
150
|
+
└────────────────────────┬───────────────────────────────┘
|
|
151
|
+
│
|
|
152
|
+
┌────────────────────────▼───────────────────────────────┐
|
|
153
|
+
│ 3. The AI receives: (Streamed instantly) │
|
|
154
|
+
│ │
|
|
155
|
+
│ [Base instructions from .pipemd/base.md] │
|
|
156
|
+
│ │
|
|
157
|
+
│ --- │
|
|
158
|
+
│ │
|
|
159
|
+
│ <!-- pmd-context --> │
|
|
160
|
+
│ │
|
|
161
|
+
│ ## Rules │
|
|
162
|
+
│ Never use `any` in TypeScript. │
|
|
163
|
+
│ │
|
|
164
|
+
│ ## Live Diff │
|
|
165
|
+
│ + const daemon = new PipeMD(); │
|
|
166
|
+
│ - const daemon = null; │
|
|
167
|
+
└────────────────────────────────────────────────────────┘
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
> **Note for Windows Users:** Native Windows lacks `mkfifo`. PipeMD falls back to **Legacy Mode**, gracefully watching your template and writing read-only (`0o444`) updates.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## 🧠 Smart Context Injection
|
|
175
|
+
|
|
176
|
+
Most AI coding agents load their context file once at session start and never re-read it. This means even with named pipes serving fresh data, the agent works with stale information for the entire session.
|
|
177
|
+
|
|
178
|
+
PipeMD's Smart Context Injection solves this by installing per-harness hooks that inject relevant context **on every tool call**, scoped to what the agent is about to do:
|
|
179
|
+
|
|
180
|
+
```text
|
|
181
|
+
Agent is about to READ a file:
|
|
182
|
+
→ Hook fires → "Crew: this file is unclaimed. Safe to read."
|
|
183
|
+
|
|
184
|
+
Agent is about to EDIT src/foo.ts:
|
|
185
|
+
→ Hook fires → "File src/foo.ts: claimed by OpenCode (cr_abc123) 45s ago
|
|
186
|
+
Type-check: 2 errors in this file
|
|
187
|
+
Last edit: you, 2 minutes ago"
|
|
188
|
+
|
|
189
|
+
Agent just EDITED src/foo.ts:
|
|
190
|
+
→ Background validation triggers → next tool call shows:
|
|
191
|
+
"After your edit to src/foo.ts: 1 error remaining (was 2)"
|
|
192
|
+
|
|
193
|
+
Agent has been idle for 10 seconds:
|
|
194
|
+
→ "Crew: Gemini session joined. Git: 1 new uncommitted file."
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Three Delivery Modes
|
|
198
|
+
|
|
199
|
+
During `pmd init`, choose how PipeMD delivers context to your agent:
|
|
200
|
+
|
|
201
|
+
| Mode | How it works | Best for |
|
|
202
|
+
|------|-------------|----------|
|
|
203
|
+
| **Active** (recommended) | Hooks installed. Fresh context injected on every tool call. Zero config. | Claude Code, OpenCode, Gemini CLI |
|
|
204
|
+
| **Passive** | Context rendered to file/pipe. Agent reads at session start. No hooks. | Cursor, Aider, CI/CD |
|
|
205
|
+
| **Expert** | Full control over injection rules via `.pipemd/injection.yml`. | Teams with custom workflows |
|
|
206
|
+
|
|
207
|
+
### What gets injected
|
|
208
|
+
|
|
209
|
+
Active mode injects context at four moments:
|
|
210
|
+
|
|
211
|
+
| Trigger | Sources |
|
|
212
|
+
|---------|---------|
|
|
213
|
+
| **Before Read** | Crew status (who's working, any conflicts) |
|
|
214
|
+
| **Before Edit** | Crew locks for target file, lint/type errors for target file, git context |
|
|
215
|
+
| **After Edit** | Async validation: run lint + type-check on edited file, deliver results on next call |
|
|
216
|
+
| **On Idle** | Crew status changes, git delta since last check |
|
|
217
|
+
|
|
218
|
+
All injection is **deduplicated** — unchanged data is skipped, saving tokens. Results are cached with per-source TTL for sub-5ms hook latency.
|
|
219
|
+
|
|
220
|
+
### The injection.yml file (Expert mode)
|
|
221
|
+
|
|
222
|
+
```yaml
|
|
223
|
+
# .pipemd/injection.yml — customize injection rules
|
|
224
|
+
delivery: expert
|
|
225
|
+
rules:
|
|
226
|
+
before-edit:
|
|
227
|
+
- source: crew-locks
|
|
228
|
+
scope: target-file
|
|
229
|
+
- source: file-errors
|
|
230
|
+
scope: target-file
|
|
231
|
+
max-lines: 5
|
|
232
|
+
after-edit:
|
|
233
|
+
- source: validate-file
|
|
234
|
+
scope: target-file
|
|
235
|
+
async: true
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## 🛠️ Commands
|
|
241
|
+
|
|
242
|
+
PipeMD is designed to stay out of your way.
|
|
243
|
+
|
|
244
|
+
| Command | Description |
|
|
245
|
+
|---------|-------------|
|
|
246
|
+
| `pmd init` | **Interactive setup:** Auto-detects ecosystem + harnesses, scaffolds the template, scripts, and `.gitignore` entries. `--headless` for CI. |
|
|
247
|
+
| `pmd start` | **Spawns daemon:** Creates the named pipe(s) and silently serves context on read. Daemon detaches and stores its PID in `.pipemd/.daemon.pid`. |
|
|
248
|
+
| `pmd stop` | **Kills daemon:** Safely removes all pipes and cleans up the PID file. |
|
|
249
|
+
| `pmd restart` | **Stop + start:** Reloads `config.yml` (use after editing config). |
|
|
250
|
+
| `pmd status` | **System health:** Shows active daemon PID, watched files, active pipes, and recent log lines. |
|
|
251
|
+
| `pmd run` | **One-shot render:** Renders the resolved template to `stdout` or a file (`-o`). No daemon required — ideal for CI and pre-commit hooks. |
|
|
252
|
+
| `pmd refresh` | **Sync scripts:** Pulls newer bundled scripts into `.pipemd/scripts/`, offers newly added ones (e.g. **Crew Activity**), and rewrites `config.yml`. |
|
|
253
|
+
| `pmd doctor` | **Diagnose:** Checks for `mkfifo`, stale PIDs, missing scripts, and config drift. |
|
|
254
|
+
| `pmd crew` | **Multi-harness coordination:** Register agents, claim files, surface conflicts (see below). |
|
|
255
|
+
| `pmd uninstall` | **Clean removal:** Restores the original context file and strips PipeMD artifacts. |
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 👥 Crew: Coordinating Parallel Agents
|
|
260
|
+
|
|
261
|
+
When several AI harnesses work the same repo at once (e.g. OpenCode with 8
|
|
262
|
+
sub-agents plus a Claude CLI session), they edit blind to each other. PipeMD
|
|
263
|
+
Crew turns the live context file into a shared awareness layer.
|
|
264
|
+
|
|
265
|
+
The model is **Harness → Coordinator → sub-agents**: one coordinator per
|
|
266
|
+
harness, with PipeMD as the neutral meta-coordinator that renders the union.
|
|
267
|
+
|
|
268
|
+
| Command | Description |
|
|
269
|
+
|---------|-------------|
|
|
270
|
+
| `pmd crew join` | Register this agent (`--role coordinator\|worker`, `--label`). |
|
|
271
|
+
| `pmd crew claim <file…>` | Mark files as being worked on (`--note "<task>"`). |
|
|
272
|
+
| `pmd crew release <file…>` | Release claims (`--all` for everything). |
|
|
273
|
+
| `pmd crew note "<text>"` | Post the current task/status. |
|
|
274
|
+
| `pmd crew status` | Show the live crew tree. |
|
|
275
|
+
| `pmd crew leave` | Deregister this agent. |
|
|
276
|
+
| `pmd crew install-hooks` | Auto-wire harness hooks so edits self-report. |
|
|
277
|
+
|
|
278
|
+
**Two signal layers.** *Passive* (always on, zero cooperation): observed git
|
|
279
|
+
churn and running harness processes. *Active* (opt-in): the `pmd crew` CLI,
|
|
280
|
+
fired automatically by `pmd crew install-hooks`:
|
|
281
|
+
|
|
282
|
+
| Harness | Events | Wired into |
|
|
283
|
+
|---------|---------|------------|
|
|
284
|
+
| Claude Code | `SessionStart` → join, `PreToolUse` → heartbeat, `PostToolUse` → claim, `SubagentStart/Stop` → worker lifecycle, `SessionEnd` → leave, `statusLine` → live PipeMD statusline | `.claude/settings.json` |
|
|
285
|
+
| OpenCode | `tool.execute.before` → heartbeat, `tool.execute.after` → claim, `session.idle` → keep-alive | `.opencode/plugin/pmd-crew.js` |
|
|
286
|
+
| Gemini CLI | `BeforeTool` → heartbeat, `AfterTool` → claim, `SessionStart`/`AfterAgent` → live PipeMD statusline via hook `systemMessage` (v0.26+) | `.gemini/settings.json` |
|
|
287
|
+
| Cursor / Aider / others | no edit-event API | injected Coordination Protocol text |
|
|
288
|
+
|
|
289
|
+
The crew block (`<!-- pmd: crew -->`) is rendered into every harness's context
|
|
290
|
+
file, so a `⚠️ CONFLICT` — two agents claiming the same file — appears for
|
|
291
|
+
everyone within one broadcast cycle. Add it via `pmd refresh` (select **Crew
|
|
292
|
+
Activity**) or pick it during `pmd init`.
|
|
293
|
+
|
|
294
|
+
**Claude Code statusline.** OpenCode gets a live TUI sidebar panel; Claude Code
|
|
295
|
+
has no pluggable panel, so `install-hooks` instead registers a `statusLine` that
|
|
296
|
+
renders the same dev-side state — daemon up/down, crew session count, passive
|
|
297
|
+
agents, file conflicts, context size, injection counts — on a single line at the
|
|
298
|
+
bottom of the Claude Code UI. It is invoked automatically by the harness on every
|
|
299
|
+
update; a pre-existing custom `statusLine` is never overwritten. Preview it any
|
|
300
|
+
time with `pmd statusline --plain`.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## 🏗️ What Gets Generated?
|
|
305
|
+
|
|
306
|
+
PipeMD keeps your root directory pristine. Everything lives in `.pipemd/`.
|
|
307
|
+
|
|
308
|
+
```text
|
|
309
|
+
your-project/
|
|
310
|
+
├── .pipemd/
|
|
311
|
+
│ ├── config.yml # ✅ Committed — pipe routing + script definitions
|
|
312
|
+
│ ├── base.md # ✅ Committed — agent's own instructions (prepended to context)
|
|
313
|
+
│ ├── template.md # ✅ Committed — 📝 edit this! The static wrapper for your context.
|
|
314
|
+
│ ├── scripts/ # ✅ Committed — Bash/Python/Node data-gathering scripts
|
|
315
|
+
│ │ ├── architecture/ # 🏗️ Architecture map (Mermaid graph TD)
|
|
316
|
+
│ │ ├── project/ # Project structure, deps, todos
|
|
317
|
+
│ │ ├── git/ # Git state scripts
|
|
318
|
+
│ │ ├── quality/ # Type checking, linting, tests
|
|
319
|
+
│ │ └── crew/ # Crew coordination block
|
|
320
|
+
│ ├── injection.yml # ✅ Committed — Smart injection rules (active/expert mode)
|
|
321
|
+
│ ├── cache/ # (Gitignored) Per-source render cache for injection
|
|
322
|
+
│ │ ├── sources/ # Cached command outputs with TTL
|
|
323
|
+
│ │ ├── validation/ # Per-file validation results
|
|
324
|
+
│ │ └── injected/ # Per-session dedup records
|
|
325
|
+
│ ├── live/ # (Gitignored) Ephemeral named pipes
|
|
326
|
+
│ ├── crew/ # (Gitignored) Per-agent coordination ledger (JSON)
|
|
327
|
+
│ ├── daemon.log # (Gitignored) Daemon activity log
|
|
328
|
+
│ └── .daemon.pid # (Gitignored) Running daemon's PID
|
|
329
|
+
├── AGENTS.md # (Gitignored) 🏴☠️ The Named Pipe. The AI reads this.
|
|
330
|
+
└── .gitignore # Updated automatically by `pmd init`
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
> Only `config.yml`, `base.md`, `template.md`, and `scripts/` are committed —
|
|
334
|
+
> everything your team needs to reproduce the harness, and nothing ephemeral.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## 🎯 The Template (`.pipemd/template.md`)
|
|
339
|
+
|
|
340
|
+
This is your source of truth. Edit it, commit it, share it with your team. Use `<!-- pmd: command_name -->` to tell the daemon where to inject live data.
|
|
341
|
+
|
|
342
|
+
The served context file is composed of two parts: **base instructions** (from `.pipemd/base.md`) and the **rendered template**. They are separated by `---` + `<!-- pmd-context -->`. AI edits above the separator go back to `base.md`; edits in the template section outside `<!-- pmd: -->` blocks go back to `template.md`.
|
|
343
|
+
|
|
344
|
+
```markdown
|
|
345
|
+
# 🏴☠️ AI Context — powered by PipeMD
|
|
346
|
+
|
|
347
|
+
> **🤖 PipeMD Context File**
|
|
348
|
+
>
|
|
349
|
+
> This file is maintained by PipeMD. It refreshes automatically.
|
|
350
|
+
>
|
|
351
|
+
> - Content inside `<!-- pmd: -->` blocks is **read-only** — the daemon overwrites it every cycle.
|
|
352
|
+
> - Everything else is **yours to edit**. Edits persist via bidirectional write-back.
|
|
353
|
+
> - Edits above `<!-- pmd-context -->` route to `.pipemd/base.md`. Edits below it route to `.pipemd/template.md`.
|
|
354
|
+
> - For full details, read `.pipemd/AI_SETUP_PIPEMD.md`.
|
|
355
|
+
|
|
356
|
+
## 🏗️ Architecture
|
|
357
|
+
<!-- pmd: arch -->
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
```
|
|
361
|
+
<!-- /pmd -->
|
|
362
|
+
|
|
363
|
+
## 📁 Project Structure
|
|
364
|
+
<!-- pmd: tree -->
|
|
365
|
+
<!-- /pmd -->
|
|
366
|
+
|
|
367
|
+
## 📝 TODOs
|
|
368
|
+
<!-- pmd: todos -->
|
|
369
|
+
<!-- /pmd -->
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
## 🚨 Volatile State
|
|
373
|
+
<!-- pmd: diff-stat -->
|
|
374
|
+
<!-- /pmd -->
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
*(Notice how volatile data like `diff-stat` is placed at the bottom? This ensures your LLM Prompt Cache hits for the top 90% of the document!)*
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## ⚙️ Configuration (`config.yml`)
|
|
382
|
+
|
|
383
|
+
The `config.yml` connects the `pmd:` tags in your template to the actual scripts that fetch the data.
|
|
384
|
+
|
|
385
|
+
```yaml
|
|
386
|
+
version: "1.0"
|
|
387
|
+
|
|
388
|
+
# ⚠️ Security Warning: PipeMD executes the commands below exactly as written.
|
|
389
|
+
# Do not run PipeMD in an untrusted repository.
|
|
390
|
+
|
|
391
|
+
# Optional: Base instructions file, prepended to the served context.
|
|
392
|
+
# AI edits to the base section are written back here.
|
|
393
|
+
base: ".pipemd/base.md"
|
|
394
|
+
|
|
395
|
+
commands:
|
|
396
|
+
arch: "bash .pipemd/scripts/architecture/arch.sh"
|
|
397
|
+
tree: "bash .pipemd/scripts/project/tree.sh"
|
|
398
|
+
diff-stat: "bash .pipemd/scripts/git/diff-stat.sh"
|
|
399
|
+
todos: "bash .pipemd/scripts/project/find-todos.sh"
|
|
400
|
+
|
|
401
|
+
pipes:
|
|
402
|
+
- file: "AGENTS.md" # The file the AI Agent reads
|
|
403
|
+
render: ".pipemd/template.md" # The template to populate
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Shared Scripts
|
|
407
|
+
Because `.pipemd/scripts/` is committed to git, your whole team gets the exact same context harness. Drop any language script in there (`.sh`, `.py`, `.js`) to pull test results, type-check errors, or database schemas.
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## 🤖 For AI Agents
|
|
412
|
+
|
|
413
|
+
If you are an AI agent reading a PipeMD context file, here is the contract:
|
|
414
|
+
|
|
415
|
+
**Reading.** The file you read (`CLAUDE.md`, `AGENTS.md`, …) is a *live render*.
|
|
416
|
+
Prefer the data inside `<!-- pmd: -->` blocks over running your own shell
|
|
417
|
+
commands — it is current as of the moment you opened the file.
|
|
418
|
+
|
|
419
|
+
**Editing.** The file is split by a `<!-- pmd-context -->` separator:
|
|
420
|
+
|
|
421
|
+
| Where you edit | Where it persists | Notes |
|
|
422
|
+
|---|---|---|
|
|
423
|
+
| Above the separator | `.pipemd/base.md` | Your own rules and instructions. |
|
|
424
|
+
| Below it, *outside* `<!-- pmd: -->` blocks | `.pipemd/template.md` | Section headers, notes, checkboxes. |
|
|
425
|
+
| *Inside* a `<!-- pmd: -->` block | **nowhere** | Overwritten every refresh cycle — never edit here. |
|
|
426
|
+
|
|
427
|
+
**Self-improvement.** Because the harness is plain text, you can tune your own
|
|
428
|
+
context: add/remove `<!-- pmd: -->` blocks in `.pipemd/template.md`, change
|
|
429
|
+
which scripts run in `.pipemd/config.yml`, or adjust the token profile. See
|
|
430
|
+
`.pipemd/AI_SETUP_PIPEMD.md` (scaffolded into every project) for the full guide.
|
|
431
|
+
|
|
432
|
+
**Working alongside other agents.** If a **Crew Activity** block is present,
|
|
433
|
+
read it before editing — it lists which files other agents hold. A
|
|
434
|
+
`⚠️ CONFLICT` line means another agent claimed a file you are about to touch;
|
|
435
|
+
treat it as blocking. Announce your own work with `pmd crew claim <file>` and
|
|
436
|
+
`pmd crew note "<task>"` (or let the installed hooks do it automatically).
|
|
437
|
+
|
|
438
|
+
**Smart Injection.** If the project uses Active or Expert delivery mode, PipeMD hooks inject fresh context into your working memory on every tool call. You'll see messages like `[pmd:crew-locks → src/foo.ts]` before edits and `[pmd:validate-file → src/foo.ts]` after edits. This data is:
|
|
439
|
+
|
|
440
|
+
- **Scoped**: you only see context relevant to the file you're about to touch
|
|
441
|
+
- **Deduplicated**: repeated unchanged data is silently skipped
|
|
442
|
+
- **Cache-backed**: hook latency is under 5ms
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## 🔒 Safety & Edge Cases Handled
|
|
447
|
+
|
|
448
|
+
> **⚠️ Security Warning:** PipeMD executes the commands in `config.yml` exactly as written. Do not run PipeMD in an untrusted repository.
|
|
449
|
+
|
|
450
|
+
Building a background daemon that streams live data into AI systems requires aggressive safety guardrails. PipeMD includes:
|
|
451
|
+
|
|
452
|
+
* **10-Second Timeouts:** No runaway `grep` commands hanging your AI. If a script stalls, it gets killed.
|
|
453
|
+
* **Isolated Rendering:** Built on `Promise.allSettled`. If your `test-summary.sh` fails, the error is rendered *in-place* inside the markdown file, and the rest of the document loads perfectly.
|
|
454
|
+
* **EPIPE Catching:** If Claude Code closes the stream mid-read to save tokens, PipeMD safely catches the `EPIPE` disconnect without crashing the daemon.
|
|
455
|
+
* **Stale PID Recovery:** If your machine forcefully reboots, `pmd start` instantly detects the dead process, cleans up the old pipes, and starts fresh.
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
459
|
+
## 🧑💻 For Developers
|
|
460
|
+
|
|
461
|
+
PipeMD is strict TypeScript, **ESM-only** (imports use `.js` extensions,
|
|
462
|
+
`NodeNext` resolution), built with `tsup`, and targets Node.js 18+.
|
|
463
|
+
|
|
464
|
+
### Build & test
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
pnpm install # Install dependencies
|
|
468
|
+
pnpm build # Production build → dist/ (run before any e2e test)
|
|
469
|
+
pnpm dev # Watch mode — rebuilds on change
|
|
470
|
+
tsc --noEmit # Type-check only
|
|
471
|
+
|
|
472
|
+
pnpm test # Full suite: unit → e2e → bidir → scripts → arch → compose → crew
|
|
473
|
+
pnpm test:unit # reverseInject logic (pure Node, no build needed)
|
|
474
|
+
pnpm test:crew # Crew coordination lifecycle (needs build)
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
There is no test framework: unit tests use `node:assert`, e2e tests are Bash
|
|
478
|
+
scripts with custom assertion helpers in `tests/`.
|
|
479
|
+
|
|
480
|
+
### Source layout
|
|
481
|
+
|
|
482
|
+
```text
|
|
483
|
+
src/
|
|
484
|
+
├── index.ts # CLI entry — Commander program, registers all commands
|
|
485
|
+
├── config.ts # PipeConfig type + DEFAULT_CONFIG
|
|
486
|
+
├── commands/ # One file per command: init, start, stop, restart,
|
|
487
|
+
│ # status, run, refresh, doctor, uninstall, crew
|
|
488
|
+
└── core/
|
|
489
|
+
├── daemon.ts # Daemon loop — pipe mode (mkfifo) + legacy mode (chokidar)
|
|
490
|
+
├── injector.ts # Renders <!-- pmd: --> blocks; reverseInject write-back
|
|
491
|
+
├── cache.ts # Per-source render cache with TTL + invalidation
|
|
492
|
+
├── injection-types.ts # Injection config schema, types, defaults
|
|
493
|
+
├── injection-engine.ts # Rules engine — resolves sources, dedup, truncation
|
|
494
|
+
├── dedup.ts # Per-session dedup — skips unchanged content
|
|
495
|
+
├── detect.ts # Ecosystem auto-detection (Node, Python, Rust, …)
|
|
496
|
+
├── detectHarness.ts # AI-harness detection (Claude Code, OpenCode, …)
|
|
497
|
+
├── crew.ts # Crew ledger, conflict detection, block rendering
|
|
498
|
+
├── hooks.ts # Per-harness hook installers (crew + injection)
|
|
499
|
+
├── actions.ts # start/stop/cleanup logic
|
|
500
|
+
└── logger.ts # File logger → .pipemd/daemon.log
|
|
501
|
+
|
|
502
|
+
scripts/ # Bundled Bash library, by ecosystem & category
|
|
503
|
+
templates/ # Per-ecosystem Markdown templates
|
|
504
|
+
tests/ # e2e-*.sh suites + test-reverse-inject.mjs + fixtures/
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### The render pipeline
|
|
508
|
+
|
|
509
|
+
1. `daemon.ts` reads `.pipemd/template.md` and finds `<!-- pmd: name -->` tags.
|
|
510
|
+
2. `injector.ts` runs each tag's command (from `config.commands`) concurrently
|
|
511
|
+
via `Promise.allSettled`, with a 10 s timeout per command.
|
|
512
|
+
3. Rendered blocks replace the tags; `base.md` is prepended with the
|
|
513
|
+
`<!-- pmd-context -->` separator.
|
|
514
|
+
4. The composed Markdown is served on the named pipe (or written in legacy mode)
|
|
515
|
+
to every harness's context file.
|
|
516
|
+
5. AI edits flow back: `reverseInject` de-renders `pmd` blocks and persists
|
|
517
|
+
edits to `base.md` / `template.md`.
|
|
518
|
+
|
|
519
|
+
### Smart injection pipeline (Active/Expert mode)
|
|
520
|
+
|
|
521
|
+
1. Harness hook fires (e.g., Claude Code `PreToolUse:Edit` on `src/foo.ts`)
|
|
522
|
+
2. Hook calls `pmd inject --trigger before-edit --file src/foo.ts`
|
|
523
|
+
3. Injection engine loads rules from `injection.yml`
|
|
524
|
+
4. For each matching rule, runs the source resolver (crew-locks, file-errors, git-context...)
|
|
525
|
+
5. Each resolver reads from the render cache (sub-5ms)
|
|
526
|
+
6. Dedup layer checks: skip if content unchanged since last injection
|
|
527
|
+
7. Payloads printed to stdout → agent sees them as hook output
|
|
528
|
+
8. For after-edit triggers: async validation (eslint + tsc) runs in background, cached for next call
|
|
529
|
+
|
|
530
|
+
PRs welcome — see `CLAUDE.md` for conventions and gotchas, `SPEC.md` for the
|
|
531
|
+
full specification.
|
|
532
|
+
|
|
533
|
+
## 📜 License
|
|
534
|
+
|
|
535
|
+
**ISC License** © Ivann Rudrauf
|