- 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>
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
- Use built-in
buildagent as primary (not portingpersonal-assistant) - All agents synced as subagents (SKIP_AGENTS kept empty for flexibility)
- Model inheritance - subagents use runtime-selected model
- Claude Code is source of truth - OpenCode references state files via
instructions - 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:
- Skills/scripts execution (highest priority)
- Agent hierarchy/delegation (second priority)
- 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- Hasclaude-synccommand 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-tools → metadata.claude_allowed_tools |
| Agents | ~/.claude/agents/*.md |
~/.config/opencode/agents/*.md |
tools: X, Y → tools: { 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:
opus→anthropic/claude-opus-4sonnet→anthropic/claude-sonnet-4-5haiku→anthropic/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
buildagent is optimized for OpenCode - Built-in
planagent 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- Hasname: gmail,description: ...sysadmin-health/SKILL.md- Hasname: sysadmin-health,description: ...morning-report/SKILL.md- Hasname: 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
Audit each SKILL.md for required frontmatterDone - already compatible!Add missingNot neededname/descriptionfields- 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
- personal-assistant.md →
mode: primary(main interface) - linux-sysadmin.md →
mode: subagent - k8s-orchestrator.md →
mode: subagent - 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
@agentmentions - 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
Option A: Symlink CLAUDE.md
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:
{file:path}variable substitution inopencode.jsoninstructionsarray for context files- 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
instructionsarray - 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: subagentto 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
instructionsarray (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 listshows 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:
-
Architecture Overview
- Relationship between Claude Code and OpenCode
- What's shared vs separate
- Source of truth (Claude Code)
-
Sync Workflow
- How
claude_sync.pyworks - When to run it (after Claude Code changes)
- Command reference
- How
-
Agent Mapping
- Which Claude Code agents map to OpenCode
- Which are skipped and why
- How to invoke subagents (@mentions)
-
Skills
- Auto-discovery from
~/.claude/skills/ - How to add new skills
- Skill invocation patterns
- Auto-discovery from
-
State Sharing
- Files referenced via
instructions - Claude Code as source of truth
- What stays separate
- Files referenced via
-
Permissions
- How guardrails translated to
permissionconfig - Safe vs prompted commands
- How guardrails translated to
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