omo-slim-plan
v0.1.1
Published
Lightweight plan-first workflow for OpenCode + oh-my-opencode-slim: plan → human gate → start-work → acceptance
Maintainers
Readme
omo-slim-plan
Lightweight plan-first workflow for OpenCode + oh-my-opencode-slim: AI writes a decision-complete plan first, a human chooses what happens next, execution updates checkboxes in the plan file, and webhook notifications (Telegram primary, extensible) fire at the gate points. Not full omo/ultrawork — no boulder, no dual-review, no CAS.
/plan → .plans/<slug>.md (status: ready) → human gate
│
├─ start-work <slug> → execute, sync checkboxes
│ └─ all done → awaiting-acceptance → human accept → status: accepted
├─ plan-review <slug> → @oracle review → Notes → back to gate
└─ revise → edit plan, stay readyFeatures
/plan— explore the repo, write a decision-complete plan to.plans/<slug>.md, setstatus: ready, stop for a human choice. Never implements product code./start-work— execute an existing plan, update- [ ]→- [x]after each verified todo, present an acceptance summary when done, wait for human accept/reject./plan-review— delegate plan review to theoracleagent, write findings into the plan## Notes, return to the human gate.- Checkbox progress as source of truth — the plan file is the only progress ledger; no completion claims without checked boxes.
- Telegram + extensible webhooks — Telegram Bot API by default; generic JSON POST; local command provider; all behind a small provider map you can extend.
Requirements
- OpenCode + oh-my-opencode-slim (agents: explorer / fixer / designer / oracle / librarian)
- Node.js 18+ (installer and plugin use only
node:builtins — zero npm runtime dependencies)
Install
npx omo-slim-plan
# or from GitHub
npx github:Daedalusys/omo-slim-planFrom a local checkout:
node bin/install.js # install
node bin/install.js --dry-run # preview only
node bin/install.js --helpWhat the installer does:
| Step | Destination |
|------|-------------|
| Commands | ~/.config/opencode/command/{plan,start-work,plan-review}.md |
| Skill | ~/.config/skillshare/skills/plan-workflow/SKILL.md if skillshare exists, else ~/.config/opencode/skills/plan-workflow/ |
| Plugin | ~/.config/opencode/plugin/{planflow.js,planflow-notify.mjs,planflow-providers.mjs} |
| Config | ~/.config/opencode/planflow.json (created if missing; never clobbered unless --force) |
| Plugin registration | "planflow" added to the plugin array in ~/.config/opencode/opencode.json |
OPencode_CONFIG overrides the config root. --config <path> sets it too (directory, or a planflow.json path). Existing targets are backed up to *.bak-<timestamp> before overwrite. After install: restart OpenCode.
Configure Telegram (first run)
You only need a bot token first. chat_id is captured interactively — no manual lookup.
- Talk to @BotFather →
/newbot→ copy the bot token. - Install / run setup (chat_id optional on the command line):
npx omo-slim-plan --telegram-token "123456:ABC-your-token"
# re-run anytime
npx omo-slim-plan --setup-telegram- The installer calls Telegram
getMe, prints your bot username, and asks you to message the bot (any text, e.g./start). - It polls
getUpdatesand shows the captured message:
捕获到消息:
chat_id : 123456789
chat_type : private
from : lofibass (@lofibass)
text : hi- Confirm
[Y/n]→chat_idis saved to~/.config/opencode/planflow.json(provider=telegram). - A test message (
Telegram 配置成功) is sent to verify the path.
If provider is telegram but chatId is empty, notifications report telegram_not_configured until setup completes — re-run --setup-telegram.
Manual config still works: set webhook.telegram.botToken + chatId in planflow.json, or pass both flags:
node bin/install.js --telegram-token "123456:ABC..." --telegram-chat-id "-1001234567890"Event toggles
| event | default | when |
|-------|---------|------|
| plan-ready | on | plan written, status: ready |
| awaiting-review | on | /plan-review starts (oracle review) |
| task-done | off | each todo completed during /start-work |
| awaiting-acceptance | on | all Todos + Final checks done |
| test | n/a | setup test notification (always allowed) |
Set any event to false to silence it. A missing/unconfigured provider never blocks the workflow — notify failures are logged and work continues.
Custom webhook providers
Provider map lives in plugin/planflow-providers.mjs:
export const PROVIDERS = {
telegram: telegramProvider, // POST api.telegram.org
generic: genericProvider, // POST JSON to webhook.generic.url
command: commandProvider, // run local command via spawn
};Generic provider
"webhook": {
"provider": "generic",
"generic": {
"url": "https://example.com/hooks/planflow",
"headers": { "Authorization": "Bearer ..." }
}
}Payload shape:
{
"event": "plan-ready",
"plan": ".plans/foo.md",
"title": "[omo-slim-plan] Plan ready: foo",
"message": "Plan .plans/foo.md status: ready",
"remaining": 3,
"session": "",
"source": "omo-slim-plan"
}Command provider
"webhook": {
"provider": "command",
"command": { "cmd": "curl -s -X POST -d \"$PLANFLOW_MESSAGE\" https://example.com/hook" }
}- Executes with
spawn(non-interactive, 10s timeout). No shell interpolation of untrusted text into the command — values go through env only:PLANFLOW_EVENT,PLANFLOW_PLAN,PLANFLOW_TITLE,PLANFLOW_MESSAGE,PLANFLOW_REMAINING
- Optional placeholders in
cmd:{{event}},{{plan}},{{title}},{{message}},{{remaining}}— substituted only from the same caller-controlled safe strings, shell-escaped.
Adding your own provider
- Write
async function myProvider(cfg, payload) { return { ok: true }; }inplanflow-providers.mjs. - Register it:
export const PROVIDERS = { ..., my: myProvider }. - Set
"webhook": { "provider": "my", "my": { ... } }inplanflow.json.
Contract: return { ok, skipped?, reason?, status?, error? }; never throw; treat missing config as { ok: false, reason: "my_not_configured" }.
Workflow overview
flowchart TD
A["User: plan this request"] --> B["/plan — explore repo (read-only)"]
B --> C["Write .plans/<slug>.md<br/>status: ready"]
C --> D["notify plan-ready"]
D --> E{"Human gate"}
E -->|"start-work <slug>"| F["/start-work — execute todos"]
E -->|"plan-review <slug>"| G["/plan-review — @oracle → Notes"]
E -->|"revise"| B
G --> E
F --> H["Sync checkboxes after each todo"]
H --> I{"All todos + F1-F3 done?"}
I -->|no| F
I -->|yes| J["status: done · notify awaiting-acceptance"]
J --> K{"Human accept?"}
K -->|accept| L["status: accepted ✓"]
K -->|reject| FPlan file contract (excerpt):
# my-feature
- status: ready
- created: 2026-01-01
- slug: my-feature
## TL;DR
## Scope
## Must-NOT
## Todos
- [ ] 1. <title>
- 验收: <agent-executable criteria>
- 证据: <exact command or path>
## Final checks
- [ ] F1. 计划符合度
- [ ] F2. 质量与测试通过
- [ ] F3. 与 Scope/Must-NOT 一致
## NotesStatus machine: draft → ready → (approved) → in-progress → done → accepted.
Full contract: the installed plan-workflow skill (~/.config/opencode/skills/plan-workflow/SKILL.md or skillshare equivalent).
Plans convention (.plans/)
- One plan per file:
.plans/<slug>.md(lowercase-hyphen slug). - Located in each project's project root — the installer never drops plans into random projects.
- Default: commit plans into the project repo (they are small and reviewable). Do not commit boulder-style heavy artifacts. Teams that want plans local-only can gitignore
.plans/. - See
templates/plans/README.mdfor the copy-able directory README.
Uninstall
npx omo-slim-plan --uninstall
# or from a checkout
node bin/install.js --uninstallRemoves installed commands, the skill, plugin files, and "planflow" from opencode.json's plugin array. Keeps planflow.json (your tokens) unless you pass --force. Project .plans/ directories are never touched.
Security
- Never commit
planflow.json— it may contain Telegram bot tokens or webhook URLs. The file lives in~/.config/opencode/, outside your project repo. - Tokens are never logged by the plugin (provider errors are redacted).
- Command-provider messages are passed via environment variables, not interpolated into the command string.
- The installer refuses to write outside your OpenCode config root and skillshare root; every overwrite is backed up first.
- Notifications are best-effort side channels: an unconfigured or failing webhook never blocks plan/execute/acceptance.
License
MIT © 2026 omo-slim-plan maintainers
