Files
claude-code/plans/enumerated-giggling-scone.md
OpenCode Test 6be9bf5aff Mark OpenCode transposition plan as complete
- Implementation complete (2026-01-07)
- All steps verified: backup, sync script, config, testing, docs
- 40 agents discovered (built-in + synced)
- 10 skills, 27 commands, 10 workflows synced
- Manual TUI testing pending

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 13:45:59 -08:00

24 KiB

Plan: Transpose Claude Code Setup to OpenCode (Parallel)

Handoff Summary

Goal: Set up OpenCode in parallel with Claude Code, sharing state files and syncing agents/skills.

Status: IMPLEMENTATION COMPLETE (2026-01-07)

Key Decisions Made

  1. Use built-in build agent as primary (not porting personal-assistant)
  2. All agents synced as subagents (SKIP_AGENTS kept empty for flexibility)
  3. Model inheritance - subagents use runtime-selected model
  4. Claude Code is source of truth - OpenCode references state files via instructions
  5. No JSON minification needed (files too small, added to future considerations as fc-047)

What Was Completed

Step Status Notes
1 Backups created (Jan 7 12:01)
2 Sync script enhanced (mode:subagent, model removal)
3 Sync run: 10 skills, 13 agents, 27 commands, 10 workflows
4 opencode.json updated (instructions, permissions)
5 Automated tests passed, manual TUI testing pending
6 README.md created (4.7KB), fc-047 added
7 Iterate as needed

Critical Files

Modified:

  • ~/.config/opencode/scripts/claude_sync.py - Added mode:subagent, model removal, skip logic
  • ~/.config/opencode/opencode.json - Added instructions, permissions

Created:

  • ~/.config/opencode/README.md - Documentation (4.7KB)

