Skip to content

Commit 1820b69

Browse files
authored
Merge pull request #1 from Octane0411/feat/initial-implementation
Feat/initial implementation
2 parents eb11c24 + d5afe66 commit 1820b69

10 files changed

Lines changed: 288 additions & 1 deletion

File tree

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
dist
3+
.DS_Store
4+
*.tsbuildinfo
5+
opencode.json
6+
AGENTS.md

README.md

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,90 @@
11
# opencode-plugin-openspec
2-
An OpenCode plugin that integrates OpenSpec, allowing Plan Mode to create and edit spec files.
2+
3+
An OpenCode plugin that integrates OpenSpec, providing a dedicated agent for planning and specifying software architecture.
4+
5+
## Features
6+
7+
- **Auto-Detection**: Automatically detects if the current workspace is an OpenSpec project.
8+
- **New Agent: `openspec-plan`**: A dedicated agent mode for creating and editing OpenSpec files.
9+
- **Smart Permissions**: Automatically grants write permissions for:
10+
- `project.md`
11+
- `AGENTS.md`
12+
- `openspec/**`
13+
- `specs/**`
14+
- **Read-Only Safety**: Keeps the rest of the codebase read-only when using the `openspec-plan` agent, ensuring the implementation details are not accidentally modified during the planning phase.
15+
16+
## Installation
17+
18+
### For Humans
19+
20+
**Option 1: Let your agent do it (Recommended)**
21+
22+
Paste this prompt into OpenCode:
23+
24+
```
25+
Install opencode-plugin-openspec. It is an NPM package. Please add "opencode-plugin-openspec" to my opencode.json plugin list.
26+
```
27+
28+
**Option 2: Manual Installation**
29+
30+
Add the plugin package name to your `opencode.json` configuration file (usually located at `~/.config/opencode/opencode.json` or `.opencode/opencode.json`):
31+
32+
```json
33+
{
34+
"plugin": [
35+
"opencode-plugin-openspec"
36+
]
37+
}
38+
```
39+
40+
OpenCode will automatically download and install the plugin the next time it runs.
41+
42+
### For LLM Agents
43+
44+
If you are an AI agent tasked with installing this plugin, follow these steps:
45+
46+
1. **Locate Configuration**: Find the user's OpenCode configuration file. It is typically at `~/.config/opencode/opencode.json` or `.opencode/opencode.json` in the workspace root.
47+
2. **Read Configuration**: Read the content of the configuration file.
48+
3. **Update Configuration**: Add `"opencode-plugin-openspec"` to the `plugin` array. If the `plugin` array does not exist, create it.
49+
```json
50+
{
51+
"plugin": [
52+
"opencode-plugin-openspec"
53+
]
54+
}
55+
```
56+
4. **Verify**: Inform the user that the plugin has been added and will be installed on the next OpenCode run.
57+
58+
## Usage
59+
60+
1. Open an OpenSpec project in OpenCode.
61+
2. The plugin will automatically detect the project structure.
62+
3. Switch to the **OpenSpec Architect** agent (colored #FF6B6B) in the agent selector.
63+
4. Start planning your architecture! The agent will have access to modify your spec files while keeping your code safe.
64+
65+
## Development
66+
67+
1. Clone the repository:
68+
```bash
69+
git clone https://github.com/yourusername/opencode-plugin-openspec.git
70+
cd opencode-plugin-openspec
71+
```
72+
73+
2. Install dependencies:
74+
```bash
75+
bun install
76+
```
77+
78+
3. Build the plugin:
79+
```bash
80+
bun run build
81+
```
82+
83+
4. Run watch mode for development:
84+
```bash
85+
bun run watch
86+
```
87+
88+
## License
89+
90+
MIT

bun.lock

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "opencode-plugin-openspec",
3+
"version": "0.1.0",
4+
"description": "An OpenCode plugin that integrates OpenSpec, providing a dedicated agent for planning and specifying software architecture.",
5+
"type": "module",
6+
"main": "dist/index.js",
7+
"files": [
8+
"dist"
9+
],
10+
"scripts": {
11+
"build": "bun build ./src/index.ts --outfile ./dist/index.js --target node",
12+
"watch": "bun build ./src/index.ts --outfile ./dist/index.js --target node --watch",
13+
"prepublishOnly": "bun run build"
14+
},
15+
"repository": {
16+
"type": "git",
17+
"url": "git+https://github.com/Octane0411/opencode-plugin-openspec.git"
18+
},
19+
"keywords": [
20+
"opencode",
21+
"plugin",
22+
"openspec",
23+
"agent",
24+
"architecture",
25+
"planning"
26+
],
27+
"author": "Octane0411",
28+
"license": "MIT",
29+
"bugs": {
30+
"url": "https://github.com/Octane0411/opencode-plugin-openspec/issues"
31+
},
32+
"homepage": "https://github.com/Octane0411/opencode-plugin-openspec#readme",
33+
"peerDependencies": {
34+
"@opencode-ai/plugin": "^1.1.19",
35+
"@opencode-ai/sdk": "^1.1.19"
36+
},
37+
"devDependencies": {
38+
"bun-types": "latest",
39+
"typescript": "^5.0.0"
40+
}
41+
}

