Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ The plugin provides these tools to OpenCode:

| Tool | Description |
|------|-------------|
| `systematic_find_skills` | List available skills |
| `systematic_find_agents` | List available agents |
| `systematic_find_commands` | List available commands |
| `systematic_skill` | Load Systematic bundled skills |

The bootstrap skill instructs OpenCode to use the native `skill` tool to load non-Systematic skills.

## Configuration

Expand Down
142 changes: 14 additions & 128 deletions docs/plans/2026-01-20-systematic-implementation.md
Original file line number Diff line number Diff line change
Expand Up @@ -719,14 +719,15 @@ const getBootstrapContent = (config: SystematicConfig, compact = false): string
const configDir = path.join(homeDir, '.config/opencode')

const toolMapping = compact
? `**Tool Mapping:** TodoWrite->update_plan, Task->@mention, Skill->systematic_use_skill
? `**Tool Mapping:** TodoWrite->update_plan, Task->@mention, Skill->systematic_skill (Systematic), skill (native)

**Skills naming (priority order):** project: > user > sys:`
: `**Tool Mapping for OpenCode:**
When skills reference tools you don't have, substitute OpenCode equivalents:
- \`TodoWrite\` → \`update_plan\`
- \`Task\` tool with subagents → Use OpenCode's subagent system (@mention)
- \`Skill\` tool → \`systematic_use_skill\` custom tool
- \`Skill\` tool → \`systematic_skill\` (Systematic plugin skills)
- Native \`skill\` tool → non-Systematic skills
- \`Read\`, \`Write\`, \`Edit\`, \`Bash\` → Your native tools

**Skills naming (priority order):**
Expand All @@ -738,7 +739,7 @@ When skills reference tools you don't have, substitute OpenCode equivalents:
return `<SYSTEMATIC_WORKFLOWS>
You have access to structured engineering workflows via the systematic plugin.

**IMPORTANT: The using-systematic skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use systematic_use_skill to load "using-systematic" - that would be redundant. Use systematic_use_skill only for OTHER skills.**
**IMPORTANT: The using-systematic skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use systematic_skill to load "using-systematic" - that would be redundant. Use systematic_skill only for Systematic bundled skills and the native skill tool for everything else.**

${content}

Expand All @@ -760,7 +761,7 @@ export const SystematicPlugin = async ({ client, directory }: PluginContext) =>