Referenced (not copied):

  • ~/.claude/CLAUDE.md
  • ~/.claude/state/kb.json
  • ~/.claude/state/personal-assistant/memory/*.json

Architecture

OpenCode (after implementation)
├── Primary: build (built-in), plan (built-in)
├── Subagents: @linux-sysadmin, @k8s-orchestrator, @code-reviewer, etc.
├── Skills: auto-discovered from ~/.claude/skills/
└── State: referenced via instructions from ~/.claude/state/

Start Command

# Exit plan mode and begin implementation
# Step 1: Backup
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
tar -czvf ~/.config/opencode-backup-$BACKUP_DATE.tar.gz -C ~/.config opencode/
tar -czvf ~/opencode-home-backup-$BACKUP_DATE.tar.gz -C ~ .opencode/

Goal

Create a parallel OpenCode configuration that shares/reuses as much of the existing Claude Code infrastructure as possible, focusing on:

  1. Skills/scripts execution (highest priority)
  2. Agent hierarchy/delegation (second priority)
  3. State persistence (if low complexity)

Key Discovery: Native Compatibility

OpenCode natively supports Claude-compatible skill paths:

  • ~/.claude/skills/<name>/SKILL.md - Already supported!
  • This means your 11 existing skills can work with minimal changes

Phase 0: Backup Existing OpenCode Setup

Current State Discovered

OpenCode is already installed with substantial configuration:

~/.config/opencode/ (main config):

  • opencode.json - Has claude-sync command already!
  • agent/ - 3 custom agents (coding-expert, k8s-expert, tdd-enforcer)
  • agents/ - 12 synced Claude Code agents (already converted!)
  • skills/ - 10 skills (some synced, one symlink to morning-report)
  • scripts/claude_sync.py - Existing sync script!

~/.opencode/ (alternate config):

  • agent/ - 4 different agents (openagent, system-builder, etc.)
  • command/ - 12 commands (commit, optimize, validate-repo, etc.)

Backup Commands

# Create timestamped backups
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)

# Backup ~/.config/opencode/
tar -czvf ~/.config/opencode-backup-$BACKUP_DATE.tar.gz -C ~/.config opencode/

# Backup ~/.opencode/
tar -czvf ~/opencode-home-backup-$BACKUP_DATE.tar.gz -C ~ .opencode/

# Verify backups
ls -la ~/.config/opencode-backup-*.tar.gz ~/opencode-home-backup-*.tar.gz

Phase 1: Use Existing claude_sync.py Script

The existing sync script is comprehensive and handles:

Category Source Destination Transforms
Skills ~/.claude/skills/*/SKILL.md ~/.config/opencode/skills/*/SKILL.md allowed-toolsmetadata.claude_allowed_tools
Agents ~/.claude/agents/*.md ~/.config/opencode/agents/*.md tools: X, Ytools: { x: true, y: true }
Commands ~/.claude/commands/*.md ~/.config/opencode/claude/commands/*.md None
Workflows ~/.claude/workflows/*.yaml ~/.config/opencode/claude/workflows/*.yaml None

Sync Commands

# Dry run - see what would change
python3 ~/.config/opencode/scripts/claude_sync.py --dry-run

# Actually sync
python3 ~/.config/opencode/scripts/claude_sync.py

# Clean stale files (dry run first)
python3 ~/.config/opencode/scripts/claude_sync.py --clean --dry-run
python3 ~/.config/opencode/scripts/claude_sync.py --clean --apply

# Sync specific category only
python3 ~/.config/opencode/scripts/claude_sync.py --only agents

Model Mapping Update Needed

Current script maps old models. May need to add:

  • opusanthropic/claude-opus-4
  • sonnetanthropic/claude-sonnet-4-5
  • haikuanthropic/claude-haiku-4-5

Phase 1.5: OpenCode Optimization (NEW)

The current sync just copies/transforms files. It doesn't optimize for how OpenCode works.

Key OpenCode Differences

Concept Claude Code OpenCode Optimization Needed
Agent hierarchy PA → MO → agents Flat: primary + subagents Add mode field
Agent invocation Delegation patterns @agent mentions Simplify prompts
Permissions Hooks + guardrails permission config Move to opencode.json
Model selection Per-agent in frontmatter model: inherit option Use inheritance
Auto-invocation Keyword triggers in registry Rich description field Enhance descriptions

Agent Mode Assignment

# PRIMARY - Use OpenCode's built-in agents
build: (built-in)     # Full access, default primary
plan:  (built-in)     # Read-only analysis

# SKIP - Not needed in OpenCode's flat model
personal-assistant:    # Use built-in "build" instead
master-orchestrator:   # Intermediary not needed

# SUBAGENTS (invoked via @mention or Task tool)
linux-sysadmin:        mode: subagent
k8s-orchestrator:      mode: subagent
k8s-diagnostician:     mode: subagent
argocd-operator:       mode: subagent
prometheus-analyst:    mode: subagent
git-operator:          mode: subagent
programmer-orchestrator: mode: subagent
code-planner:          mode: subagent
code-implementer:      mode: subagent
code-reviewer:         mode: subagent

Hierarchy Simplification

Claude Code pattern (complex, 3 layers):

User → Personal Assistant → Master Orchestrator → linux-sysadmin
                                                → k8s-orchestrator → k8s-diagnostician

OpenCode pattern (flat, 2 layers):

User → build (built-in) → @linux-sysadmin
                        → @k8s-orchestrator
                        → @k8s-diagnostician
                        → @code-reviewer
                        → etc.

Benefits:

  • No custom primary agent to maintain
  • Built-in build agent is optimized for OpenCode
  • Built-in plan agent available for read-only analysis
  • Subagents invoked directly via @mention

Sync Script Enhancements Needed

Update claude_sync.py to add:

# In transform_frontmatter() for agents:

# 1. Skip agents not needed in OpenCode's flat model
SKIP_AGENTS = {"personal-assistant", "master-orchestrator"}

if name in SKIP_AGENTS:
    return None  # Signal to skip this file

# 2. All synced agents become subagents (built-in build/plan are primary)
frontmatter["mode"] = "subagent"

# 3. Use model inheritance (subagents use parent's model)
frontmatter["model"] = "inherit"

# 4. Map explicit models if not using inherit
MODEL_MAP = {
    "opus": "anthropic/claude-opus-4",
    "sonnet": "anthropic/claude-sonnet-4-5",
    "haiku": "anthropic/claude-haiku-4-5",
}
if frontmatter.get("model") in MODEL_MAP:
    frontmatter["model"] = MODEL_MAP[frontmatter["model"]]

Also update sync_tree() to handle None return (skip file).

Description Enhancement

OpenCode uses descriptions for auto-invocation. Enhance with examples:

Current (basic):

description: Manages Arch Linux workstation - system maintenance...

Optimized (with examples):

description: |
  Manages Arch Linux workstation. Use for system maintenance, updates,
  troubleshooting, and health checks.
  Examples:
  - "check system health" → @linux-sysadmin
  - "update packages" → @linux-sysadmin
  - "why is my disk full" → @linux-sysadmin

Permission Migration

Move guardrail logic to opencode.json:

{
  "permission": {
    "edit": "ask",
    "bash": {
      "*": "ask",
      "pacman -Q*": "allow",
      "systemctl status*": "allow",
      "kubectl get*": "allow",
      "git status": "allow",
      "git diff": "allow"
    }
  }
}

Phase 2: Create OpenCode Config Structure

Directory Layout

~/.config/opencode/
├── opencode.json          # Main config
├── AGENTS.md              # Global rules (symlink or copy from CLAUDE.md)
├── agent/                 # Agent definitions
│   ├── personal-assistant.md
│   ├── linux-sysadmin.md
│   ├── k8s-orchestrator.md
│   └── ... (converted agents)
├── tool/                  # Custom tool wrappers (TypeScript)
│   ├── gmail.ts           # Wrapper for gmail scripts
│   ├── gcal.ts            # Wrapper for gcal scripts
│   └── ...
└── skill/                 # OpenCode-native skills (optional)

Config File: ~/.config/opencode/opencode.json

{
  "$schema": "https://opencode.ai/config.json",
  "model": "anthropic/claude-sonnet-4-5",
  "small_model": "anthropic/claude-haiku-4-5",
  "autoupdate": true,

  // OpenCode already searches ~/.claude/skills/ - no extra config needed!

  // Agent definitions
  "agent": {
    // Override built-in agents or define custom via files
  },

  // Default permissions (conservative like your current setup)
  "permission": {
    "edit": "ask",
    "bash": "ask"
  },

  // Custom tools enabled
  "tools": {
    "gmail": true,
    "gcal": true,
    "gtasks": true
  }
}

Phase 3: Skills Migration

Already Compatible (No Changes Needed)

OpenCode automatically discovers skills from:

  • ~/.claude/skills/*/SKILL.md