src/config.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { Hooks } from "@opencode-ai/plugin";
2+
import { isOpenSpecProject } from "./utils/detection";
3+
import { OPENSPEC_SYSTEM_PROMPT } from "./prompts";
4+
5+
export function createConfigHook(ctx: { directory: string }): Hooks["config"] {
6+
return async (config) => {
7+
// 1. Check if this is an OpenSpec project
8+
const mockCtx = { directory: ctx.directory } as any;
9+
10+
const isActive = await isOpenSpecProject(mockCtx);
11+
if (!isActive) {
12+
return;
13+
}
14+
15+
// 2. Define the OpenSpec Plan Agent
16+
const openSpecAgent = {
17+
name: "openspec-plan",
18+
mode: "primary",
19+
description: "OpenSpec Architect - Plan and specify software architecture.",
20+
prompt: OPENSPEC_SYSTEM_PROMPT,
21+
permission: {
22+
edit: {
23+
// Allow editing specific root files
24+
"project.md": "allow",
25+
"AGENTS.md": "allow",
26+
// Allow editing anything in openspec directory
27+
"openspec/**": "allow",
28+
// Allow editing anything in specs directory (standard OpenSpec structure)
29+
"specs/**": "allow"
30+
}
31+
},
32+
color: "#FF6B6B" // Distinctive color for the agent
33+
};
34+
35+
// 3. Inject into configuration
36+
const agentConfig = (config.agent || {}) as any;
37+
agentConfig["openspec-plan"] = openSpecAgent;
38+
config.agent = agentConfig;
39+
};
40+
}

src/index.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { Plugin } from "@opencode-ai/plugin";
2+
import { createConfigHook } from "./config";
3+
import { isOpenSpecProject } from "./utils/detection";
4+
5+
const OpenSpecPlugin: Plugin = async (ctx) => {
6+
const isActive = await isOpenSpecProject(ctx);
7+
8+
if (!isActive) {
9+
return {};
10+
}
11+
12+
return {
13+
config: createConfigHook(ctx),
14+
};
15+
};
16+
17+
export default OpenSpecPlugin;

src/prompts.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export const OPENSPEC_SYSTEM_PROMPT = `
2+
<Role>
3+
You are the **OpenSpec Architect**.
4+
Your goal is to design, specify, and document software architecture using the OpenSpec standard.
5+
You work primarily with Markdown files in the \`openspec/\` and \`specs/\` directories.
6+
</Role>
7+
8+
<Context>
9+
This project follows the OpenSpec standard for documentation-driven development.
10+
Key files:
11+
- \`project.md\`: High-level project vision, goals, and scope.
12+
- \`openspec/AGENTS.md\` (or \`AGENTS.md\`): Definitions of agents and their roles.
13+
- \`specs/**/*.spec.md\`: Detailed specifications for components or features.
14+
</Context>
15+
16+
<Rules>
17+
1. **Focus on Specifications**: Your primary output should be modifications to \`*.spec.md\` files.
18+
2. **No Implementation**: Do NOT write implementation code (TypeScript, Python, etc.) unless explicitly requested to "implement" or "prototype". Your job is to *plan*, not to *build*.
19+
3. **Structure**:
20+
- When designing a new feature, create a new spec file in \`specs/<feature-name>/spec.md\`.
21+
- Link back to \`project.md\` to ensure alignment with high-level goals.
22+
4. **Format**: Follow the existing Markdown structure found in the project. Use clear headers, bullet points, and diagrams (Mermaid) where appropriate.
23+
</Rules>
24+
`.trim();

src/utils/detection.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { PluginInput } from "@opencode-ai/plugin";
2+
import { existsSync } from "node:fs";
3+
import { join } from "node:path";
4+
5+
/**
6+
* Checks if the current workspace is an OpenSpec project.
7+
*
8+
* Detection logic:
9+
* 1. Checks for `openspec/AGENTS.md` (Primary indicator)
10+
* 2. Checks for `AGENTS.md` in root (Secondary indicator)
11+
*/
12+
export async function isOpenSpecProject(ctx: PluginInput): Promise<boolean> {
13+
const openspecAgentsPath = join(ctx.directory, "openspec", "AGENTS.md");
14+
15+
return existsSync(openspecAgentsPath);
16+
}

tsconfig.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"compilerOptions": {
3+
"lib": ["ESNext"],
4+
"module": "esnext",
5+
"target": "esnext",
6+
"moduleResolution": "bundler",
7+
"moduleDetection": "force",
8+
"allowImportingTsExtensions": true,
9+
"noEmit": true,
10+
"composite": true,
11+
"strict": true,
12+
"downlevelIteration": true,
13+
"skipLibCheck": true,
14+
"jsx": "react-jsx",
15+
"allowSyntheticDefaultImports": true,
16+
"forceConsistentCasingInFileNames": true,
17+
"allowJs": true,
18+
"types": [
19+
"bun-types" // add Bun global
20+
]
21+
}
22+
}

tsconfig.tsbuildinfo

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)