opencoding-agent 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 j5hjun
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # opencoding-agent
2
+
3
+ opencoding-agent is an OpenCode plugin that provides specialized agents and a subagent management system.
4
+
5
+ ## Features
6
+
7
+ - **Custom Agents**: Replaces default agents with specialized `plan` and `build` modes.
8
+ - **Subagent Catalog**: Browse and install subagents from the [awesome-opencode-subagents](https://github.com/j5hjun/awesome-opencode-subagents) repository.
9
+
10
+ ## Installation
11
+
12
+ Add this plugin to your `opencode.json`:
13
+
14
+ ```json
15
+ {
16
+ "plugin": [
17
+ "opencoding-agent"
18
+ ]
19
+ }
20
+ ```
21
+
22
+ OpenCode automatically installs plugin dependencies at runtime.
23
+
24
+ ## Tools
25
+
26
+ - `/subagent-catalog:list`: List available subagent categories.
27
+ - `/subagent-catalog:search <query>`: Search for specific subagents by name or description.
28
+ - `/subagent-catalog:fetch <name> [scope]`: Download and install a subagent (scope: `global` or `local`).
29
+
30
+ ## Development
31
+
32
+ To install dependencies:
33
+
34
+ ```bash
35
+ bun install
36
+ ```
37
+
38
+ To build:
39
+
40
+ ```bash
41
+ bun run build
42
+ ```
@@ -0,0 +1 @@
1
+ export { default } from "./src/index";
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { default } from "./src/index";
@@ -0,0 +1,2 @@
1
+ import type { AgentInfo } from "../config";
2
+ export declare const buildAgent: AgentInfo;
@@ -0,0 +1,9 @@
1
+ export const buildAgent = {
2
+ name: "opencoding-build",
3
+ description: "The default agent. Executes tools based on configured permissions.",
4
+ mode: "primary",
5
+ color: "#e74c3c",
6
+ permission: {
7
+ "*": "allow"
8
+ }
9
+ };
@@ -0,0 +1 @@
1
+ export declare const injectAgents: (config: any) => Promise<void>;
@@ -0,0 +1,24 @@
1
+ import { planAgent } from "./plan";
2
+ import { buildAgent } from "./build";
3
+ export const injectAgents = async (config) => {
4
+ const planPrompt = await Bun.file(`${import.meta.dir}/../prompts/plan.txt`).text();
5
+ const buildPrompt = await Bun.file(`${import.meta.dir}/../prompts/build.txt`).text();
6
+ config.agent = {
7
+ ...config.agent,
8
+ // Disable default agents
9
+ "build": { disable: true },
10
+ "plan": { disable: true },
11
+ // Inject our opencoding- prefixed agents
12
+ "opencoding-plan": {
13
+ ...planAgent,
14
+ disable: false,
15
+ prompt: planPrompt
16
+ },
17
+ "opencoding-build": {
18
+ ...buildAgent,
19
+ disable: false,
20
+ prompt: buildPrompt
21
+ }
22
+ };
23
+ config.default_agent = "opencoding-plan";
24
+ };
@@ -0,0 +1,2 @@
1
+ import type { AgentInfo } from "../config";
2
+ export declare const planAgent: AgentInfo;
@@ -0,0 +1,12 @@
1
+ export const planAgent = {
2
+ name: "opencoding-plan",
3
+ description: "Plan mode. Disallows all edit tools.",
4
+ mode: "primary",
5
+ color: "#3498db",
6
+ permission: {
7
+ "*": "allow",
8
+ "edit": "deny",
9
+ "write": "deny",
10
+ "apply_patch": "deny"
11
+ }
12
+ };
@@ -0,0 +1,8 @@
1
+ export type AgentInfo = {
2
+ name: string;
3
+ description: string;
4
+ mode: string;
5
+ color: string;
6
+ permission: Record<string, string>;
7
+ };
8
+ export declare const PLUGIN_NAME = "opencoding-agent";
@@ -0,0 +1 @@
1
+ export const PLUGIN_NAME = "opencoding-agent";
@@ -0,0 +1,8 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ /**
3
+ * opencoding-agent Plugin
4
+ *
5
+ * Replaces default OpenCode agents with core-identical 'plan' and 'build' modes.
6
+ */
7
+ declare const OpencodingAgentPlugin: Plugin;
8
+ export default OpencodingAgentPlugin;
@@ -0,0 +1,20 @@
1
+ import { injectAgents } from "./agents";
2
+ import { catalogTools } from "./tools/catalog";
3
+ /**
4
+ * opencoding-agent Plugin
5
+ *
6
+ * Replaces default OpenCode agents with core-identical 'plan' and 'build' modes.
7
+ */
8
+ const OpencodingAgentPlugin = async (ctx) => {
9
+ return {
10
+ // Config hook: Injected once during initialization
11
+ config: async (config) => {
12
+ await injectAgents(config);
13
+ },
14
+ // Register custom tools
15
+ tool: {
16
+ ...catalogTools
17
+ }
18
+ };
19
+ };
20
+ export default OpencodingAgentPlugin;
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ export declare const catalogTools: {
3
+ "subagent-catalog:list": {
4
+ description: string;
5
+ args: {};
6
+ execute(args: Record<string, never>, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
7
+ };
8
+ "subagent-catalog:search": {
9
+ description: string;
10
+ args: {
11
+ query: z.ZodString;
12
+ category: z.ZodOptional<z.ZodString>;
13
+ };
14
+ execute(args: {
15
+ query: string;
16
+ category?: string | undefined;
17
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
18
+ };
19
+ "subagent-catalog:fetch": {
20
+ description: string;
21
+ args: {
22
+ name: z.ZodString;
23
+ scope: z.ZodDefault<z.ZodEnum<{
24
+ global: "global";
25
+ local: "local";
26
+ }>>;
27
+ };
28
+ execute(args: {
29
+ name: string;
30
+ scope: "global" | "local";
31
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
32
+ };
33
+ };
@@ -0,0 +1,113 @@
1
+ import { tool } from "@opencode-ai/plugin";
2
+ import { z } from "zod";
3
+ import * as path from "path";
4
+ import * as os from "os";
5
+ const REPO_URL = "https://raw.githubusercontent.com/j5hjun/awesome-opencode-subagents/main";
6
+ export const catalogTools = {
7
+ "subagent-catalog:list": tool({
8
+ description: "List all available subagent categories and the number of agents in each.",
9
+ args: {},
10
+ execute: async () => {
11
+ try {
12
+ const url = `${REPO_URL}/catalog.json?t=${Date.now()}`;
13
+ console.log(`Fetching catalog from: ${url}`);
14
+ const response = await fetch(url);
15
+ if (!response.ok) {
16
+ const errorMsg = `Fetch failed for ${url}: ${response.status} ${response.statusText}`;
17
+ console.error(errorMsg);
18
+ return errorMsg;
19
+ }
20
+ const catalog = await response.json();
21
+ const categories = catalog.reduce((acc, item) => {
22
+ acc[item.category] = (acc[item.category] || 0) + 1;
23
+ return acc;
24
+ }, {});
25
+ let output = "Available Subagent Categories:\n\n";
26
+ for (const [name, count] of Object.entries(categories)) {
27
+ output += `- ${name}: ${count} agents\n`;
28
+ }
29
+ output += "\nUse subagent-catalog:search to find specific agents.";
30
+ return output;
31
+ }
32
+ catch (error) {
33
+ return `Error fetching catalog: ${error.message}`;
34
+ }
35
+ }
36
+ }),
37
+ "subagent-catalog:search": tool({
38
+ description: "Search for subagents by name, description, or category.",
39
+ args: {
40
+ query: z.string().describe("Search term"),
41
+ category: z.string().optional().describe("Filter by category")
42
+ },
43
+ execute: async ({ query, category }) => {
44
+ try {
45
+ const url = `${REPO_URL}/catalog.json?t=${Date.now()}`;
46
+ const response = await fetch(url);
47
+ if (!response.ok)
48
+ return `Fetch failed for ${url}: ${response.status} ${response.statusText}`;
49
+ const catalog = await response.json();
50
+ const results = catalog.filter(item => {
51
+ const matchesQuery = item.name.toLowerCase().includes(query.toLowerCase()) ||
52
+ item.description.toLowerCase().includes(query.toLowerCase());
53
+ const matchesCategory = !category || item.category.toLowerCase() === category.toLowerCase();
54
+ return matchesQuery && matchesCategory;
55
+ });
56
+ if (results.length === 0)
57
+ return "No agents found matching your search.";
58
+ let output = `Search Results for "${query}":\n\n`;
59
+ for (const item of results) {
60
+ output += `### ${item.name}\n`;
61
+ output += `**Category**: ${item.category}\n`;
62
+ output += `**Description**: ${item.description}\n\n`;
63
+ }
64
+ output += "Use subagent-catalog:fetch to install an agent.";
65
+ return output;
66
+ }
67
+ catch (error) {
68
+ return `Error searching catalog: ${error.message}`;
69
+ }
70
+ }
71
+ }),
72
+ "subagent-catalog:fetch": tool({
73
+ description: "Download and install a subagent by name. You can choose to install it globally or locally.",
74
+ args: {
75
+ name: z.string().describe("Name of the agent to fetch"),
76
+ scope: z.enum(["global", "local"]).default("global").describe("Installation scope (global: all projects, local: current project only)")
77
+ },
78
+ execute: async ({ name, scope }, { directory }) => {
79
+ try {
80
+ const catalogUrl = `${REPO_URL}/catalog.json?t=${Date.now()}`;
81
+ const catalogResponse = await fetch(catalogUrl);
82
+ if (!catalogResponse.ok)
83
+ return `Fetch failed for ${catalogUrl}: ${catalogResponse.status} ${catalogResponse.statusText}`;
84
+ const catalog = await catalogResponse.json();
85
+ const agent = catalog.find(item => item.name.toLowerCase() === name.toLowerCase());
86
+ if (!agent)
87
+ return `Agent "${name}" not found in the catalog.`;
88
+ const agentUrl = `${REPO_URL}/${agent.path}?t=${Date.now()}`;
89
+ const agentResponse = await fetch(agentUrl);
90
+ if (!agentResponse.ok)
91
+ return `Fetch failed for ${agentUrl}: ${agentResponse.status} ${agentResponse.statusText}`;
92
+ const content = await agentResponse.text();
93
+ let targetDir;
94
+ if (scope === "global") {
95
+ targetDir = path.join(os.homedir(), ".config", "opencode", "agents");
96
+ }
97
+ else {
98
+ targetDir = path.join(directory, ".opencode", "agents");
99
+ }
100
+ const fileName = `${agent.name}.md`;
101
+ const filePath = path.join(targetDir, fileName);
102
+ // Ensure directory exists - Bun.write will create the file, but we might need to create the directory
103
+ const fs = await import("fs/promises");
104
+ await fs.mkdir(targetDir, { recursive: true });
105
+ await Bun.write(filePath, content);
106
+ return `✓ Successfully installed **${agent.name}** to ${scope} path: \`${filePath}\`\n\nYou can now use this agent by saying: "Use the ${agent.name} to [task]"`;
107
+ }
108
+ catch (error) {
109
+ return `Error fetching agent: ${error.message}`;
110
+ }
111
+ }
112
+ })
113
+ };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "opencoding-agent",
3
+ "version": "1.0.0",
4
+ "description": "OpenCode specialized agents and subagent catalog manager",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "keywords": [
14
+ "opencode",
15
+ "opencode-plugin",
16
+ "plugin"
17
+ ],
18
+ "license": "MIT",
19
+ "peerDependencies": {
20
+ "@opencode-ai/plugin": "^1.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "@opencode-ai/plugin": "^1.0.0",
24
+ "@types/bun": "^1.2.0",
25
+ "@types/node": "^22.0.0",
26
+ "typescript": "^5.7.0"
27
+ },
28
+ "scripts": {
29
+ "clean": "rm -rf dist",
30
+ "build": "npm run clean && tsc",
31
+ "prepublishOnly": "npm run build"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ }
36
+ }