Your existing skills should work if they have proper frontmatter:

Skill Status Notes
gmail Check frontmatter Needs name + description
gcal Check frontmatter Needs name + description
gtasks Check frontmatter Needs name + description
sysadmin-health Check frontmatter
k8s-quick-status Check frontmatter
morning-report Check frontmatter
stock-lookup Check frontmatter
rag-search Check frontmatter
usage Check frontmatter
guardrails N/A Becomes permission config

Frontmatter Requirements

Each SKILL.md needs:

---
name: skill-name          # Required, must match directory name
description: Brief desc   # Required, 1-1024 chars
---

Audit Results (Already Compatible!)

Checked skills have proper frontmatter:

  • gmail/SKILL.md - Has name: gmail, description: ...
  • sysadmin-health/SKILL.md - Has name: sysadmin-health, description: ...
  • morning-report/SKILL.md - Has name: morning-report, description: ...

The allowed-tools field in some skills will be ignored by OpenCode (not in their schema), but this is fine.

Action Items

  1. Audit each SKILL.md for required frontmatter Done - already compatible!
  2. Add missing name/description fields Not needed
  3. Test skill discovery in OpenCode after install

Phase 4: Agent Migration

Mapping Strategy

Claude Code OpenCode Notes
model: opus model: anthropic/claude-opus-4 Full provider/model path
model: sonnet model: anthropic/claude-sonnet-4-5
model: haiku model: anthropic/claude-haiku-4-5
tools: Read, Write... tools: { write: true, ... } Boolean map
Hierarchy (PA → MO → agent) mode: primary + mode: subagent Flattened