return {
tool: {
systematic_use_skill: tool({
systematic_skill: tool({
description:
'Load and read a specific skill to guide your work. Skills contain proven workflows, mandatory processes, and expert techniques.',
args: {
Expand Down Expand Up @@ -790,9 +791,9 @@ export const SystematicPlugin = async ({ client, directory }: PluginContext) =>
projectSkillsDir
)

if (!resolved) {
return `Error: Skill "${skill_name}" not found.\n\nRun systematic_find_skills to see available skills.`
}
if (!resolved) {
return `Error: Skill "${skill_name}" not found.\n\nUse the systematic_skill tool description to see available Systematic skills.`
}

const fullContent = fs.readFileSync(resolved.skillFile, 'utf8')
const { name, description } = skillsCore.extractFrontmatter(resolved.skillFile)
Expand Down Expand Up @@ -826,120 +827,7 @@ export const SystematicPlugin = async ({ client, directory }: PluginContext) =>
},
}),

systematic_find_skills: tool({
description:
'List all available skills in the project, user, and bundled skill libraries.',
args: {},
execute: async (): Promise<string> => {
const projectSkills = skillsCore.findSkillsInDir(projectSkillsDir, 'project', 3)
const userSkills = skillsCore.findSkillsInDir(userSkillsDir, 'user', 3)
const bundledSkills = skillsCore.findSkillsInDir(bundledSkillsDir, 'bundled', 3)

// Filter disabled skills
const filterDisabled = (skills: skillsCore.SkillInfo[]) =>
skills.filter((s) => !config.disabled_skills.includes(s.name))

const allSkills = [
...filterDisabled(projectSkills),
...filterDisabled(userSkills),
...filterDisabled(bundledSkills),
]

if (allSkills.length === 0) {
return `No skills found. Add skills to ${bundledSkillsDir}/ or ${userSkillsDir}/`
}

let output = 'Available skills:\n\n'

for (const skill of allSkills) {
let namespace: string
switch (skill.sourceType) {
case 'project':
namespace = 'project:'
break
case 'user':
namespace = ''
break
default:
namespace = 'sys:'
}

output += `${namespace}${skill.name}\n`
if (skill.description) {
output += ` ${skill.description}\n`
}
output += ` Directory: ${skill.path}\n\n`
}

return output
},
}),

systematic_find_agents: tool({
description: 'List all available review agents.',
args: {},
execute: async (): Promise<string> => {
const projectAgents = skillsCore.findAgentsInDir(projectAgentsDir, 'project')
const userAgents = skillsCore.findAgentsInDir(userAgentsDir, 'user')
const bundledAgents = skillsCore.findAgentsInDir(bundledAgentsDir, 'bundled')

const seen = new Set<string>()
const agents: Array<{ name: string; sourceType: string }> = []

for (const list of [projectAgents, userAgents, bundledAgents]) {
for (const agent of list) {
if (seen.has(agent.name)) continue
if (config.disabled_agents.includes(agent.name)) continue
seen.add(agent.name)
agents.push({ name: agent.name, sourceType: agent.sourceType })
}
}

if (agents.length === 0) {
return 'No agents available.'
}

let output = 'Available agents:\n\n'
for (const agent of agents.sort((a, b) => a.name.localeCompare(b.name))) {
output += `- ${agent.name} (${agent.sourceType})\n`
}

return output
},
}),

systematic_find_commands: tool({
description: 'List all available commands.',
args: {},
execute: async (): Promise<string> => {
const projectCommands = skillsCore.findCommandsInDir(projectCommandsDir, 'project')
const userCommands = skillsCore.findCommandsInDir(userCommandsDir, 'user')
const bundledCommands = skillsCore.findCommandsInDir(bundledCommandsDir, 'bundled')

const seen = new Set<string>()
const commands: Array<{ name: string; sourceType: string }> = []

for (const list of [projectCommands, userCommands, bundledCommands]) {
for (const cmd of list) {
if (seen.has(cmd.name)) continue
if (config.disabled_commands.includes(cmd.name)) continue
seen.add(cmd.name)
commands.push({ name: cmd.name, sourceType: cmd.sourceType })
}
}

if (commands.length === 0) {
return 'No commands available.'
}

let output = 'Available commands:\n\n'
for (const cmd of commands.sort((a, b) => a.name.localeCompare(b.name))) {
output += `- ${cmd.name} (${cmd.sourceType})\n`
}

return output
},
}),
// system lists provided by config hook; no find_* tools
},

event: async () => {
Expand Down Expand Up @@ -1837,10 +1725,8 @@ You have access to structured engineering workflows via the systematic plugin. T

## Available Tools

- `systematic_use_skill` - Load a skill to guide your work
- `systematic_find_skills` - List all available skills
- `systematic_find_agents` - List available review agents
- `systematic_find_commands` - List available commands
- `systematic_skill` - Load Systematic bundled skills
- Native `skill` tool - Load non-Systematic skills

## Core Workflow

Expand Down Expand Up @@ -1883,7 +1769,7 @@ Each unit of work should make subsequent work easier:
- Build on prior knowledge
- Compound your engineering

When a skill might apply to your current task, use `systematic_use_skill` to load it. Skills provide proven workflows for common engineering tasks.
When a skill might apply to your current task, use `systematic_skill` for Systematic bundled skills or the native `skill` tool for everything else.
```

**Step 2: Commit**
Expand All @@ -1910,7 +1796,7 @@ Port these skills from Superpowers with full content:

**For each skill:**
1. Fetch the full SKILL.md content from Superpowers repo
2. Adapt tool references (Skill → systematic_use_skill, TodoWrite → update_plan)
2. Adapt tool references (Skill → systematic_skill for Systematic skills, Skill → native skill for non-Systematic, TodoWrite → update_plan)
3. Update namespace references (superpowers: → sys:)
4. Save to `skills/<name>/SKILL.md`
5. Commit individually
Expand Down Expand Up @@ -2022,7 +1908,7 @@ Full documentation with installation, usage, customization, and credits.
**Key Differences from Original Plan:**
- Uses `tool()` from `@opencode-ai/plugin/tool` (matches Superpowers exactly)
- Uses `experimental.chat.system.transform` for bootstrap injection (workaround for model reset issue per PR #228)
- `session.prompt()` still used for `systematic_use_skill` tool to inject skills into conversation
- `session.prompt()` still used for `systematic_skill` tool to inject skills into conversation
- Comprehensive bash test suite modeled after Superpowers
- Phase 5 explicitly requires FULL content porting, not placeholders
- Test setup creates isolated environment with fixtures
Expand Down
12 changes: 4 additions & 8 deletions docs/plans/2026-01-20-systematic-plugin-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,7 @@ export const SystematicPlugin = async ({ client, directory }) => {

return {
tool: {
systematic_use_skill: tool({...}),
systematic_find_skills: tool({...}),
systematic_find_agents: tool({...}),
systematic_find_commands: tool({...}),
systematic_skill: tool({...}),
},

// Workaround for session.prompt() model reset issue
Expand Down Expand Up @@ -260,10 +257,9 @@ export default SystematicPlugin

| Tool | Purpose |
| -------------------------- | --------------------------------- |
| `systematic_use_skill` | Load a skill into context |
| `systematic_find_skills` | List available skills (all tiers) |
| `systematic_find_agents` | List available agents |
| `systematic_find_commands` | List available commands |
| `systematic_skill` | Load Systematic bundled skills |

Use the native `skill` tool for non-Systematic skills.

### Bootstrap Injection

Expand Down
10 changes: 5 additions & 5 deletions skills/using-systematic/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This is not negotiable. This is not optional. You cannot rationalize your way ou

## How to Access Skills

Use the `skill` tool. When you invoke a skill, its content is loaded and presented to you—follow it directly.
Use the `systematic_skill` tool for Systematic bundled skills. Use the native `skill` tool for non-Systematic skills. When you invoke a skill, its content is loaded and presented to you—follow it directly.

# Using Skills

Expand All @@ -25,17 +25,17 @@ Use the `skill` tool. When you invoke a skill, its content is loaded and present
digraph skill_flow {
"User message received" [shape=doublecircle];
"Might any skill apply?" [shape=diamond];
"Invoke `skill` tool" [shape=box];
"Invoke `systematic_skill` tool" [shape=box];
"Announce: 'Using [skill] to [purpose]'" [shape=box];
"Has checklist?" [shape=diamond];
"Create todo per item" [shape=box];
"Follow skill exactly" [shape=box];
"Respond (including clarifications)" [shape=doublecircle];

"User message received" -> "Might any skill apply?";
"Might any skill apply?" -> "Invoke `skill` tool" [label="yes, even 1%"];
"Might any skill apply?" -> "Invoke `systematic_skill` tool" [label="yes, even 1%"];
"Might any skill apply?" -> "Respond (including clarifications)" [label="definitely not"];
"Invoke `skill` tool" -> "Announce: 'Using [skill] to [purpose]'";
"Invoke `systematic_skill` tool" -> "Announce: 'Using [skill] to [purpose]'";
"Announce: 'Using [skill] to [purpose]'" -> "Has checklist?";
"Has checklist?" -> "Create todo per item" [label="yes"];
"Has checklist?" -> "Follow skill exactly" [label="no"];
Expand Down Expand Up @@ -91,4 +91,4 @@ Skills are resolved in priority order:
2. **User skills**: `~/.config/opencode/skills/`
3. **Bundled skills**: Provided by systematic plugin

Use `systematic_find_skills` to see all available skills and their sources.
Systematic bundled skills are listed in the `systematic_skill` tool description. Use the native `skill` tool for skills outside the Systematic plugin.
Loading