@sorenllm/opencode-forge 0.1.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 +128 -0
- package/SKILL.md +91 -0
- package/dist/index.js +13036 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# opencode-forge
|
|
2
|
+
|
|
3
|
+
Single general-purpose **forge** agent + a plan harness for
|
|
4
|
+
[opencode](https://opencode.ai) ≥ 1.18. Plans become first-class files on
|
|
5
|
+
disk with tool-enforced structure, a hard write-ban while planning, user
|
|
6
|
+
confirmation gates for approve/close, and tick-as-you-go task tracking.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
/plan fix login timeout → read-only recon → plan_write (draft, writes denied)
|
|
10
|
+
→ present → plan_approve (user dialog = approval gate)
|
|
11
|
+
→ execute task by task, plan_tick on each (timestamped audit)
|
|
12
|
+
→ all ticked → per-criterion self-check → plan_close
|
|
13
|
+
(user dialog = completion gate) → done
|
|
14
|
+
/plan → list in-progress plans with progress
|
|
15
|
+
/plan resume → continue the most recent unfinished plan
|
|
16
|
+
/plan discard → abandon the current plan (abandoned, writes restored)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- Plan files: `.opencode/plan/<date>-<slug>.md` in your project, frontmatter
|
|
20
|
+
state machine `draft → approved → done` (exit: `abandoned`).
|
|
21
|
+
- While a plan is in draft, `write` / `edit` / `bash` / `task` are **denied
|
|
22
|
+
at the permission layer** — including your own `allow` config. The only
|
|
23
|
+
exits are approval and discard. This is deliberate; see Design stance.
|
|
24
|
+
- `plan_approve` / `plan_close` are pinned to a confirmation dialog: the
|
|
25
|
+
model can never flip the state itself.
|
|
26
|
+
- The native `build` / `plan` agents are hidden while the plugin is loaded
|
|
27
|
+
(runtime injection, nothing written to your config). Uninstall restores
|
|
28
|
+
them automatically; plan files are never deleted.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
Requires opencode ≥ 1.18.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# npm (recommended)
|
|
36
|
+
opencode plugin @sorenllm/opencode-forge --global
|
|
37
|
+
# or GitHub source
|
|
38
|
+
opencode plugin github:ChengZiiii/opencode-forge --global
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Local development: add `"file:///<repo abs path>"` to the `plugin` array in
|
|
42
|
+
your opencode config. Single-file install: copy `dist/index.js` to
|
|
43
|
+
`~/.config/opencode/plugin/forge.js` **and manually copy `SKILL.md`** to
|
|
44
|
+
`~/.config/opencode/skills/plan/SKILL.md` (the package has no installer
|
|
45
|
+
script; that mode has no bundled skill otherwise).
|
|
46
|
+
|
|
47
|
+
Note: do not enable opencode's experimental plan mode
|
|
48
|
+
(`OPENCODE_EXPERIMENTAL_PLAN_MODE`) together with forge — two plan mechanisms
|
|
49
|
+
would overlap.
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
Everything works with zero config. Optional knobs (your config, your files —
|
|
54
|
+
the plugin never writes them):
|
|
55
|
+
|
|
56
|
+
```jsonc
|
|
57
|
+
{
|
|
58
|
+
"agent": {
|
|
59
|
+
"forge": {
|
|
60
|
+
"model": "provider/model", // pick any model for forge
|
|
61
|
+
"disable": true // one-knob return to native: no forge,
|
|
62
|
+
// build/plan restored, no tools/commands/skill
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
If you already have a `command.plan` of your own, it wins and the plugin's
|
|
69
|
+
`/plan` is not registered.
|
|
70
|
+
|
|
71
|
+
## Uninstall (four steps, restores native opencode)
|
|
72
|
+
|
|
73
|
+
1. Remove the plugin entry from the `plugin` array in
|
|
74
|
+
`~/.config/opencode/opencode.json` (global installs).
|
|
75
|
+
2. Delete the package store dir:
|
|
76
|
+
`~/.cache/opencode/packages/github_ChengZiiii/opencode-forge/` (github
|
|
77
|
+
installs, owner/repo layout; for npm installs it is
|
|
78
|
+
`~/.cache/opencode/packages/opencode-forge/`).
|
|
79
|
+
3. Delete the `agent["forge"]` block from your config if you added one
|
|
80
|
+
(otherwise the name lingers in the agent list).
|
|
81
|
+
4. Done — the hidden native `build`/`plan` agents come back automatically
|
|
82
|
+
(the hide was runtime-only). Your `.opencode/plan/` files are yours;
|
|
83
|
+
delete them yourself if you want.
|
|
84
|
+
|
|
85
|
+
## File ledger
|
|
86
|
+
|
|
87
|
+
What this plugin touches, exhaustively:
|
|
88
|
+
|
|
89
|
+
| Where | What | Lifetime |
|
|
90
|
+
| --- | --- | --- |
|
|
91
|
+
| `<project>/.opencode/plan/*.md` | plan files | user data — kept forever, uninstall never deletes |
|
|
92
|
+
| merged config object (RAM only) | forge agent, native build/plan `disable`, `skills.paths` entry, `command.plan` | vanishes when the plugin is removed; nothing is written to disk |
|
|
93
|
+
| `~/.cache/opencode/packages/...` | installed package copy | written by the `opencode plugin` installer, not the plugin |
|
|
94
|
+
| `~/.config/opencode/opencode.json` | `plugin` array entry | written by the installer |
|
|
95
|
+
|
|
96
|
+
The plugin writes no temp files, no logs, nothing outside the table.
|
|
97
|
+
|
|
98
|
+
## Design stance (read before filing "bash is blocked" issues)
|
|
99
|
+
|
|
100
|
+
During a plan's draft phase every mutating tool — `bash` included — is
|
|
101
|
+
denied, and an `allow` in your config does not override it. Reconnaissance is
|
|
102
|
+
read/grep/glob; if you genuinely need a shell command to decide the plan,
|
|
103
|
+
approve the plan first (revising after approval is allowed via a new `/plan`).
|
|
104
|
+
The escape hatches are `plan_approve` and `/plan discard`, by design.
|
|
105
|
+
|
|
106
|
+
A process restart forgets the session binding: the write-ban soft-disables
|
|
107
|
+
(safety over strictness) and the next session's system notice + `/plan
|
|
108
|
+
resume` re-bind from the plan file on disk, which is the source of truth.
|
|
109
|
+
|
|
110
|
+
## Development
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm install
|
|
114
|
+
bun run typecheck # tsc --noEmit
|
|
115
|
+
node --test tests/*.test.mjs
|
|
116
|
+
bun run bundle # rebuild self-contained dist/index.js (committed)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Architecture: `plugin.ts` (dual entry — v1 `server` full-featured + v2
|
|
120
|
+
`setup` defensive forward-compat) + `src/plan-file.ts` (pure plan document
|
|
121
|
+
core, unit-tested, no opencode imports) + `SKILL.md` (planning discipline,
|
|
122
|
+
discovered via `config.skills.paths`). Behavioral changes go through the
|
|
123
|
+
OpenSpec workflow in `openspec/` — see AGENTS.md. Common pitfalls live in
|
|
124
|
+
`../opencode-plugin-dev-pitfalls.md`.
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
MIT
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plan
|
|
3
|
+
description: >-
|
|
4
|
+
The plan discipline for the forge agent. You **MUST** load this skill when
|
|
5
|
+
the /plan command routes a task goal to you, OR the user asks to "plan
|
|
6
|
+
first", "make a plan", "think before coding" before implementation. It
|
|
7
|
+
governs the whole plan lifecycle: read-only reconnaissance, clarifying
|
|
8
|
+
questions, plan_write (structured, tool-rendered), user-approval via
|
|
9
|
+
plan_approve, tick-as-you-go execution via plan_tick, per-criterion
|
|
10
|
+
self-check at plan_close, and the OpenSpec boundary for long-horizon work.
|
|
11
|
+
Do NOT load it for direct implementation requests with no planning intent.
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Plan Discipline (forge)
|
|
15
|
+
|
|
16
|
+
Plans are short-horizon, single-task-goal documents on disk
|
|
17
|
+
(`.opencode/plan/<date>-<slug>.md`). The harness (tools + permission layer)
|
|
18
|
+
enforces the hard parts; you supply the engineering judgment.
|
|
19
|
+
|
|
20
|
+
## Phase 1 — Reconnaissance (read-only)
|
|
21
|
+
|
|
22
|
+
- Explore with read/grep/glob only. **All write tools, bash, and task
|
|
23
|
+
(subagents) are denied while a draft exists** — do not attempt them, do not
|
|
24
|
+
ask the user to bypass.
|
|
25
|
+
- Gather concrete evidence with `file:line` references; the plan's Context
|
|
26
|
+
Findings section must contain findings you actually verified, not guesses.
|
|
27
|
+
- If the goal is ambiguous on scope, behavior, or acceptance — ask the user
|
|
28
|
+
1-3 focused questions FIRST. Do not plan against assumptions the user could
|
|
29
|
+
settle in one line.
|
|
30
|
+
|
|
31
|
+
## Phase 2 — Write the plan (plan_write)
|
|
32
|
+
|
|
33
|
+
Call `plan_write` with structured fields; the tool renders and validates the
|
|
34
|
+
fixed sections (Goal / Non-Goals / Context Findings / Approach and
|
|
35
|
+
Alternatives / Task List / Risks / Acceptance Criteria), so a malformed plan
|
|
36
|
+
cannot exist.
|
|
37
|
+
|
|
38
|
+
Quality bar for each field:
|
|
39
|
+
|
|
40
|
+
- **goal**: one line, the outcome — not the activity.
|
|
41
|
+
- **context**: verified findings with `file:line` evidence; include what you
|
|
42
|
+
ruled out and why.
|
|
43
|
+
- **approach**: the chosen approach AND at least one rejected alternative
|
|
44
|
+
with the reason. A plan with no considered alternative is a guess.
|
|
45
|
+
- **tasks**: 3-8 concrete, independently verifiable steps, each doable in one
|
|
46
|
+
sitting. A task like "improve the code" is invalid; "extract timeout
|
|
47
|
+
constant into config.ts and default it to 3000" is valid.
|
|
48
|
+
- **risks**: what could break, blast radius, rollback path.
|
|
49
|
+
- **acceptance**: criteria you can verify with a command, a file, or an
|
|
50
|
+
observable behavior. Vague criteria will fail the plan_close self-check.
|
|
51
|
+
- **nonGoals**: explicit out-of-scope items (what the user might expect but
|
|
52
|
+
will NOT get).
|
|
53
|
+
|
|
54
|
+
Revising: calling `plan_write` again while still in draft overwrites the same
|
|
55
|
+
file. Do this after user feedback instead of hand-editing.
|
|
56
|
+
|
|
57
|
+
## Phase 3 — Approval gate (plan_approve)
|
|
58
|
+
|
|
59
|
+
Present to the user, briefly: goal, chosen approach (one line why), the
|
|
60
|
+
numbered task list, and the acceptance criteria. Then call `plan_approve`.
|
|
61
|
+
The user confirms in a dialog — that confirmation IS the approval. If they
|
|
62
|
+
object, revise with `plan_write` and present again. Never proceed to
|
|
63
|
+
implementation before approval succeeds.
|
|
64
|
+
|
|
65
|
+
## Phase 4 — Execution (tick as you go)
|
|
66
|
+
|
|
67
|
+
- Execute tasks in order; after EACH task's work is actually done, call
|
|
68
|
+
`plan_tick` with its number immediately. Never batch ticks; never tick
|
|
69
|
+
ahead of reality — the tick timestamp is an audit trail.
|
|
70
|
+
- If mid-execution you discover the plan is wrong, do not silently improvise:
|
|
71
|
+
tell the user what changed and either finish the affected task anyway or
|
|
72
|
+
ask whether to revise (/plan with the same goal re-enters planning).
|
|
73
|
+
|
|
74
|
+
## Phase 5 — Completion gate (plan_close)
|
|
75
|
+
|
|
76
|
+
When all tasks are ticked: self-check EVERY acceptance criterion with
|
|
77
|
+
concrete evidence (`file:line`, command output, test result). Call
|
|
78
|
+
`plan_close` with one check per criterion, `pass` honest — a ✗ fails the
|
|
79
|
+
close and that is the design working, not an inconvenience. The user
|
|
80
|
+
confirms closure in a dialog.
|
|
81
|
+
|
|
82
|
+
## Boundaries
|
|
83
|
+
|
|
84
|
+
- **Abandon**: user cancels → `/plan discard` (or plan_discard). Terminal,
|
|
85
|
+
file kept as history, writes restored.
|
|
86
|
+
- **Resume**: new session with unfinished plan → the system notice carries
|
|
87
|
+
the path; `/plan resume` continues from the remaining tasks.
|
|
88
|
+
- **Spec-workflow boundary**: work expected to span multiple sessions, days
|
|
89
|
+
of multi-file change, or multi-round requirement review is spec work, not
|
|
90
|
+
plan work. Say so once (e.g. "this fits a spec workflow like OpenSpec
|
|
91
|
+
better"), let the user choose, and proceed with a plan only if they insist.
|