Agent Conversion Template

From (Claude Code):

---
name: linux-sysadmin
description: Manages Arch Linux workstation...
model: sonnet
tools: Bash, Read, Write, Edit, Grep, Glob
---

To (OpenCode):

---
name: linux-sysadmin
description: Manages Arch Linux workstation...
mode: subagent
model: anthropic/claude-sonnet-4-5
tools:
  bash: true
  read: true
  write: true
  edit: true
permission:
  bash:
    "*": ask
    "pacman -Q*": allow
    "systemctl status*": allow
---

Priority Agents to Convert

  1. personal-assistant.mdmode: primary (main interface)
  2. linux-sysadmin.mdmode: subagent
  3. k8s-orchestrator.mdmode: subagent
  4. master-orchestrator.md → May not be needed (OpenCode doesn't have same hierarchy)

Hierarchy Adaptation

OpenCode doesn't have hierarchical agent delegation like your current setup. Options:

  • Option A: Flatten to primary + subagents, use @agent mentions
  • Option B: Use OpenCode's Task tool for agent invocation
  • Option C: Create a "dispatcher" primary agent that routes via @mentions

Recommendation: Option A (simplest) - personal-assistant as primary, others as subagents invokable via @linux-sysadmin, @k8s-orchestrator, etc.


Phase 5: Custom Tools (Scripts Execution)

Wrapper Pattern

Create TypeScript wrappers that invoke your existing Python scripts:

Example: ~/.config/opencode/tool/gmail.ts

import { tool } from "@opencode-ai/plugin"

export const check_unread = tool({
  description: "Check unread emails from Gmail",
  args: {
    limit: tool.schema.number().optional().describe("Max emails to return"),
  },
  async execute(args) {
    const limit = args.limit ?? 10
    const result = await Bun.$`~/.claude/mcp/gmail/venv/bin/python ~/.claude/skills/gmail/scripts/check_unread.py --limit ${limit}`.text()
    return result.trim()
  },
})

export const search = tool({
  description: "Search Gmail for specific emails",
  args: {
    query: tool.schema.string().describe("Search query"),
  },
  async execute(args) {
    const result = await Bun.$`~/.claude/mcp/gmail/venv/bin/python ~/.claude/skills/gmail/scripts/search.py "${args.query}"`.text()
    return result.trim()
  },
})

Tools to Create Wrappers For

Script Wrapper
gmail/scripts/*.py gmail.ts
gcal/scripts/*.py gcal.ts
gtasks/scripts/*.py gtasks.ts
sysadmin-health/scripts/*.sh sysadmin.ts
morning-report/scripts/*.py morning.ts
stock-lookup/scripts/*.py stocks.ts

Phase 6: Rules/Instructions

ln -s ~/.claude/CLAUDE.md ~/.config/opencode/AGENTS.md

Option B: Create Minimal AGENTS.md + Reference

# OpenCode Agent Rules

Read @~/.claude/CLAUDE.md for shared conventions.

## OpenCode-Specific

- Use `@agent-name` to invoke subagents
- Skills are loaded via the `skill` tool
- Custom tools available: gmail, gcal, gtasks, sysadmin

Option C: Use instructions config

{
  "instructions": ["~/.claude/CLAUDE.md", "~/.claude/state/system-instructions.json"]
}

Recommendation: Option C - cleanest, no duplication


Phase 7: State Persistence (Claude Code as Source of Truth)

Strategy

Claude Code owns the state files. OpenCode reads them via:

  1. {file:path} variable substitution in opencode.json
  2. instructions array for context files
  3. Skills that read state files directly

What Can Be Shared

File Method Notes
~/.claude/CLAUDE.md instructions Global rules
~/.claude/state/kb.json instructions or skill Knowledge base
~/.claude/state/personal-assistant/memory/*.json instructions Memory context
~/.claude/state/system-instructions.json instructions Process definitions

Implementation in opencode.json

{
  "$schema": "https://opencode.ai/config.json",

  // Load Claude Code state as instructions (read at session start)
  "instructions": [
    "~/.claude/CLAUDE.md",
    "~/.claude/state/kb.json",
    "~/.claude/state/personal-assistant/memory/facts.json",
    "~/.claude/state/personal-assistant/memory/preferences.json"
  ]
}

What Stays Separate

Item Reason
Session history Different formats, different storage
Autonomy/permissions OpenCode uses permission config instead
Component registry OpenCode discovers via file paths

Overhead Assessment

Low overhead - just config changes:

  • Add paths to instructions array
  • No symlinks or sync scripts needed
  • OpenCode reads files directly at session start
  • Claude Code continues to write/update normally

Phase 8: What Won't Transfer

Feature Claude Code OpenCode Alternative
Hooks (SessionStart, etc.) hooks/hooks.json Plugins (future)
Guardrails hook PreToolUse script permission config
Component registry routing Keyword triggers Agent descriptions + @mentions
Hierarchical delegation PA → MO → agent Flat subagent model

Implementation Order

Step 1: Backup (5 min) COMPLETE

  • Create timestamped backup of ~/.config/opencode/opencode-backup-20260107_120135.tar.gz
  • Create timestamped backup of ~/.opencode/opencode-home-backup-20260107_120136.tar.gz

Step 2: Enhance Sync Script (45 min) COMPLETE

  • Add skip list: SKIP_AGENTS (kept empty - all agents synced as subagents)
  • Add mode: subagent to all synced agents
  • Remove hardcoded model (agents inherit from runtime selection)
  • Add model stripping from opencode.json
  • Update sync_tree() to handle skipped files
  • Optionally enhance descriptions with examples (deferred)

Step 3: Run Enhanced Sync (10 min) COMPLETE

  • python3 ~/.config/opencode/scripts/claude_sync.py --dry-run
  • Review output - verify mode/model changes
  • python3 ~/.config/opencode/scripts/claude_sync.py
  • All synced: 10 skills, 13 agents, 27 commands, 10 workflows

Step 4: Update opencode.json (20 min) COMPLETE

  • Add instructions array (CLAUDE.md, kb.json, memory files)
  • Model defaults: intentionally omitted (user selects at runtime)
  • Add permission config with safe command patterns

Step 5: Testing (30 min) COMPLETE (automated)

  • OpenCode v1.0.220 installed at /home/linuxbrew/.linuxbrew/bin/opencode
  • opencode agent list shows 40 agents (built-in + synced)
  • All Claude Code agents show as (subagent)
  • 10 skills synced to ~/.config/opencode/skills/
  • Config verified: instructions, permissions, commands present
  • Manual TUI testing (user to verify interactively)

Step 6: Documentation (20 min) COMPLETE

  • Create ~/.config/opencode/README.md (4.7KB)
  • Document complete agent mapping table
  • Document sync workflow with examples
  • Add fc-047 to ~/.claude/state/future-considerations.json

Step 7: Iterate (as needed) PENDING

  • Adjust agent descriptions if auto-invocation isn't working well
  • Tune permission patterns
  • Consider dropping/hiding agents that don't fit OpenCode model
  • Update documentation with lessons learned

Status: IMPLEMENTATION COMPLETE - Manual TUI testing recommended


Phase 8: Documentation

Documentation Deliverables

Create ~/.config/opencode/README.md with:

  1. Architecture Overview

    • Relationship between Claude Code and OpenCode
    • What's shared vs separate
    • Source of truth (Claude Code)
  2. Sync Workflow

    • How claude_sync.py works
    • When to run it (after Claude Code changes)
    • Command reference
  3. Agent Mapping

    • Which Claude Code agents map to OpenCode
    • Which are skipped and why
    • How to invoke subagents (@mentions)
  4. Skills

    • Auto-discovery from ~/.claude/skills/
    • How to add new skills
    • Skill invocation patterns
  5. State Sharing

    • Files referenced via instructions
    • Claude Code as source of truth
    • What stays separate
  6. Permissions

    • How guardrails translated to permission config
    • Safe vs prompted commands

Documentation Template

# OpenCode Configuration

This OpenCode setup is synchronized from Claude Code (`~/.claude/`).

## Quick Start

```bash
# Start OpenCode (uses built-in build agent)
opencode

# Switch to read-only plan agent
# Press Tab

# Invoke a subagent
@linux-sysadmin check system health

Architecture

Claude Code (source of truth)
├── ~/.claude/agents/          → synced to ~/.config/opencode/agents/
├── ~/.claude/skills/          → synced to ~/.config/opencode/skills/
├── ~/.claude/CLAUDE.md        → referenced via instructions
└── ~/.claude/state/           → referenced via instructions

OpenCode
├── Built-in: build (primary), plan (read-only)
├── Subagents: @linux-sysadmin, @k8s-orchestrator, etc.
└── Skills: gmail, gcal, sysadmin-health, etc.

Sync Workflow

After making changes in Claude Code:

# Preview changes
python3 ~/.config/opencode/scripts/claude_sync.py --dry-run

# Apply changes
python3 ~/.config/opencode/scripts/claude_sync.py

# Clean stale files
python3 ~/.config/opencode/scripts/claude_sync.py --clean --apply

Agents

Claude Code OpenCode Notes
personal-assistant (skipped) Use built-in build
master-orchestrator (skipped) Flat model, not needed
linux-sysadmin @linux-sysadmin Subagent
k8s-orchestrator @k8s-orchestrator Subagent
... ... ...

Skills

Skills are auto-discovered from:

  • ~/.claude/skills/*/SKILL.md
  • ~/.config/opencode/skills/*/SKILL.md

State Files

Referenced via instructions in opencode.json:

  • ~/.claude/CLAUDE.md - Global rules
  • ~/.claude/state/kb.json - Knowledge base
  • ~/.claude/state/personal-assistant/memory/*.json - Memory

Permissions

Configured in opencode.json permission section. Migrated from Claude Code's guardrail hooks.


### Implementation Step

Add to Step 6:
- [ ] Create `~/.config/opencode/README.md`
- [ ] Document sync workflow
- [ ] Document agent mapping
- [ ] Document any gotchas discovered during testing

---

## Files to Create/Modify

### Files to Create
- `~/.config/opencode/README.md` - Documentation of setup, workflow, and requirements

### Files to Modify
- `~/.config/opencode/opencode.json` - Add `instructions` array + model/permission config
- `~/.config/opencode/scripts/claude_sync.py` - Add mode, model mappings, skip list

### Files Auto-Synced by Script
These are created/updated by `claude_sync.py`:
- `~/.config/opencode/agents/*.md` - From `~/.claude/agents/`
- `~/.config/opencode/skills/*/SKILL.md` - From `~/.claude/skills/`
- `~/.config/opencode/claude/commands/*.md` - From `~/.claude/commands/`
- `~/.config/opencode/claude/workflows/*.yaml` - From `~/.claude/workflows/`

### Files Referenced (Not Copied)
These stay in Claude Code, referenced via `instructions`:
- `~/.claude/CLAUDE.md`
- `~/.claude/state/kb.json`
- `~/.claude/state/personal-assistant/memory/*.json`

---

## Success Criteria

1. `opencode` launches and shows available skills
2. Can invoke `@linux-sysadmin` and get expected behavior
3. Gmail/GCal/GTasks tools work via custom wrappers
4. Can switch between build/plan agents + custom agents
5. Both Claude Code and OpenCode can run in parallel without conflicts