@guyghost/opencode-dao
v2.0.0
Published
OpenCode DAO Plugin - 4-layer governance with AI agent swarm deliberation
Maintainers
Readme
OpenCode DAO Plugin
A 4-layer DAO governance plugin for OpenCode with AI agent swarm deliberation, self-amending capabilities, and multi-platform sync.
📚 Based on pi-swarm-dao architecture
What is this?
OpenCode DAO implements a decentralized autonomous organization governance system where specialized AI agents deliberate on proposals via weighted voting. The system handles the full lifecycle—from proposal creation through deliberation, quality control, and execution—with a complete audit trail.
Architecture
┌─────────────────────────────────────────────────┐
│ L1 Governance │
│ Proposals · Voting · Quorum · Amendments │
├─────────────────────────────────────────────────┤
│ L2 Intelligence │
│ 7 Specialized Agents · Parallel Deliberation │
├─────────────────────────────────────────────────┤
│ L3 Delivery │
│ Execution Plans · Tasks · Release Artifacts │
├─────────────────────────────────────────────────┤
│ L4 Control │
│ Quality Gates · Audit Trail · Checklists │
└─────────────────────────────────────────────────┘Compatibility
| opencode-dao | @opencode-ai/plugin | OpenCode CLI | Bun |
| -------------- | --------------------- | ------------ | ------- |
| 1.1.x | >=1.14.19 | >=1.14.19 | >=1.3 |
| 1.0.x | ^1.14.0 | >=1.14.0 | >=1.3 |
The plugin declares engines.opencode in package.json; OpenCode's plugin
loader will skip (with a warning) any plugin whose declared range does not
satisfy the running CLI version. @opencode-ai/plugin is a peerDependency
to ensure the host process and the plugin share the same SDK instance.
Installation (from source)
Prerequisites: Bun >= 1.3
git clone [email protected]:guyghost/opencode-dao.git
cd opencode-dao
bun install
bun test # should show 130/130 passInstallation (as an OpenCode plugin)
Copy this plugin to your OpenCode plugins directory:
~/.config/opencode/plugins/opencode-dao/Or reference from your config:
{
"plugin": ["opencode-dao"]
}Quick Start
# 1. Initialize DAO with 7 default agents
> dao_setup
# 2. (Optional but recommended) Create per-project config
> dao_config_init mode="suggest"
# 3. Create a proposal
> dao_propose title="Add dark mode" type="product-feature" \
description="..." problemStatement="..." acceptanceCriteria=["..."]
# 4. Plan deliberation — returns a dispatch plan
> dao_deliberate proposalId=1
# → The assistant then spawns each @dao-* subagent in parallel
# via the built-in `task` tool, following the returned plan.
# 5. Record collected outputs to finalize the vote
> dao_record_outputs proposalId=1 outputs=[...]
# 6. Run quality gates
> dao_control proposalId=1
# 7. Execute
> dao_execute proposalId=1
# → If a forge (GitHub/GitLab/Bitbucket) is enabled, dao_execute
# suggests branch + PR/MR commands to open a review.
# 8. (Optional) Open a PR/MR when forge integration is enabled
> dao_github_create_branch proposalId=1 # creates remote branch
# → push your commits, then:
> dao_github_open_pr proposalId=1 headBranch="dao/1-add-dark-mode"Slash commands
The plugin ships 12 ready-to-use slash commands that wrap the most
common DAO flows so you don't have to type the underlying tool calls.
They are auto-installed into <your-project>/.opencode/commands/dao/
the first time you run dao_setup. Re-running is idempotent — local
edits are preserved unless you pass force: true to
dao_install_commands.
| Command | What it does |
|----------------------------------|-----------------------------------------------------------------------|
| /dao/init | Bootstrap the DAO with the 7 default agents |
| /dao/status | Concise overview: proposals + agents + recommended next action |
| /dao/propose <free-form text> | Create a proposal from a natural-language description |
| /dao/deliberate <id> | Generate the swarm dispatch plan (preview) |
| /dao/decide <id> | Run full deliberation end-to-end: spawn swarm + tally + synthesize |
| /dao/vote <id> <for\|against\|abstain> <reasoning> | Cast a manual human vote |
| /dao/show <id> | Show full proposal details (votes, scores, synthesis) |
| /dao/plan <id> | Show the delivery plan for an approved proposal |
| /dao/execute <id> | Run quality gates and execute |
| /dao/forge <id> | Open a PR/MR on whichever forge is enabled (GitHub/GitLab/Bitbucket) |
| /dao/amend <free-form text> | Propose a self-amendment to the DAO (agents, config, quorum, gates) |
| /dao/audit [id] | Show the audit trail (full DAO-wide, or scoped to a single proposal) |
Want to install or refresh them manually (e.g. globally across all projects):
> dao_install_commands scope="project" # default: <cwd>/.opencode/commands/dao/
> dao_install_commands scope="global" # ~/.config/opencode/commands/dao/
> dao_install_commands force=true # overwrite local editsHow deliberation actually runs
OpenCode plugins cannot programmatically spawn subagents, so the swarm runs in two steps orchestrated by the primary assistant:
dao_deliberatevalidates the proposal, transitions it todeliberating, and returns a markdown dispatch plan that lists the OpenCode subagents (@dao-strategist,@dao-architect, …) the primary agent should spawn in parallel via the built-intasktool.dao_record_outputsingests the collected subagent responses, parses votes and composite-score inputs, runs synthesis, and transitions the proposal toapprovedorrejected.
The 7 product agents live as native OpenCode subagents under
agent/dao-*.md. Each file declares its system prompt, allowed tools,
temperature, and (importantly) the strict output format the DAO
parses — ## Vote, ## Reasoning, ## Composite Score Inputs (0-10),
## Risk Score (1-10).
Activation modes
Configure how aggressively the DAO interjects in normal coding sessions
via .dao/config.json:
| Mode | Behavior |
|------|----------|
| opt-in (default) | Tools are available but never auto-invoked. |
| suggest | The plugin watches user messages for trigger keywords (feature, refactor, migration, security, …) and nudges the assistant to consider a DAO proposal first. |
| enforce | write / edit / patch operations on critical paths (auth, payment, migrations, env, secrets — configurable globs) are blocked unless an approved proposal references the path. |
Initialize with:
> dao_config_init mode="enforce"
> dao_config_showTools
Core Tools
| Tool | Layer | Description |
|------|-------|-------------|
| dao_setup | L1 | Initialize DAO with 7 default agents |
| dao_config_init | — | Create per-project .dao/config.json |
| dao_config_show | — | Display merged effective configuration |
| dao_suggest | — | Analyze text and return a structured DAO-invocation suggestion |
| dao_propose | L1 | Create a new proposal (supports affectedPaths for enforce mode) |
| dao_deliberate | L2 | Plan deliberation (returns subagent dispatch plan) |
| dao_record_outputs | L2 | Ingest subagent outputs and finalize vote |
| dao_control | L3 | Run quality gates |
| dao_execute | L4 | Execute proposal |
| dao_list | L1 | List all proposals |
| dao_agents | L1 | List all agents |
| dao_audit | L3 | View audit trail |
| dao_plan | L4 | Get delivery plan |
Amendment Tools (Self-Amending DAO)
| Tool | Description |
|------|-------------|
| dao_propose_amendment | Propose DAO change (agents, config, quorum, gates) |
| dao_preview_amendment | Preview changes before execution |
| dao_execute_amendment | Execute approved amendment |
Integration Tools
| Tool | Description |
|------|-------------|
| dao_config_github | Configure GitHub integration |
| dao_config_gitlab | Configure GitLab integration |
| dao_config_bitbucket | Configure Bitbucket integration |
| dao_sync | Sync proposals to external platforms |
Forge Tools (PR/MR + Branch)
Each forge provides a pair of tools to create a remote branch and open a pull/merge request. Branch names default to dao/<id>-<slug> derived from the proposal title.
| Tool | Key Args | Description |
|------|----------|-------------|
| dao_github_open_pr | proposalId, headBranch, baseBranch?, draft?, linkedIssue? | Open a GitHub pull request |
| dao_github_create_branch | proposalId, branchName?, baseBranch? | Create a remote branch on GitHub |
| dao_gitlab_open_mr | proposalId, sourceBranch, targetBranch? | Open a GitLab merge request |
| dao_gitlab_create_branch | proposalId, branchName?, baseBranch? | Create a remote branch on GitLab |
| dao_bitbucket_open_pr | proposalId, sourceBranch, targetBranch? | Open a Bitbucket pull request |
| dao_bitbucket_create_branch | proposalId, branchName?, baseBranch? | Create a remote branch on Bitbucket |
Standalone CLI
The opencode-dao binary provides direct access to DAO state for inspection and lightweight authoring — no OpenCode runtime required.
bun run src/cli.ts <command> [options]Commands
| Command | Description |
|---------|-------------|
| init | Initialize .dao/ in the current directory |
| propose | Create a new proposal (--title, --type, --description, --by) |
| list | List proposals (--status, --type filters) |
| show <id> | Show full proposal details |
| vote <id> | Cast a vote (--position, --reasoning, --weight, --agent) |
| execute <id> | (stub) Not available standalone — exits code 2 |
| config | Print current DAO configuration |
| audit | Print audit log (--proposal <id> filter) |
| status | Print DAO status summary |
| help | Print help text |
Examples
# Initialize DAO
bun run src/cli.ts init
# Create a proposal
bun run src/cli.ts propose --title "Add dark mode" --type product-feature --description "Implement dark theme"
# List open proposals
bun run src/cli.ts list --status open
# Vote on a proposal
bun run src/cli.ts vote 1 --position approve --reasoning "Low risk, high impact" --weight 2 --agent cli-user
# View proposal details
bun run src/cli.ts show 1Exit codes
| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | Error (invalid args, not found, etc.) |
| 2 | Intentionally unsupported (execute is a stub) |
Note: Deliberation, synthesis, and execution require the OpenCode runtime with AI sub-agents. The
votecommand is the deterministic exception — it works without any AI.
7 Default Agents
| Agent | Weight | Role | |-------|--------|------| | Product Strategist | 3 | Business vision, objectives | | Research Agent | 2 | Market, competition, user signals | | Solution Architect | 3 | Technical options, tradeoffs | | Critic / Risk Agent | 3 | Risk scoring, objections | | Prioritization Agent | 2 | Impact/cost scoring | | Spec Writer | 1 | PRD, user stories | | Delivery Agent | 1 | Implementation plan |
Total weight: 15 · Quorum: 60% · Approval: 55%
Proposal Types
| Type | Emoji | Domain |
|------|-------|-------|
| product-feature | ✨ | New functionality |
| security-change | 🔒 | Permissions, security |
| technical-change | ⚙️ | Architecture, refactors |
| release-change | 📦 | Publication, rollback |
| governance-change | 📜 | DAO rules, quorum, agents |
Amendment Types
The DAO can self-amend via governance proposals:
| Type | Description |
|------|-------------|
| agent-update | Update agent properties (weight, role, model) |
| agent-add | Add new agent |
| agent-remove | Remove agent |
| config-update | Update DAO config |
| quorum-update | Update per-type quorum |
| gate-update | Add/remove quality gates |
Integrations
All three integrations support optional apiBase (for self-hosted instances) and defaultBranch (override auto-detected default) configuration fields.
GitHub
> dao_config_github token="ghp_..." owner="myorg" repo="myrepo" enabled=true
# Optional: apiBase="https://github.mycompany.com/api/v3" defaultBranch="main"
> dao_sync proposalId=1GitLab
> dao_config_gitlab token="glpat-" url="https://gitlab.com" projectId="mygroup/myproject" enabled=true
# Optional: apiBase="https://gitlab.mycompany.com" defaultBranch="main"
> dao_sync proposalId=1Bitbucket
> dao_config_bitbucket token="..." username="myuser" workspace="myworkspace" repo="myrepo" enabled=true
# Optional: apiBase="https://api.bitbucket.mycompany.net" defaultBranch="main"
> dao_sync proposalId=1The dao_sync tool creates issues on all enabled platforms and updates them as proposals progress through the lifecycle.
PR/MR Workflow
After a proposal is approved and executed, dao_execute automatically suggests the next steps for each enabled forge. A typical end-to-end flow:
# 1. Proposal approved via deliberation
> dao_control proposalId=1
> dao_execute proposalId=1
# → dao_execute prints execution result + forge-specific next steps
# 2. Create a branch (name auto-generated from proposal title)
> dao_github_create_branch proposalId=1
# → or dao_gitlab_create_branch / dao_bitbucket_create_branch
# 3. Push your commits to the branch, then open a PR/MR
> dao_github_open_pr proposalId=1 headBranch="dao/1-add-dark-mode"
# → or dao_gitlab_open_mr / dao_bitbucket_open_prProposal Lifecycle
open → deliberating → approved → controlled → executed
↘ rejected ↘ rejected ↘ failedControl Gates
| Gate | Severity | Purpose | |------|----------|---------| | quorum-quality | blocker | Quorum was met | | risk-threshold | warning | Risk below threshold | | vote-consensus | warning | No high-weight dissent | | zone-compliance | info | Zone requirements met |
Persistence
Storage Structure
Three storage locations live under .dao/ in the project directory:
state.json— Monolithic state snapshot (proposals, agents, config, audit log)proposals/NNN.json— Per-proposal sidecar files (complete records, all proposals)decisions/NNN.json— Compact decision summaries (resolved proposals only)decisions/index.json— Quick lookup index of all decisionsconfig.json— Per-project configuration (activation mode, agent overrides, gates)
ID Padding: All proposal and decision files use 3-digit zero-padded IDs (001.json, not 1.json) for proper alphabetical sorting.
Decisions vs Proposals:
proposals/contains ALL proposals with full data (open, deliberating, approved, executed, etc.)decisions/contains only resolved proposals (status not "open" or "deliberating") as compact summaries- Decisions are derived views, not separate entities — same ID references the same item
This structure follows the pi-swarm-dao standard for cross-project compatibility.
state.json— monolithic state: proposals index, votes, agent outputs, audit log.config.json— activation mode, agent overrides, gates, critical paths.proposals/<id>.json— per-proposal sidecar files (source of truth on read).
Sidecar behavior
- Read:
loadStatereconciles sidecars withstate.json; sidecar data wins for any proposal present in both. - Write:
saveStatewrites bothstate.jsonand every proposal sidecar. - Orphan cleanup: On each
saveState, sidecar files for proposals no longer in state are deleted. Non-JSON files inproposals/(.gitkeep,README, etc.) are preserved.
Project Structure
opencode-dao/
├── src/
│ ├── index.ts # Main plugin: tools + hooks
│ ├── cli.ts # Standalone CLI (opencode-dao binary)
│ ├── types.ts # Type definitions
│ ├── persistence.ts # State management (.dao/state.json)
│ ├── config.ts # Per-project config (.dao/config.json)
│ ├── governance/
│ │ ├── agents.ts # Default agent registry
│ │ ├── voting.ts # Vote parsing & tally
│ │ ├── scoring.ts # Composite scoring
│ │ ├── lifecycle.ts # State machine
│ │ └── amendments.ts # Self-amending system
│ ├── intelligence/
│ │ ├── swarm.ts # Subagent dispatch plan builder
│ │ └── synthesis.ts # Deliberation synthesis
│ ├── control/
│ │ └── gates.ts # Quality gates
│ ├── delivery/
│ │ ├── plans.ts # Delivery plans
│ │ └── execution.ts # Execution
│ └── integrations/
│ ├── github.ts # GitHub sync
│ ├── gitlab.ts # GitLab sync
│ └── bitbucket.ts # Bitbucket sync
├── tests/
│ ├── cli.test.ts # CLI command tests
│ ├── config.test.ts # Config unit + integration tests
│ ├── persistence.test.ts # Sidecar persistence tests
│ ├── github.test.ts # GitHub integration tests
│ ├── gitlab.test.ts # GitLab integration tests
│ └── bitbucket.test.ts # Bitbucket integration tests
├── agent/ # Native OpenCode subagents (one .md per DAO role)
│ ├── dao-strategist.md
│ ├── dao-researcher.md
│ ├── dao-architect.md
│ ├── dao-critic.md
│ ├── dao-prioritizer.md
│ ├── dao-spec-writer.md
│ └── dao-delivery.md
├── openspec/ # Change specs and context logs
└── package.jsonCustomizing agents
The 7 default agents are plain markdown files in agent/. To customize:
- Tweak prompts/tools/temperature: edit the YAML frontmatter or
body of any
agent/dao-*.md. - Disable an agent for this project: set
"agents": { "researcher": { "enabled": false } }in.dao/config.json. - Override a vote weight: set
"agents": { "critic": { "enabled": true, "weight": 5 } }. - Add a new agent permanently: use
dao_propose_amendmentwithamendmentType="agent-add"(and add a matchingagent/dao-<id>.md).
Tests
bun test # run all tests
bun test tests/cli.test.ts # run a single test file
bun test --grep "vote command" # run tests matching a nameRuns 103 tests across 6 files covering CLI commands, config validation,
persistence with sidecar files, and GitHub/GitLab/Bitbucket integration.
Uses bun:test (built-in, no dev deps required; needs Bun ≥ 1.3).
Development
Project layout
| Directory | Purpose |
|-----------|---------|
| src/ | Plugin source (index, CLI, governance, integrations, etc.) |
| tests/ | Test files (*.test.ts) |
| agent/ | OpenCode sub-agent markdown definitions |
| openspec/ | Change-context history (specs, context logs) |
Key scripts
bun test # run all tests
bun test tests/cli.test.ts # run a single test file
bun run src/cli.ts <command> # run the CLI in development
bun run src/index.ts # start the plugin entry (smoke test)Adding a test
Drop a *.test.ts file in tests/. Import sources with .ts extension:
import { describe, it, expect, beforeEach } from "bun:test";
import { myFunction } from "../src/myModule.ts";Adding source code
Place new modules under src/ (sub-directories are fine). For imports
between source files, use the .js extension (NodeNext convention; Bun
resolves .js to .ts automatically):
import { helper } from "./helper.js";Conventions
- Conventional commits:
feat:,fix:,refactor:,docs:,chore: - No new external dependencies without strong justification — the project deliberately has zero dev dependencies beyond Bun's built-in test runner
