pluidr 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +294 -73
- package/package.json +7 -2
- package/src/cli/commands/doctor.js +99 -0
- package/src/cli/commands/init.js +14 -7
- package/src/cli/commands/uninstall.js +67 -0
- package/src/cli/commands/update.js +22 -0
- package/src/cli/index.js +31 -1
- package/src/cli/wizard/selectModelTier.js +22 -31
- package/src/core/agentPromptWriter.js +2 -2
- package/src/core/agentPromptWriter.test.js +56 -0
- package/src/core/backup.js +35 -5
- package/src/core/backup.test.js +51 -0
- package/src/core/configBuilder.js +13 -0
- package/src/core/configBuilder.test.js +47 -0
- package/src/core/configWriter.js +7 -4
- package/src/core/configWriter.test.js +26 -0
- package/src/core/identityHeader.test.js +15 -0
- package/src/core/paths.js +4 -15
- package/src/core/paths.test.js +21 -0
- package/src/core/pluginWriter.js +12 -8
- package/src/core/pluginWriter.test.js +41 -0
- package/src/core/squeezeInstaller.js +141 -0
- package/src/core/squeezeInstaller.test.js +77 -0
- package/src/plugins/README.md +29 -15
- package/src/plugins/{parent-session.js → pluidr-flow.js} +1 -6
- package/src/plugins/pluidr-squeeze.js +56 -0
- package/src/templates/agent-prompts/auditor.txt +20 -0
- package/src/templates/agent-prompts/coder.txt +33 -7
- package/src/templates/agent-prompts/{writer.txt → compose-reporter.txt} +7 -7
- package/src/templates/agent-prompts/composer.txt +428 -0
- package/src/templates/agent-prompts/{reporter.txt → debug-reporter.txt} +3 -7
- package/src/templates/agent-prompts/debugger.txt +64 -18
- package/src/templates/agent-prompts/fixer.txt +7 -0
- package/src/templates/agent-prompts/hierarchy.txt +29 -15
- package/src/templates/agent-prompts/patcher.txt +20 -0
- package/src/templates/agent-prompts/plan-checker.txt +5 -5
- package/src/templates/agent-prompts/plan-writer.txt +3 -3
- package/src/templates/agent-prompts/probe-reporter.txt +62 -0
- package/src/templates/agent-prompts/prober.txt +90 -0
- package/src/templates/agent-prompts/researcher.txt +3 -3
- package/src/templates/agent-prompts/reviewer.txt +16 -4
- package/src/templates/agent-prompts/tester.txt +10 -1
- package/src/templates/agent-prompts/tracer.txt +33 -0
- package/src/templates/model-defaults.json +45 -2
- package/src/templates/opencode.config.json +227 -73
- package/src/templates/rtk-checksums.json +7 -0
- package/src/templates/agent-prompts/builder.txt +0 -107
- package/src/templates/agent-prompts/explorer.txt +0 -53
- package/src/templates/agent-prompts/planner.txt +0 -126
package/README.md
CHANGED
|
@@ -4,94 +4,288 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/pluidr)
|
|
5
5
|
[](https://github.com/funara/pluidr/blob/main/LICENSE)
|
|
6
6
|
|
|
7
|
-
**Plan · Build · Review
|
|
7
|
+
** Plan · Build · Review ** — opinionated engineering workflow installer for [OpenCode](https://opencode.ai).
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## What is Pluidr?
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Pluidr installs a **17-agent pipeline** into OpenCode — structured around **3 primary agents**, each with their own exclusive subagents, scoped permissions, and enforced workflow rules. No shared subagents. No ad-hoc delegation.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
| Primary Agent | Purpose | Subagents |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| **Composer** | Feature work — Explore → Plan → Build | Researcher, Plan-Writer, Plan-Checker, Coder, Tester, Reviewer, Compose-Reporter |
|
|
18
|
+
| **Debugger** | Bug investigation — Investigate → Fix → Report | Inspector, Fixer, Debug-Reporter |
|
|
19
|
+
| **Prober** | Security audit — Trace → Patch → Audit | Tracer, Patcher, Auditor, Probe-Reporter |
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
---
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
## Agent Workflows
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
### 🎼 Composer — Feature Work
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
Composer is the **single entry point for all feature work**. It runs 3 strict, one-directional phases. Phase direction is one-way — no going back without explicit user instruction.
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
```
|
|
30
|
+
You describe a feature / idea
|
|
31
|
+
│
|
|
32
|
+
▼
|
|
33
|
+
┌─────────────────────────────────────────┐
|
|
34
|
+
│ EXPLORE PHASE (mandatory start) │
|
|
35
|
+
│ │
|
|
36
|
+
│ Delegate: Researcher │
|
|
37
|
+
│ → deep codebase + web fact-finding │
|
|
38
|
+
│ → confirmed_facts / inferred_facts / │
|
|
39
|
+
│ unknowns / risks │
|
|
40
|
+
│ │
|
|
41
|
+
│ Composer internally assesses: │
|
|
42
|
+
│ Is this feature simple or complex? │
|
|
43
|
+
└──────────┬──────────────────────────────┘
|
|
44
|
+
│
|
|
45
|
+
┌────────┴────────┐
|
|
46
|
+
│ Simple feature │ Complex feature
|
|
47
|
+
▼ ▼
|
|
48
|
+
GUARDRAIL GATE 1a GUARDRAIL GATE 1b
|
|
49
|
+
"Build directly?" "Write a PRD?"
|
|
50
|
+
│ │
|
|
51
|
+
│ Yes │ Yes
|
|
52
|
+
│ ▼
|
|
53
|
+
│ ┌──────────────────────────────┐
|
|
54
|
+
│ │ PLAN PHASE │
|
|
55
|
+
│ │ │
|
|
56
|
+
│ │ Plan-Writer → docs/plans/ │
|
|
57
|
+
│ │ Plan-Checker validates PRD │
|
|
58
|
+
│ │ PASS/FAIL + gap list only │
|
|
59
|
+
│ │ │
|
|
60
|
+
│ │ FAIL → surface gaps to you │
|
|
61
|
+
│ │ (max 5 loops) │
|
|
62
|
+
│ │ │
|
|
63
|
+
│ │ PASS → GUARDRAIL GATE 2 │
|
|
64
|
+
│ │ "Build from this PRD?" │
|
|
65
|
+
│ └──────────┬───────────────────┘
|
|
66
|
+
│ │ Yes
|
|
67
|
+
└──────────┬──────────┘
|
|
68
|
+
▼
|
|
69
|
+
┌────────────────────────────────────────────┐
|
|
70
|
+
│ BUILD PHASE │
|
|
71
|
+
│ │
|
|
72
|
+
│ Coder → implements from PRD / request │
|
|
73
|
+
│ │ │
|
|
74
|
+
│ ▼ │
|
|
75
|
+
│ Tester → PASS/FAIL/BLOCKED │
|
|
76
|
+
│ │ FAIL → back to Coder (max 5 loops) │
|
|
77
|
+
│ │ PASS ↓ │
|
|
78
|
+
│ ▼ │
|
|
79
|
+
│ Reviewer → PASS/FAIL + gap list │
|
|
80
|
+
│ │ FAIL → back to Coder (max 5 loops) │
|
|
81
|
+
│ │ PASS ↓ │
|
|
82
|
+
│ ▼ │
|
|
83
|
+
│ Compose-Reporter → docs/reports/ │
|
|
84
|
+
└────────────────────────────────────────────┘
|
|
85
|
+
│
|
|
86
|
+
▼
|
|
87
|
+
You review result
|
|
88
|
+
│
|
|
89
|
+
Composer resets → asks: New feature? Debug? Iterate?
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Key rules:**
|
|
93
|
+
- Composer has **no read/write/bash permissions** — all work delegated to subagents
|
|
94
|
+
- Phase transition only via guardrail gates — no skipping
|
|
95
|
+
- `Coder → Coder` loops without Tester verification are forbidden
|
|
96
|
+
- 5 consecutive FAILs from Tester or Reviewer → surfaces to you
|
|
97
|
+
|
|
98
|
+
---
|
|
26
99
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
| Planner | Researcher | Technical/codebase fact-finding (confirmed_facts/inferred_facts/unknowns/risks) |
|
|
31
|
-
| Planner | Plan-Writer | Stateless PRD formatter — missing input = TBD |
|
|
32
|
-
| Planner | Plan-Checker | **Gate** — validates PRD against original request, PASS/FAIL + gap list only |
|
|
33
|
-
| Builder | Coder | Writes and edits implementation code |
|
|
34
|
-
| Builder | Tester | Runs tests, reports PASS/FAIL/BLOCKED + coverage gaps |
|
|
35
|
-
| Builder | Reviewer | **Gate** — compares implementation against definition-of-done, PASS/FAIL + gap list only |
|
|
36
|
-
| Builder | Writer | Stateless document formatter — completion reports |
|
|
37
|
-
| Debugger | Inspector | Brooks-Lint RCA (Iron Law + 6 decay risks + 4 review modes) |
|
|
38
|
-
| Debugger | Fixer | Applies minimal, root-cause-targeted fixes |
|
|
39
|
-
| Debugger | Reporter | Stateless diagnosis report formatter (Iron Law structure) |
|
|
40
|
-
|
|
41
|
-
### Workflow
|
|
100
|
+
### 🐛 Debugger — Bug Investigation
|
|
101
|
+
|
|
102
|
+
Debugger is a **standalone primary agent** — does not depend on Composer. Trigger it directly from the Debugger tab whenever you find a bug.
|
|
42
103
|
|
|
43
104
|
```
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
105
|
+
You report a bug / defect
|
|
106
|
+
│
|
|
107
|
+
▼
|
|
108
|
+
┌─────────────────────────────────────────────┐
|
|
109
|
+
│ INVESTIGATE PHASE │
|
|
110
|
+
│ │
|
|
111
|
+
│ Delegate: Inspector │
|
|
112
|
+
│ Review mode (Debugger selects): │
|
|
113
|
+
│ · PR Review → classify R1-R6 │
|
|
114
|
+
│ · Architecture → dependency analysis │
|
|
115
|
+
│ · Tech Debt → Pain × Spread score │
|
|
116
|
+
│ · Test Quality → classify T1-T6 │
|
|
117
|
+
│ │
|
|
118
|
+
│ Output: Iron Law chain per finding │
|
|
119
|
+
│ Symptom → Source → Consequence → Remedy │
|
|
120
|
+
└──────────┬──────────────────────────────────┘
|
|
121
|
+
│
|
|
122
|
+
Root cause identified?
|
|
123
|
+
┌────────┴────────┐
|
|
124
|
+
│ Yes │ No / unknowns remain
|
|
125
|
+
▼ ▼
|
|
126
|
+
┌─────────────┐ Halt — surface to you
|
|
127
|
+
│ FIX PHASE │ with specific questions
|
|
128
|
+
│ │
|
|
129
|
+
│ Delegate: │
|
|
130
|
+
│ Fixer │
|
|
131
|
+
│ → minimal │
|
|
132
|
+
│ fix per │
|
|
133
|
+
│ Iron Law │
|
|
134
|
+
└──────┬──────┘
|
|
52
135
|
│
|
|
53
136
|
▼
|
|
54
|
-
|
|
55
|
-
|
|
137
|
+
┌──────────────────────────────────────┐
|
|
138
|
+
│ REPORT PHASE │
|
|
139
|
+
│ │
|
|
140
|
+
│ Delegate: Debug-Reporter │
|
|
141
|
+
│ → Iron Law diagnosis report │
|
|
142
|
+
│ → saved to docs/reports/ │
|
|
143
|
+
└──────────────────────────────────────┘
|
|
56
144
|
│
|
|
57
145
|
▼
|
|
58
|
-
|
|
146
|
+
You review the diagnosis + fix
|
|
59
147
|
│
|
|
60
|
-
|
|
61
|
-
Reporter → you verify)
|
|
148
|
+
Debugger resets → asks: New bug? Feature work? Re-investigate?
|
|
62
149
|
```
|
|
63
150
|
|
|
64
|
-
|
|
151
|
+
**Key rules:**
|
|
152
|
+
- Debugger has **no read/write/bash permissions** — all delegated to subagents
|
|
153
|
+
- Never delegates Fixer without Inspector confirming root cause first
|
|
154
|
+
- If unknowns remain after investigation → halts and prompts you, does not guess
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### 🔍 Prober — Security Audit
|
|
159
|
+
|
|
160
|
+
Prober is a **standalone primary agent** — does not depend on Composer or Debugger. Trigger it directly from the Prober tab to audit any codebase for security vulnerabilities and quality decay.
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
You trigger a security audit
|
|
164
|
+
│
|
|
165
|
+
▼
|
|
166
|
+
┌───────────────────────────────────────────────────┐
|
|
167
|
+
│ TRACE PHASE (mandatory start) │
|
|
168
|
+
│ │
|
|
169
|
+
│ Delegate: Tracer │
|
|
170
|
+
│ → WSTG-guided breadth-first recon │
|
|
171
|
+
│ → trace data flows: input → path → sink │
|
|
172
|
+
│ │
|
|
173
|
+
│ Output: │
|
|
174
|
+
│ · Confirmed Vulnerabilities (OWASP category, │
|
|
175
|
+
│ location, data flow) │
|
|
176
|
+
│ · Suspected Vulnerabilities (manual verify) │
|
|
177
|
+
│ · Quality & Decay Risks (e.g. hardcoded │
|
|
178
|
+
│ secrets, missing input validation) │
|
|
179
|
+
└──────────┬────────────────────────────────────────┘
|
|
180
|
+
│
|
|
181
|
+
▼
|
|
182
|
+
GUARDRAIL GATE (question tool):
|
|
183
|
+
"Audit findings ready. How to proceed?"
|
|
184
|
+
├── "Patch all confirmed findings" → PATCH PHASE
|
|
185
|
+
├── "Select specific findings" → PATCH PHASE (you pick)
|
|
186
|
+
├── "Audit only — no patches" → AUDIT PHASE (skip PATCH)
|
|
187
|
+
└── "Re-investigate attack surface" → re-delegate Tracer
|
|
188
|
+
│
|
|
189
|
+
▼
|
|
190
|
+
┌──────────────────────────────────────────────────┐
|
|
191
|
+
│ PATCH PHASE (skipped if audit-only) │
|
|
192
|
+
│ │
|
|
193
|
+
│ Delegate: Patcher │
|
|
194
|
+
│ → Ponytail mindset: smallest correct diff │
|
|
195
|
+
│ → prefer deleting the cause over wrapping it │
|
|
196
|
+
│ → escalates to you if patch > 10 lines │
|
|
197
|
+
└──────────┬───────────────────────────────────────┘
|
|
198
|
+
│
|
|
199
|
+
▼
|
|
200
|
+
┌──────────────────────────────────────────────────┐
|
|
201
|
+
│ AUDIT PHASE (max 5 loops) │
|
|
202
|
+
│ │
|
|
203
|
+
│ Delegate: Auditor │
|
|
204
|
+
│ → verify patch resolved vulnerabilities │
|
|
205
|
+
│ → security regression check │
|
|
206
|
+
│ → Ponytail BLOAT analysis (over-engineering) │
|
|
207
|
+
│ │
|
|
208
|
+
│ PASS → proceed to report │
|
|
209
|
+
│ FAIL → re-delegate Patcher with Gap + BLOAT │
|
|
210
|
+
│ lists verbatim (max 5 loops, then you) │
|
|
211
|
+
│ │
|
|
212
|
+
│ Delegate: Probe-Reporter │
|
|
213
|
+
│ → security audit report → docs/reports/ │
|
|
214
|
+
└──────────────────────────────────────────────────┘
|
|
215
|
+
│
|
|
216
|
+
▼
|
|
217
|
+
You review the audit report
|
|
218
|
+
│
|
|
219
|
+
Prober resets → asks: New audit? Feature work? Bug investigation?
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Key rules:**
|
|
223
|
+
- Prober has **no read/write/bash permissions** — all delegated to subagents
|
|
224
|
+
- TRACE phase is always mandatory — no patching without recon first
|
|
225
|
+
- GUARDRAIL GATE required before any patches are applied
|
|
226
|
+
- 5 consecutive AUDIT FAILs → surfaces to you
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Subagent Reference
|
|
231
|
+
|
|
232
|
+
Each subagent belongs to exactly one primary agent and cannot be invoked by anyone else:
|
|
233
|
+
|
|
234
|
+
| Primary | Phase | Subagent | Role |
|
|
235
|
+
|---------|-------|----------|------|
|
|
236
|
+
| Composer | EXPLORE | Researcher | Fact-finding: confirmed_facts / inferred_facts / unknowns / risks |
|
|
237
|
+
| Composer | PLAN | Plan-Writer | **Formatter** — writes PRD to `docs/plans/`, missing input = TBD |
|
|
238
|
+
| Composer | PLAN | Plan-Checker | **Gate** — PASS/FAIL + gap list only, no suggestions |
|
|
239
|
+
| Composer | BUILD | Coder | Implements code from PRD |
|
|
240
|
+
| Composer | BUILD | Tester | PASS/FAIL/BLOCKED + coverage gaps only |
|
|
241
|
+
| Composer | BUILD | Reviewer | **Gate** — PASS/FAIL + gap list only, no suggestions |
|
|
242
|
+
| Composer | BUILD | Compose-Reporter | **Formatter** — completion report to `docs/reports/` |
|
|
243
|
+
| Debugger | DEBUG | Inspector | Brooks-Lint RCA (Iron Law + 6 decay risks + 4 review modes) |
|
|
244
|
+
| Debugger | DEBUG | Fixer | Minimal, root-cause-targeted fix |
|
|
245
|
+
| Debugger | DEBUG | Debug-Reporter | **Formatter** — Iron Law diagnosis report to `docs/reports/` |
|
|
246
|
+
| Prober | TRACE | Tracer | WSTG recon + vuln path tracing, no remedies |
|
|
247
|
+
| Prober | PATCH | Patcher | Minimal, security-targeted fix (Ponytail, max 10 lines) |
|
|
248
|
+
| Prober | AUDIT | Auditor | **Gate** — PASS/FAIL + Gap List + BLOAT List only |
|
|
249
|
+
| Prober | AUDIT | Probe-Reporter | **Formatter** — security audit report to `docs/reports/` |
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Flow Rules
|
|
65
254
|
|
|
66
255
|
| Rule | Detail |
|
|
67
256
|
|------|--------|
|
|
68
|
-
| **
|
|
69
|
-
| **
|
|
70
|
-
| **
|
|
71
|
-
| **
|
|
72
|
-
| **
|
|
73
|
-
| **
|
|
74
|
-
| **
|
|
75
|
-
| **
|
|
257
|
+
| **Mandatory starts** | Composer always starts in EXPLORE. Prober always starts in TRACE. No skipping. |
|
|
258
|
+
| **Guardrail gates** | Composer: Gate 1 (EXPLORE→PLAN/BUILD), Gate 2 (PLAN→BUILD). Prober: Gate after TRACE. All require user confirmation. |
|
|
259
|
+
| **Gate agents** | Plan-Checker, Reviewer, Auditor — PASS/FAIL + gap list only. No suggestions, no decisions. |
|
|
260
|
+
| **Formatter agents** | Plan-Writer, Compose-Reporter, Debug-Reporter, Probe-Reporter — stateless. Missing input = TBD/NA. Never invent content. |
|
|
261
|
+
| **Fact-finding agents** | Researcher, Inspector, Tracer — facts/inferences/risks only. No recommendations. |
|
|
262
|
+
| **Build gate order** | Coder → Tester → Reviewer → Compose-Reporter. No skipping. No Coder→Coder without verification. |
|
|
263
|
+
| **FAIL loops** | Plan-Checker FAIL: max 5 loops. Build FAIL (Tester/Reviewer): max 5 loops. Prober AUDIT FAIL: max 5 loops. All surface to you after limit. |
|
|
264
|
+
| **Output directories** | PRDs → `docs/plans/`. Reports (Compose-Reporter, Debug-Reporter, Probe-Reporter) → `docs/reports/`. Enforced by permissions. |
|
|
265
|
+
| **Independence** | Debugger and Prober are fully standalone — triggered directly, do not flow through Composer. |
|
|
76
266
|
|
|
77
|
-
|
|
267
|
+
---
|
|
78
268
|
|
|
79
|
-
|
|
269
|
+
## Brooks-Lint Methodology (Debugger)
|
|
270
|
+
|
|
271
|
+
The Debugger pipeline uses the [Brooks-Lint](https://hyhmrright.github.io/brooks-lint/guide.html) framework:
|
|
80
272
|
|
|
81
273
|
- **Iron Law** per finding: Symptom → Source → Consequence → Remedy
|
|
82
|
-
- **6 Decay Risks (R1
|
|
83
|
-
- **4 Review Modes**: PR Review (R1
|
|
84
|
-
- **T1
|
|
274
|
+
- **6 Decay Risks (R1–R6)**: Cognitive Overload, Change Propagation, Knowledge Duplication, Accidental Complexity, Dependency Disorder, Domain Model Distortion
|
|
275
|
+
- **4 Review Modes**: PR Review (R1–R6), Architecture Audit, Tech Debt Assessment (Pain × Spread), Test Quality (T1–T6)
|
|
276
|
+
- **T1–T6 Test Risks**: Test Obscurity, Brittleness, Duplication, Mock Abuse, Coverage Illusion, Architecture Mismatch
|
|
277
|
+
|
|
278
|
+
## Principle Hierarchy
|
|
85
279
|
|
|
86
|
-
|
|
280
|
+
All agents resolve conflicts using this priority order (defined in `hierarchy.txt`):
|
|
87
281
|
|
|
88
|
-
|
|
282
|
+
1. **PRD / Spec** — explicit requirement text
|
|
283
|
+
2. **Verdict** — Reviewer / Plan-Checker / Auditor PASS/FAIL
|
|
284
|
+
3. **Engineering principles** — Fail Fast, Single Responsibility
|
|
285
|
+
4. **Heuristics** — KISS, DRY, SOLID, Law of Demeter
|
|
286
|
+
5. **Local optimization** — style preference
|
|
89
287
|
|
|
90
|
-
|
|
91
|
-
2. **Verdict** (Reviewer PASS/FAIL, Plan-Checker PASS/FAIL)
|
|
92
|
-
3. **Engineering principles tied to correctness** (Fail Fast, Single Responsibility)
|
|
93
|
-
4. **Heuristics** (KISS, DRY, SOLID, Law of Demeter)
|
|
94
|
-
5. **Local optimization / style preference**
|
|
288
|
+
---
|
|
95
289
|
|
|
96
290
|
## Install
|
|
97
291
|
|
|
@@ -109,28 +303,55 @@ npx pluidr init
|
|
|
109
303
|
|
|
110
304
|
### `pluidr init`
|
|
111
305
|
|
|
112
|
-
Prompts you to select models for two agent tiers, then:
|
|
306
|
+
Prompts you to select models for two agent tiers (reasoning-heavy and fast), then:
|
|
113
307
|
|
|
308
|
+
- Asks whether to install the pluidr-squeeze plugin (can decline)
|
|
114
309
|
- Builds a complete `opencode.jsonc` config with the chosen models injected into the right agents
|
|
115
|
-
- Backs up any existing config
|
|
310
|
+
- Backs up any existing config to `opencode.jsonc.bak.*`
|
|
116
311
|
- Writes the new config to `~/.config/opencode/opencode.jsonc`
|
|
117
|
-
- Copies agent
|
|
118
|
-
- Copies
|
|
119
|
-
- Writes a `package.json`
|
|
312
|
+
- Copies all 18 agent prompt files into `~/.config/opencode/prompts/`
|
|
313
|
+
- Copies `pluidr-flow` and `pluidr-squeeze` plugins into `~/.config/opencode/plugins/`
|
|
314
|
+
- Writes a `package.json` declaring `@opencode-ai/plugin` as a dependency
|
|
120
315
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
316
|
+
### `pluidr doctor`
|
|
317
|
+
|
|
318
|
+
Checks installation health and reports ✓/✗ for each component:
|
|
319
|
+
|
|
320
|
+
- `opencode.jsonc` exists
|
|
321
|
+
- All 18 prompt files present
|
|
322
|
+
- Both plugin files present
|
|
323
|
+
- `package.json` with `@opencode-ai/plugin` dependency
|
|
324
|
+
- squeeze binary available
|
|
325
|
+
- Config is valid JSON
|
|
326
|
+
|
|
327
|
+
Exits with code `0` if all pass, `1` if any fail.
|
|
127
328
|
|
|
128
|
-
|
|
329
|
+
### `pluidr update`
|
|
129
330
|
|
|
130
|
-
|
|
331
|
+
Re-runs the setup wizard. Warns if existing config is found and asks for confirmation before overwriting.
|
|
332
|
+
|
|
333
|
+
### `pluidr uninstall`
|
|
334
|
+
|
|
335
|
+
Restores your previous configuration:
|
|
336
|
+
|
|
337
|
+
- Finds the latest timestamped backup and restores it to `opencode.jsonc`
|
|
338
|
+
- Removes `prompts/`, `plugins/`, and `bin/` directories
|
|
339
|
+
- Preserves `opencode.jsonc` and `package.json`
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Bundled Plugins
|
|
344
|
+
|
|
345
|
+
### `pluidr-flow`
|
|
346
|
+
|
|
347
|
+
Provides subagents with cross-session context access:
|
|
131
348
|
|
|
132
349
|
- `parent_session_messages` — read the parent session's transcript
|
|
133
350
|
- `session_messages(sessionId)` — read any session by ID
|
|
134
351
|
- `session_messages_batch(sessionIds)` — read multiple sessions in one call
|
|
135
352
|
|
|
136
|
-
`pluidr
|
|
353
|
+
### `pluidr-squeeze`
|
|
354
|
+
|
|
355
|
+
Hooks into tool execution to rewrite bash commands through the `squeeze` binary, filtering verbose output and saving **60–90% of tokens** across all agents.
|
|
356
|
+
|
|
357
|
+
Both plugins and their dependency declaration are installed automatically by `pluidr init` — no extra user action required. On OpenCode's first launch, the bundled Bun runtime installs `@opencode-ai/plugin` from the generated `package.json`.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pluidr",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Opinionated Engineering Workflow for OpenCode — Plan, Build,
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "Opinionated Engineering Workflow for OpenCode — Explore, Plan, Build, Debug, and Security-Audit.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"opencode",
|
|
7
7
|
"workflow",
|
|
@@ -10,12 +10,17 @@
|
|
|
10
10
|
"ai-agents",
|
|
11
11
|
"code-review",
|
|
12
12
|
"debugging",
|
|
13
|
+
"security-audit",
|
|
14
|
+
"security",
|
|
13
15
|
"planner",
|
|
14
16
|
"builder",
|
|
15
17
|
"cli"
|
|
16
18
|
],
|
|
17
19
|
"license": "MIT",
|
|
18
20
|
"type": "module",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "node --test"
|
|
23
|
+
},
|
|
19
24
|
"bin": {
|
|
20
25
|
"pluidr": "bin/pluidr.js"
|
|
21
26
|
},
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs"
|
|
2
|
+
import { join, dirname } from "node:path"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
import { execFileSync } from "node:child_process"
|
|
5
|
+
import { getConfigDir, getConfigPath, getPromptsDir } from "../../core/paths.js"
|
|
6
|
+
import { findRtkPath } from "../../core/squeezeInstaller.js"
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const EXPECTED_PROMPT_COUNT = 18
|
|
10
|
+
const PLUGIN_FILES = ["pluidr-flow.js", "pluidr-squeeze.js"]
|
|
11
|
+
|
|
12
|
+
export async function runDoctor() {
|
|
13
|
+
const configDir = getConfigDir()
|
|
14
|
+
const configPath = getConfigPath()
|
|
15
|
+
const promptsDir = getPromptsDir()
|
|
16
|
+
const pluginsDir = join(configDir, "plugins")
|
|
17
|
+
const packageJsonPath = join(configDir, "package.json")
|
|
18
|
+
const binDir = join(configDir, "bin")
|
|
19
|
+
|
|
20
|
+
const checks = []
|
|
21
|
+
|
|
22
|
+
// 1. opencode.jsonc exists
|
|
23
|
+
const configExists = existsSync(configPath)
|
|
24
|
+
checks.push({ component: "opencode.jsonc", pass: configExists })
|
|
25
|
+
|
|
26
|
+
// 2. All 18 prompt files exist
|
|
27
|
+
let promptCount = 0
|
|
28
|
+
if (existsSync(promptsDir)) {
|
|
29
|
+
try {
|
|
30
|
+
const files = readdirSync(promptsDir).filter((f) => f.endsWith(".txt"))
|
|
31
|
+
promptCount = files.length
|
|
32
|
+
} catch {
|
|
33
|
+
promptCount = 0
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
checks.push({ component: "18 prompt files", pass: promptCount === EXPECTED_PROMPT_COUNT, detail: `${promptCount}/${EXPECTED_PROMPT_COUNT}` })
|
|
37
|
+
|
|
38
|
+
// 3. Both plugin files exist
|
|
39
|
+
let pluginsFound = 0
|
|
40
|
+
for (const f of PLUGIN_FILES) {
|
|
41
|
+
if (existsSync(join(pluginsDir, f))) pluginsFound++
|
|
42
|
+
}
|
|
43
|
+
checks.push({ component: "plugin files", pass: pluginsFound === PLUGIN_FILES.length, detail: `${pluginsFound}/${PLUGIN_FILES.length}` })
|
|
44
|
+
|
|
45
|
+
// 4. package.json with @opencode-ai/plugin dependency
|
|
46
|
+
let pkgValid = false
|
|
47
|
+
if (existsSync(packageJsonPath)) {
|
|
48
|
+
try {
|
|
49
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8"))
|
|
50
|
+
pkgValid = !!(pkg.dependencies && pkg.dependencies["@opencode-ai/plugin"])
|
|
51
|
+
} catch {
|
|
52
|
+
pkgValid = false
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
checks.push({ component: "package.json + plugin dep", pass: pkgValid })
|
|
56
|
+
|
|
57
|
+
// 5. RTK binary exists
|
|
58
|
+
let rtkFound = false
|
|
59
|
+
const rtkOnPath = findRtkPath()
|
|
60
|
+
if (rtkOnPath) {
|
|
61
|
+
rtkFound = true
|
|
62
|
+
} else {
|
|
63
|
+
const binName = process.platform === "win32" ? "rtk.exe" : "rtk"
|
|
64
|
+
rtkFound = existsSync(join(binDir, binName))
|
|
65
|
+
}
|
|
66
|
+
checks.push({ component: "squeeze binary", pass: rtkFound })
|
|
67
|
+
|
|
68
|
+
// 6. Config is valid JSON/JSONC
|
|
69
|
+
let configValid = false
|
|
70
|
+
if (configExists) {
|
|
71
|
+
try {
|
|
72
|
+
const content = readFileSync(configPath, "utf-8")
|
|
73
|
+
const cleaned = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g) => g ? "" : m)
|
|
74
|
+
JSON.parse(cleaned)
|
|
75
|
+
configValid = true
|
|
76
|
+
} catch {
|
|
77
|
+
configValid = false
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
checks.push({ component: "config JSON validity", pass: configValid })
|
|
81
|
+
|
|
82
|
+
// Print summary table
|
|
83
|
+
const allPass = checks.every((c) => c.pass)
|
|
84
|
+
console.log("\nPluidr Doctor — Installation Health Check\n")
|
|
85
|
+
for (const c of checks) {
|
|
86
|
+
const icon = c.pass ? "\u2713" : "\u2717"
|
|
87
|
+
const detail = c.detail ? ` (${c.detail})` : ""
|
|
88
|
+
console.log(` ${icon} ${c.component}${detail}`)
|
|
89
|
+
}
|
|
90
|
+
console.log("")
|
|
91
|
+
|
|
92
|
+
if (allPass) {
|
|
93
|
+
console.log("All checks passed.")
|
|
94
|
+
} else {
|
|
95
|
+
console.log("Some checks failed. Re-run `pluidr init` to repair.")
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
process.exit(allPass ? 0 : 1)
|
|
99
|
+
}
|
package/src/cli/commands/init.js
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs"
|
|
2
2
|
import { resolve, dirname } from "node:path"
|
|
3
3
|
import { fileURLToPath } from "node:url"
|
|
4
|
+
import { confirm, isCancel } from "@clack/prompts"
|
|
4
5
|
import { selectModelTier } from "../wizard/selectModelTier.js"
|
|
5
6
|
import { backupExistingConfig } from "../../core/backup.js"
|
|
6
7
|
import { buildConfig } from "../../core/configBuilder.js"
|
|
7
8
|
import { writeConfig } from "../../core/configWriter.js"
|
|
8
9
|
import { writeAgentPrompts } from "../../core/agentPromptWriter.js"
|
|
9
10
|
import { writePluginBundle, writePluginPackageJson } from "../../core/pluginWriter.js"
|
|
11
|
+
import { installSqueeze } from "../../core/squeezeInstaller.js"
|
|
10
12
|
import { getConfigPath } from "../../core/paths.js"
|
|
11
13
|
|
|
12
14
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
13
15
|
const TEMPLATES_DIR = resolve(__dirname, "../../templates")
|
|
14
16
|
|
|
15
|
-
function makeFileHyperlink(absolutePath, displayText) {
|
|
16
|
-
const normalized = absolutePath.replace(/\\/g, "/").replace(/^\//, "")
|
|
17
|
-
const fileUrl = `file:///${normalized}`
|
|
18
|
-
return `\x1b]8;;${fileUrl}\x1b\\${displayText}\x1b]8;;\x1b\\`
|
|
19
|
-
}
|
|
20
|
-
|
|
21
17
|
export async function runInit() {
|
|
22
18
|
const defaultsPath = resolve(TEMPLATES_DIR, "model-defaults.json")
|
|
23
19
|
const modelDefaults = JSON.parse(readFileSync(defaultsPath, "utf-8"))
|
|
24
20
|
|
|
25
21
|
const tierChoices = await selectModelTier(modelDefaults)
|
|
26
22
|
|
|
23
|
+
const squeezeAnswer = await confirm({
|
|
24
|
+
message: "Install pluidr-squeeze plugin? Reduces bash output tokens by 60-90%.",
|
|
25
|
+
initialValue: true,
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const installSqueezePlugin = isCancel(squeezeAnswer) ? true : squeezeAnswer
|
|
29
|
+
|
|
27
30
|
backupExistingConfig()
|
|
28
31
|
|
|
29
32
|
const configObject = buildConfig(tierChoices, TEMPLATES_DIR)
|
|
@@ -31,6 +34,10 @@ export async function runInit() {
|
|
|
31
34
|
writeAgentPrompts(TEMPLATES_DIR)
|
|
32
35
|
writePluginBundle()
|
|
33
36
|
writePluginPackageJson()
|
|
37
|
+
if (installSqueezePlugin) {
|
|
38
|
+
await installSqueeze()
|
|
39
|
+
}
|
|
34
40
|
|
|
35
|
-
|
|
41
|
+
const path = getConfigPath().replace(/\\/g, "/").replace(/^\//, "")
|
|
42
|
+
console.log(`Pluidr setup complete!\nYou can update your agent model settings later in \x1b]8;;file:///${path}\x1b\\opencode.jsonc\x1b]8;;\x1b\\`)
|
|
36
43
|
}
|