Skip to content

Commit bf2aaa7

Browse files
authored
docs(readme.md): restructure AGENTS.md and add module documentation (#48)
1 parent decbf40 commit bf2aaa7

3 files changed

Lines changed: 239 additions & 222 deletions

File tree

AGENTS.md

Lines changed: 110 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -1,264 +1,153 @@
11
# AGENTS.md - Coding Agent Guidelines for Systematic
22

3-
**Generated:** 2026-01-28 | **Commit:** d4bfa75 | **Branch:** main
3+
**Generated:** 2026-02-02 | **Commit:** decbf40 | **Branch:** main
44

5-
## Project Overview
5+
## Overview
66

7-
OpenCode plugin providing systematic engineering workflows. Converts/adapts Claude Code agents, skills, and commands from Compound Engineering Plugin (CEP) to OpenCode.
7+
OpenCode plugin providing systematic engineering workflows. Converts Claude Code (CEP) agents, skills, and commands to OpenCode format.
88

9-
**Key insight:** This repo has two distinct parts:
10-
1. **TypeScript source** (`src/`) - Plugin logic, tools, config handling
11-
2. **Bundled assets** (`skills/`, `agents/`, `commands/`) - OpenCode Markdown content shipped with npm package
9+
**Two distinct parts:**
10+
1. **TypeScript source** (`src/`) Plugin logic, tools, config handling
11+
2. **Bundled assets** (`skills/`, `agents/`, `commands/`) Markdown content shipped with npm package
1212

13-
## Build & Test Commands
13+
## Commands
1414

1515
```bash
16-
# Install dependencies
17-
bun install
18-
19-
# Build (outputs to dist/)
20-
bun run build
21-
22-
# Type checking (strict mode)
23-
bun run typecheck
24-
25-
# Lint with Biome
26-
bun run lint
27-
28-
# Run unit tests
29-
bun test tests/unit
16+
bun install # Install deps
17+
bun run build # Build to dist/
18+
bun run typecheck # Type check (strict)
19+
bun run lint # Biome linter
20+
bun test tests/unit # Unit tests
21+
bun test tests/integration # Integration tests
22+
bun test # All tests
23+
bun test --filter "pattern" # Filter tests
24+
```
3025

31-
# Run a single test file
32-
bun test tests/unit/skills-core.test.ts
26+
## Stack
3327

34-
# Run tests matching a pattern
35-
bun test --filter "extractFrontmatter"
28+
- **Runtime:** Bun (Node.js API compatible)
29+
- **Language:** TypeScript 5.7+ strict mode
30+
- **Modules:** ESM (`"type": "module"`)
31+
- **Linter:** Biome (not ESLint/Prettier)
32+
- **Tests:** `bun:test`
3633

37-
# Run all tests (unit + integration)
38-
bun test
34+
## Structure
3935

40-
# Run integration tests only
41-
bun test tests/integration
36+
```
37+
systematic/
38+
├── src/
39+
│ ├── index.ts # Plugin entry (SystematicPlugin)
40+
│ ├── cli.ts # CLI entry
41+
│ └── lib/ # Core implementation (see src/lib/AGENTS.md)
42+
├── skills/ # 8 bundled skills (SKILL.md format)
43+
├── agents/ # 11 bundled agents (4 categories)
44+
├── commands/ # 9 bundled commands
45+
├── tests/
46+
│ ├── unit/ # 9 test files
47+
│ └── integration/ # 2 test files
48+
└── dist/ # Build output
4249
```
4350

44-
## Technology Stack
45-
46-
- **Runtime**: Bun (not Node.js for execution, but Node.js API compatible)
47-
- **Language**: TypeScript 5.7+ with strict mode
48-
- **Module System**: ESM (`"type": "module"`)
49-
- **Target**: ES2022
50-
- **Linter/Formatter**: Biome (not ESLint/Prettier)
51-
- **Testing**: Bun's native test runner (`bun:test`)
52-
53-
## Code Style
51+
## Where to Look
52+
53+
| Task | Location |
54+
|------|----------|
55+
| Plugin hooks (config, tool, system.transform) | `src/index.ts` |
56+
| Config merging logic | `src/lib/config-handler.ts` |
57+
| Skill tool implementation | `src/lib/skill-tool.ts` |
58+
| Bootstrap injection | `src/lib/bootstrap.ts` |
59+
| CEP conversion | `src/lib/converter.ts` |
60+
| Asset discovery | `src/lib/skills.ts`, `agents.ts`, `commands.ts` |
61+
| Add new skill | `skills/<name>/SKILL.md` |
62+
| Add new agent | `agents/<category>/<name>.md` |
63+
| Add new command | `commands/<name>.md` |
64+
65+
## Code Map
66+
67+
| Symbol | Type | Location | Role |
68+
|--------|------|----------|------|
69+
| `SystematicPlugin` | export | src/index.ts:30 | Main plugin factory |
70+
| `createConfigHandler` | fn | src/lib/config-handler.ts:182 | Config hook impl |
71+
| `createSkillTool` | fn | src/lib/skill-tool.ts:35 | systematic_skill tool |
72+
| `getBootstrapContent` | fn | src/lib/bootstrap.ts:32 | System prompt injection |
73+
| `convertContent` | fn | src/lib/converter.ts:234 | CEP→OpenCode conversion |
74+
| `findSkillsInDir` | fn | src/lib/skills.ts:90 | Skill discovery |
75+
| `loadConfig` | fn | src/lib/config.ts:47 | JSONC config loading |
76+
77+
## Conventions
5478

5579
### Formatting (Biome)
56-
57-
- **Indent**: 2 spaces
58-
- **Quotes**: Single quotes for strings
59-
- **Semicolons**: As needed (omit where possible)
60-
- **Line width**: Default (no strict limit)
80+
- 2 spaces, single quotes, semicolons as-needed
6181

6282
### Imports
63-
6483
```typescript
65-
// 1. Node.js built-ins with node: protocol
66-
import fs from 'node:fs'
67-
import path from 'node:path'
68-
import os from 'node:os'
69-
70-
// 2. External dependencies
71-
import type { Plugin } from '@opencode-ai/plugin'
72-
import { tool } from '@opencode-ai/plugin/tool'
73-
74-
// 3. Internal modules with .js extension (ESM requirement)
75-
import { loadConfig } from './lib/config.js'
76-
import * as skillsCore from './lib/skills-core.js'
84+
import fs from 'node:fs' // Node built-ins with node: protocol
85+
import type { Plugin } from '@opencode-ai/plugin' // External deps
86+
import { loadConfig } from './lib/config.js' // Internal with .js extension
7787
```
7888
79-
### TypeScript Patterns
80-
81-
```typescript
82-
// Prefer function declarations over classes
83-
export function extractFrontmatter(filePath: string): SkillFrontmatter {
84-
// implementation
85-
}
86-
87-
// Use explicit return types
88-
export function findSkillsInDir(
89-
dir: string,
90-
sourceType: 'project' | 'user' | 'bundled',
91-
maxDepth = 3
92-
): SkillInfo[] {
93-
// implementation
94-
}
95-
96-
// Define interfaces for data structures
97-
export interface SkillInfo {
98-
path: string
99-
skillFile: string
100-
name: string
101-
description: string
102-
sourceType: 'project' | 'user' | 'bundled'
103-
}
104-
105-
// Use union types for constrained values
106-
type SourceType = 'project' | 'user' | 'bundled'
107-
108-
// Prefer const for immutable bindings
109-
const packageRoot = path.resolve(__dirname, '..')
110-
111-
// Arrow functions for inline callbacks
112-
const filtered = skills.filter((s) => !disabled.includes(s.name))
113-
```
89+
### TypeScript
90+
- Function declarations over classes
91+
- Explicit return types
92+
- Interfaces for data structures
93+
- Union types for constrained values
11494
11595
### Error Handling
96+
- Return null/empty for non-critical failures
97+
- Early return for guard clauses
98+
- Throw with context for critical errors
11699
117-
```typescript
118-
// Return null/empty for non-critical failures
119-
export function extractFrontmatter(filePath: string): SkillFrontmatter {
120-
try {
121-
const content = fs.readFileSync(filePath, 'utf8')
122-
// parse...
123-
return { name, description }
124-
} catch {
125-
return { name: '', description: '' }
126-
}
127-
}
100+
### Naming
101+
- Files: kebab-case
102+
- Functions: camelCase
103+
- Types/Interfaces: PascalCase
104+
- Tests: `*.test.ts`
128105
129-
// Early return for guard clauses
130-
if (!fs.existsSync(dir)) return skills
106+
## Anti-Patterns
131107
132-
// Throw for critical errors with context
133-
if (!validTypes.includes(typeArg)) {
134-
console.error(`Invalid type: ${typeArg}. Must be one of: ${validTypes.join(', ')}`)
135-
process.exit(1)
136-
}
137-
```
108+
- `require()` — use ESM imports
109+
- Omitting `.js` extension in relative imports
110+
- Classes when functions suffice
111+
- `any` — use `unknown` with type guards
112+
- `@ts-ignore` or `@ts-expect-error`
113+
- Non-null assertions (`!`) — Biome warns
138114
139-
### Naming Conventions
115+
## Plugin Architecture
140116
141-
- **Files**: kebab-case (`skills-core.ts`, `config.ts`)
142-
- **Functions**: camelCase (`findSkillsInDir`, `loadConfig`)
143-
- **Interfaces/Types**: PascalCase (`SkillInfo`, `SystematicConfig`)
144-
- **Constants**: SCREAMING_SNAKE_CASE or camelCase based on scope
145-
- **Test files**: `*.test.ts` in `tests/` directory
146-
147-
## Testing Patterns
148-
149-
```typescript
150-
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
151-
import fs from 'node:fs'
152-
import os from 'node:os'
153-
import path from 'node:path'
154-
155-
describe('module-name', () => {
156-
let testDir: string
157-
158-
beforeEach(() => {
159-
testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'systematic-test-'))
160-
})
161-
162-
afterEach(() => {
163-
fs.rmSync(testDir, { recursive: true, force: true })
164-
})
165-
166-
describe('functionName', () => {
167-
test('describes expected behavior', () => {
168-
const result = functionUnderTest(input)
169-
expect(result).toBe(expected)
170-
})
171-
172-
test('handles edge case', () => {
173-
expect(functionUnderTest(null)).toEqual([])
174-
})
175-
})
176-
})
177-
```
178-
179-
## Project Structure
180-
181-
```
182-
systematic/
183-
├── src/
184-
│ ├── index.ts # Plugin entry point (SystematicPlugin)
185-
│ ├── cli.ts # CLI entry point
186-
│ └── lib/
187-
│ ├── agents.ts # Agent discovery + frontmatter parsing
188-
│ ├── bootstrap.ts # System prompt injection
189-
│ ├── commands.ts # Command discovery + frontmatter parsing
190-
│ ├── config.ts # JSONC config loading (project > user)
191-
│ ├── config-handler.ts # OpenCode config hook (merges bundled → existing)
192-
│ ├── converter.ts # CEP to OpenCode conversion
193-
│ ├── frontmatter.ts # YAML frontmatter utilities
194-
│ ├── skill-tool.ts # `systematic_skill` tool implementation
195-
│ ├── skills.ts # Skill discovery + frontmatter parsing
196-
│ └── walk-dir.ts # Recursive directory traversal
197-
├── tests/
198-
│ ├── unit/ # Unit tests (bun test tests/unit)
199-
│ └── integration/ # Integration tests
200-
├── skills/ # Bundled OpenCode skill definitions (SKILL.md)
201-
├── agents/ # Bundled OpenCode agent definitions (Markdown)
202-
├── commands/ # Bundled OpenCode command definitions (Markdown)
203-
├── dist/ # Build output (git-ignored)
204-
├── biome.json # Biome linter/formatter config
205-
├── tsconfig.json # TypeScript config
206-
└── package.json
207117
```
208-
209-
## Key Patterns
210-
211-
### Plugin Export Pattern
212-
213-
```typescript
214-
export const SystematicPlugin: Plugin = async ({ client, directory }) => {
215-
const config = loadConfig(directory)
216-
217-
return {
218-
tool: {
219-
tool_name: tool({
220-
description: 'Tool description',
221-
args: {},
222-
execute: async (): Promise<string> => {
223-
// implementation
224-
},
225-
}),
226-
},
227-
}
228-
}
229-
230-
export default SystematicPlugin
118+
OpenCode loads plugin
119+
120+
SystematicPlugin({ client, directory })
121+
122+
┌──────────────────────────────────────────┐
123+
config hook: createConfigHandler() │
124+
│ → Merges bundled agents/commands/skills
125+
├──────────────────────────────────────────┤
126+
tool hook: systematic_skill
127+
│ → Loads bundled skills on demand
128+
├──────────────────────────────────────────┤
129+
system.transform hook
130+
│ → Injects using-systematic bootstrap
131+
└──────────────────────────────────────────┘
231132
```
232133

233-
### Skill File Format
234-
235-
Skills are directories containing `SKILL.md` with YAML frontmatter:
134+
## Skill Format
236135

237136
```markdown
238137
---
239138
name: skill-name
240-
description: Use when [condition] - [what it does]
139+
description: Use when [condition] [what it does]
241140
---
242141

243142
# Skill Content
244143
```
245144

246-
### Configuration Loading
247-
248-
Supports JSONC (JSON with comments). Priority: project > user > bundled.
249-
250-
## Linting Rules (Biome)
145+
## Config Priority
251146

252-
- `noExcessiveCognitiveComplexity`: warn
253-
- `noNonNullAssertion`: warn
254-
- All recommended rules enabled
255-
- Markdown files excluded from linting
147+
project `.opencode/systematic.json` > user `~/.config/opencode/systematic.json` > defaults
256148

257-
## Don'ts
149+
## Notes
258150

259-
- Don't use `require()` - use ESM imports
260-
- Don't omit `.js` extension in relative imports
261-
- Don't use classes when functions suffice
262-
- Don't use `any` - prefer `unknown` with type guards
263-
- Don't ignore Biome warnings without justification
264-
- Don't use `@ts-ignore` or `@ts-expect-error`
151+
- Bootstrap injection is opt-out via `bootstrap.enabled: false`
152+
- Skills are registered as commands (prefixed `systematic:`)
153+
- Experimental hook: `experimental.chat.system.transform`

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ Skills are structured workflows that guide the AI through systematic engineering
8686
| `agent-browser` | Browser automation using Vercel's agent-browser CLI |
8787
| `agent-native-architecture` | Design systems where AI agents are first-class citizens |
8888
| `compound-docs` | Capture solved problems as categorized documentation |
89-
| `create-agent-skills` | Expert guidance for writing and refining skills |
89+
| `creating-agent-skills` | Expert guidance for writing and refining skills |
9090
| `file-todos` | File-based todo tracking with status and dependency management |
9191
| `git-worktree` | Manage git worktrees for isolated parallel development |
9292

0 commit comments

Comments
 (0)