@hiai-gg/hiai-opencode 0.1.5 → 0.1.6

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.
Files changed (67) hide show
  1. package/.env.example +14 -8
  2. package/AGENTS.md +14 -5
  3. package/LICENSE.md +0 -1
  4. package/README.md +42 -23
  5. package/assets/cli/hiai-opencode.mjs +590 -7
  6. package/assets/mcp/mempalace.mjs +159 -25
  7. package/config/hiai-opencode.schema.json +13 -2
  8. package/dist/agents/dynamic-agent-core-sections.d.ts +4 -1
  9. package/dist/agents/dynamic-agent-prompt-builder.d.ts +1 -1
  10. package/dist/config/platform-schema.d.ts +2 -6
  11. package/dist/config/schema/commands.d.ts +1 -0
  12. package/dist/config/schema/oh-my-opencode-config.d.ts +1 -3
  13. package/dist/config/types.d.ts +1 -3
  14. package/dist/features/builtin-commands/templates/doctor.d.ts +1 -0
  15. package/dist/features/builtin-commands/types.d.ts +1 -1
  16. package/dist/features/builtin-skills/skills/hiai-opencode-setup.d.ts +2 -0
  17. package/dist/features/builtin-skills/skills/index.d.ts +1 -0
  18. package/dist/index.js +348 -1424
  19. package/dist/shared/mcp-static-export.d.ts +22 -0
  20. package/dist/tools/ast-grep/constants.d.ts +1 -1
  21. package/dist/tools/ast-grep/environment-check.d.ts +1 -5
  22. package/dist/tools/ast-grep/language-support.d.ts +0 -1
  23. package/dist/tools/ast-grep/types.d.ts +1 -2
  24. package/hiai-opencode.json +4 -2
  25. package/package.json +6 -4
  26. package/src/agents/bob/default.ts +6 -1
  27. package/src/agents/bob/gpt-pro.ts +1 -0
  28. package/src/agents/bob.ts +1 -0
  29. package/src/agents/coder/gpt-codex.ts +1 -0
  30. package/src/agents/coder/gpt-pro.ts +1 -0
  31. package/src/agents/coder/gpt.ts +1 -0
  32. package/src/agents/dynamic-agent-core-sections.ts +36 -0
  33. package/src/agents/dynamic-agent-prompt-builder.ts +1 -0
  34. package/src/config/defaults.ts +14 -1
  35. package/src/config/model-slots-and-export.test.ts +55 -0
  36. package/src/config/platform-schema.ts +1 -3
  37. package/src/config/schema/commands.ts +1 -0
  38. package/src/config/schema/oh-my-opencode-config.ts +0 -3
  39. package/src/config/types.ts +1 -3
  40. package/src/features/builtin-commands/commands.ts +7 -0
  41. package/src/features/builtin-commands/templates/doctor.ts +43 -0
  42. package/src/features/builtin-commands/types.ts +1 -1
  43. package/src/features/builtin-skills/skills/hiai-opencode-setup.ts +69 -0
  44. package/src/features/builtin-skills/skills/index.ts +1 -0
  45. package/src/features/builtin-skills/skills.ts +10 -1
  46. package/src/index.ts +3 -75
  47. package/src/shared/mcp-static-export.ts +121 -0
  48. package/src/tools/ast-grep/constants.ts +1 -1
  49. package/src/tools/ast-grep/environment-check.ts +2 -32
  50. package/src/tools/ast-grep/language-support.ts +0 -3
  51. package/src/tools/ast-grep/types.ts +1 -2
  52. package/src/tools/skill-mcp/tools.test.ts +44 -0
  53. package/dist/ast-grep-napi.win32-x64-msvc-67c0y8nc.node +0 -0
  54. package/dist/config/loader.test.d.ts +0 -1
  55. package/dist/config/models.d.ts +0 -13
  56. package/dist/internals/plugins/websearch-cited/google.d.ts +0 -38
  57. package/dist/internals/plugins/websearch-cited/index.d.ts +0 -17
  58. package/dist/internals/plugins/websearch-cited/openai.d.ts +0 -9
  59. package/dist/internals/plugins/websearch-cited/openrouter.d.ts +0 -2
  60. package/dist/internals/plugins/websearch-cited/types.d.ts +0 -5
  61. package/src/internals/plugins/websearch-cited/LICENSE +0 -214
  62. package/src/internals/plugins/websearch-cited/codex_prompt.txt +0 -79
  63. package/src/internals/plugins/websearch-cited/google.ts +0 -749
  64. package/src/internals/plugins/websearch-cited/index.ts +0 -306
  65. package/src/internals/plugins/websearch-cited/openai.ts +0 -407
  66. package/src/internals/plugins/websearch-cited/openrouter.ts +0 -190
  67. package/src/internals/plugins/websearch-cited/types.ts +0 -7
@@ -0,0 +1,22 @@
1
+ import type { HiaiOpencodeConfig } from "../config/types";
2
+ type StaticMcpServer = {
3
+ type?: "http" | "stdio";
4
+ url?: string;
5
+ command?: string;
6
+ args?: string[];
7
+ env?: Record<string, string>;
8
+ headers?: Record<string, string>;
9
+ };
10
+ export declare const MCP_EXPORT_MARKER = "hiai-opencode";
11
+ type StaticMcpJsonPayload = {
12
+ mcpServers: Record<string, StaticMcpServer>;
13
+ _meta?: {
14
+ generatedBy: typeof MCP_EXPORT_MARKER;
15
+ version: 1;
16
+ generatedAt: string;
17
+ };
18
+ };
19
+ export declare function buildStaticMcpJson(config: HiaiOpencodeConfig): StaticMcpJsonPayload;
20
+ export declare function isManagedStaticMcpFile(path: string): boolean;
21
+ export declare function autoExportStaticMcpJson(directory: string, config: HiaiOpencodeConfig): void;
22
+ export {};
@@ -1,5 +1,5 @@
1
1
  export type { EnvironmentCheckResult } from "./environment-check";
2
2
  export { checkEnvironment, formatEnvironmentCheck } from "./environment-check";
3
- export { CLI_LANGUAGES, NAPI_LANGUAGES, LANG_EXTENSIONS } from "./language-support";
3
+ export { CLI_LANGUAGES, LANG_EXTENSIONS } from "./language-support";
4
4
  export { DEFAULT_TIMEOUT_MS, DEFAULT_MAX_OUTPUT_BYTES, DEFAULT_MAX_MATCHES } from "./language-support";
5
5
  export { findSgCliPathSync, getSgCliPath, setSgCliPath } from "./sg-cli-path";
@@ -4,13 +4,9 @@ export interface EnvironmentCheckResult {
4
4
  path: string;
5
5
  error?: string;
6
6
  };
7
- napi: {
8
- available: boolean;
9
- error?: string;
10
- };
11
7
  }
12
8
  /**
13
- * Check if ast-grep CLI and NAPI are available.
9
+ * Check if ast-grep CLI is available.
14
10
  * Call this at startup to provide early feedback about missing dependencies.
15
11
  */
16
12
  export declare function checkEnvironment(): EnvironmentCheckResult;
@@ -1,5 +1,4 @@
1
1
  export declare const CLI_LANGUAGES: readonly ["bash", "c", "cpp", "csharp", "css", "elixir", "go", "haskell", "html", "java", "javascript", "json", "kotlin", "lua", "nix", "php", "python", "ruby", "rust", "scala", "solidity", "swift", "typescript", "tsx", "yaml"];
2
- export declare const NAPI_LANGUAGES: readonly ["html", "javascript", "tsx", "css", "typescript"];
3
2
  export declare const DEFAULT_TIMEOUT_MS = 300000;
4
3
  export declare const DEFAULT_MAX_OUTPUT_BYTES: number;
5
4
  export declare const DEFAULT_MAX_MATCHES = 500;
@@ -1,6 +1,5 @@
1
- import type { CLI_LANGUAGES, NAPI_LANGUAGES } from "./constants";
1
+ import type { CLI_LANGUAGES } from "./constants";
2
2
  export type CliLanguage = (typeof CLI_LANGUAGES)[number];
3
- export type NapiLanguage = (typeof NAPI_LANGUAGES)[number];
4
3
  export interface Position {
5
4
  line: number;
6
5
  column: number;
@@ -44,7 +44,6 @@
44
44
  }
45
45
  },
46
46
  "auth": {
47
- "googleSearch": "{env:GOOGLE_SEARCH_API_KEY}",
48
47
  "stitch": "{env:STITCH_AI_API_KEY}",
49
48
  "firecrawl": "{env:FIRECRAWL_API_KEY}",
50
49
  "context7": "{env:CONTEXT7_API_KEY}"
@@ -55,7 +54,10 @@
55
54
  "sequential-thinking": { "enabled": true },
56
55
  "firecrawl": { "enabled": true },
57
56
  "rag": { "enabled": true },
58
- "mempalace": { "enabled": true },
57
+ "mempalace": {
58
+ "enabled": true,
59
+ "pythonPath": "{env:MEMPALACE_PYTHON:-./.venv/bin/python}"
60
+ },
59
61
  "context7": { "enabled": true }
60
62
  },
61
63
  "lsp": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hiai-gg/hiai-opencode",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Unified OpenCode plugin — canonical 12-agent model with bundled skills, MCP integrations, LSP, and permissions in one install.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -50,19 +50,21 @@
50
50
  "access": "public"
51
51
  },
52
52
  "scripts": {
53
- "build": "bun build src/index.ts --outdir dist --target bun --format esm && tsc --emitDeclarationOnly",
53
+ "clean:dist": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
54
+ "build": "bun run clean:dist && bun build src/index.ts --outdir dist --target bun --format esm && tsc --emitDeclarationOnly",
54
55
  "build:bundle": "bun build src/index.ts --outdir dist --target bun --format esm",
55
56
  "build:types": "tsc --emitDeclarationOnly",
56
57
  "typecheck": "tsc --noEmit",
58
+ "test": "bun test",
59
+ "pack:check": "npm pack --dry-run",
57
60
  "prepare": "bun run build",
58
- "prepublishOnly": "bun run build"
61
+ "prepublishOnly": "bun run typecheck && bun run test && bun run build && bun run pack:check"
59
62
  },
60
63
  "dependencies": {
61
64
  "bun-pty": "^0.4.8",
62
65
  "@opencode-ai/plugin": "^1.4.0",
63
66
  "@opencode-ai/sdk": "^1.4.0",
64
67
  "@modelcontextprotocol/sdk": "^1.12.0",
65
- "@ast-grep/napi": "^0.37.0",
66
68
  "zod": "^4.3.0",
67
69
  "jsonc-parser": "^3.3.1",
68
70
  "js-yaml": "^4.1.0",
@@ -36,7 +36,12 @@ export function buildDefaultBobPrompt(
36
36
  useTaskSystem = false,
37
37
  ): string {
38
38
  const keyTriggers = buildKeyTriggersSection(availableAgents, availableSkills)
39
- const toolSelection = buildToolSelectionTable(availableAgents, availableTools, availableSkills)
39
+ const toolSelection = buildToolSelectionTable(
40
+ availableAgents,
41
+ availableTools,
42
+ availableSkills,
43
+ { includeIntegrationPrimer: true },
44
+ )
40
45
  const researcherSection = buildResearcherSection(availableAgents)
41
46
  const categorySkillsGuide = buildCategorySkillsDelegationGuide(availableCategories, availableSkills)
42
47
  const delegationTable = buildDelegationTable(availableAgents)
@@ -88,6 +88,7 @@ export function buildGptProBobPrompt(
88
88
  availableAgents,
89
89
  availableTools,
90
90
  availableSkills,
91
+ { includeIntegrationPrimer: true },
91
92
  );
92
93
  const researcherSection = buildResearcherSection(availableAgents);
93
94
  const categorySkillsGuide = buildCategorySkillsDelegationGuide(
package/src/agents/bob.ts CHANGED
@@ -54,6 +54,7 @@ function buildDynamicBobPrompt(
54
54
  availableAgents,
55
55
  availableTools,
56
56
  availableSkills,
57
+ { includeIntegrationPrimer: true },
57
58
  );
58
59
  const researcherSection = buildResearcherSection(availableAgents);
59
60
  const categorySkillsGuide = buildCategorySkillsDelegationGuide(
@@ -56,6 +56,7 @@ export function buildCoderPrompt(
56
56
  availableAgents,
57
57
  availableTools,
58
58
  availableSkills,
59
+ { includeIntegrationPrimer: true },
59
60
  );
60
61
  const researcherSection = buildResearcherSection(availableAgents);
61
62
  const categorySkillsGuide = buildCategorySkillsDelegationGuide(
@@ -51,6 +51,7 @@ export function buildCoderPrompt(
51
51
  availableAgents,
52
52
  availableTools,
53
53
  availableSkills,
54
+ { includeIntegrationPrimer: true },
54
55
  );
55
56
  const researcherSection = buildResearcherSection(availableAgents);
56
57
  const categorySkillsGuide = buildCategorySkillsDelegationGuide(
@@ -32,6 +32,7 @@ export function buildCoderPrompt(
32
32
  availableAgents,
33
33
  availableTools,
34
34
  availableSkills,
35
+ { includeIntegrationPrimer: true },
35
36
  );
36
37
  const researcherSection = buildResearcherSection(availableAgents);
37
38
  const categorySkillsGuide = buildCategorySkillsDelegationGuide(
@@ -45,6 +45,7 @@ export function buildToolSelectionTable(
45
45
  agents: AvailableAgent[],
46
46
  tools: AvailableTool[] = [],
47
47
  _skills: AvailableSkill[] = [],
48
+ options: { includeIntegrationPrimer?: boolean } = {},
48
49
  ): string {
49
50
  const rows: string[] = ["### Tool & Agent Selection:", ""]
50
51
 
@@ -72,10 +73,45 @@ export function buildToolSelectionTable(
72
73
  rows.push(
73
74
  "**Default flow**: researcher (background) + tools → strategist (if required) → critic (high-risk gate)",
74
75
  )
76
+ if (options.includeIntegrationPrimer) {
77
+ rows.push("")
78
+ rows.push(buildHiaiIntegrationPrimerSection())
79
+ }
75
80
 
76
81
  return rows.join("\n")
77
82
  }
78
83
 
84
+ export function buildHiaiIntegrationPrimerSection(): string {
85
+ return `<hiai-opencode-integration-primer>
86
+ ## hiai-opencode Architecture And Integration Rules
87
+
88
+ This workspace may use hiai-opencode, an OpenCode plugin that wires agents, skills, MCP launchers, LSP, diagnostics, and compatibility helpers around external upstream tools.
89
+
90
+ Core rules:
91
+ - OpenCode plugins are not MCP servers. Keep \`@hiai-gg/hiai-opencode\` and optional \`@tarquinen/opencode-dcp\` in the OpenCode plugin list; never add MCP packages such as \`firecrawl-mcp\`, \`@playwright/mcp\`, or \`@modelcontextprotocol/server-sequential-thinking\` to the plugin list.
92
+ - User-facing config lives in \`hiai-opencode.json\` or \`.opencode/hiai-opencode.json\`: 10 model slots, MCP enable flags, LSP enable flags, service auth placeholders, and skill discovery switches.
93
+ - Model provider credentials are configured through OpenCode Connect. Do not ask for \`OPENROUTER_API_KEY\`, \`OPENAI_API_KEY\`, or \`ANTHROPIC_API_KEY\` for normal model usage.
94
+ - Service keys are separate: \`FIRECRAWL_API_KEY\`, \`STITCH_AI_API_KEY\`, \`CONTEXT7_API_KEY\`, and \`OPENCODE_RAG_URL\` when those services are enabled.
95
+
96
+ MCP usage:
97
+ - Run \`hiai-opencode doctor\` or \`hiai-opencode mcp-status\` for effective runtime MCP status.
98
+ - \`opencode mcp list\` often reads only static \`.mcp.json\`; plugin runtime MCP may work even when that list is empty.
99
+ - The plugin auto-exports \`.mcp.json\` when missing. Run \`hiai-opencode export-mcp .mcp.json\` to refresh static visibility.
100
+ - \`skill_mcp\` can call skill-embedded MCP and enabled hiai-opencode MCP. If an MCP is "not found", check whether the skill was loaded, whether \`hiai-opencode.json\` enables it, and whether static export is needed.
101
+
102
+ Memory and retrieval:
103
+ - MemPalace MCP is external. If enabled, use \`mempalace_status\` first, search before answering about remembered people/projects/past decisions, and write diary entries when appropriate. Never invent memories.
104
+ - RAG MCP is external/local. Use it for project knowledge search when \`OPENCODE_RAG_URL\` is configured or the default \`http://localhost:9002/tools/search\` is reachable.
105
+ - Sequential Thinking MCP is for complex planning/revision/branching, not for trivial edits.
106
+ - Firecrawl/Stitch/Context7 are external web/docs/research services; missing service keys should be reported by env var name only.
107
+
108
+ Installation/debugging:
109
+ - Use \`/doctor\` or \`hiai-opencode doctor\` before changing config.
110
+ - Prefer user-level or project-local installs. Do not use sudo/admin rights unless explicitly requested.
111
+ - If DCP is requested, install it separately with \`opencode plugin @tarquinen/opencode-dcp@latest --global\`.
112
+ </hiai-opencode-integration-primer>`
113
+ }
114
+
79
115
  export function buildResearcherSection(agents: AvailableAgent[]): string {
80
116
  const researcherAgent = agents.find((agent) => agent.name === "researcher")
81
117
  if (!researcherAgent) {
@@ -13,6 +13,7 @@ export {
13
13
  buildToolSelectionTable,
14
14
  buildResearcherSection,
15
15
  buildDelegationTable,
16
+ buildHiaiIntegrationPrimerSection,
16
17
  buildStrategistAndCriticSection,
17
18
  buildNonClaudePlannerSection,
18
19
  buildParallelDelegationSection,
@@ -135,7 +135,20 @@ function deriveMcp(config: HiaiOpencodeConfig): HiaiOpencodeConfig["mcp"] {
135
135
  return Object.fromEntries(
136
136
  Object.entries(defaults).map(([name, entry]) => {
137
137
  const override = userMcp[name] ?? {}
138
- return [name, { ...entry, ...override }]
138
+ const merged = { ...entry, ...override }
139
+
140
+ if (name === "mempalace" && typeof merged.pythonPath === "string" && merged.pythonPath.trim()) {
141
+ merged.environment = {
142
+ ...(entry.environment ?? {}),
143
+ ...(merged.environment ?? {}),
144
+ MEMPALACE_PYTHON: merged.pythonPath.trim(),
145
+ }
146
+ }
147
+
148
+ // Internal launcher hint; do not leak unknown keys into final OpenCode MCP server config.
149
+ delete merged.pythonPath
150
+
151
+ return [name, merged]
139
152
  }),
140
153
  )
141
154
  }
@@ -0,0 +1,55 @@
1
+ import { expect, test } from "bun:test"
2
+
3
+ import { applyModelSlots } from "./defaults"
4
+ import type { HiaiOpencodeConfig } from "./types"
5
+ import { buildStaticMcpJson, MCP_EXPORT_MARKER } from "../shared/mcp-static-export"
6
+ import { buildHiaiIntegrationPrimerSection } from "../agents/dynamic-agent-core-sections"
7
+
8
+ const baseConfig: HiaiOpencodeConfig = {
9
+ models: {
10
+ bob: { model: "openrouter/test/bob", recommended: "xhigh" },
11
+ coder: { model: "openrouter/test/coder", recommended: "high" },
12
+ strategist: { model: "openrouter/test/strategist", recommended: "high" },
13
+ guard: { model: "openrouter/test/guard", recommended: "middle" },
14
+ critic: { model: "openrouter/test/critic", recommended: "high" },
15
+ designer: { model: "openrouter/test/designer", recommended: "design" },
16
+ researcher: { model: "openrouter/test/researcher", recommended: "fast" },
17
+ manager: { model: "openrouter/test/manager", recommended: "fast" },
18
+ brainstormer: { model: "openrouter/test/brainstormer", recommended: "writing" },
19
+ vision: { model: "openrouter/test/vision", recommended: "vision" },
20
+ },
21
+ mcp: {
22
+ mempalace: { enabled: true, pythonPath: "/opt/venv/bin/python" },
23
+ },
24
+ }
25
+
26
+ test("model slots derive canonical agents and categories", () => {
27
+ const resolved = applyModelSlots(baseConfig)
28
+ expect(resolved.agents?.bob?.model).toBe("openrouter/test/bob")
29
+ expect(resolved.agents?.coder?.model).toBe("openrouter/test/coder")
30
+ expect(resolved.agents?.["platform-manager"]?.model).toBe("openrouter/test/manager")
31
+ expect(resolved.agents?.sub?.model).toBe("openrouter/test/coder")
32
+ expect(resolved.categories?.artistry?.model).toBe("openrouter/test/designer")
33
+ expect(resolved.categories?.ultrabrain?.model).toBe("openrouter/test/strategist")
34
+ expect(resolved.categories?.writing?.model).toBe("openrouter/test/brainstormer")
35
+ })
36
+
37
+ test("compact MCP mempalace pythonPath is materialized into environment", () => {
38
+ const resolved = applyModelSlots(baseConfig)
39
+ expect(resolved.mcp?.mempalace?.environment?.MEMPALACE_PYTHON).toBe("/opt/venv/bin/python")
40
+ })
41
+
42
+ test("static MCP export includes marker metadata and servers", () => {
43
+ const resolved = applyModelSlots(baseConfig)
44
+ const exported = buildStaticMcpJson(resolved)
45
+
46
+ expect(exported._meta?.generatedBy).toBe(MCP_EXPORT_MARKER)
47
+ expect(exported._meta?.version).toBe(1)
48
+ expect(exported.mcpServers.playwright).toBeDefined()
49
+ expect(exported.mcpServers.mempalace).toBeDefined()
50
+ })
51
+
52
+ test("integration primer does not request model provider API keys", () => {
53
+ const primer = buildHiaiIntegrationPrimerSection()
54
+ expect(primer).toContain("Do not ask for `OPENROUTER_API_KEY`, `OPENAI_API_KEY`, or `ANTHROPIC_API_KEY`")
55
+ })
@@ -76,6 +76,7 @@ export const McpServerConfigSchema = z.object({
76
76
  command: z.array(z.string()).optional(),
77
77
  timeout: z.number().optional(),
78
78
  environment: z.record(z.string(), z.string()).optional(),
79
+ pythonPath: z.string().optional(),
79
80
  });
80
81
 
81
82
  export const LspServerConfigSchema = z.object({
@@ -129,9 +130,6 @@ export const PermissionsConfigSchema = z.object({
129
130
  });
130
131
 
131
132
  export const AuthKeysSchema = z.object({
132
- googleSearch: z.string().optional(),
133
- openai: z.string().optional(),
134
- openrouter: z.string().optional(),
135
133
  stitch: z.string().optional(),
136
134
  firecrawl: z.string().optional(),
137
135
  context7: z.string().optional(),
@@ -10,6 +10,7 @@ export const BuiltinCommandNameSchema = z.enum([
10
10
  "stop-continuation",
11
11
  "remove-ai-slops",
12
12
  "mcp-status",
13
+ "doctor",
13
14
  ])
14
15
 
15
16
  export type BuiltinCommandName = z.infer<typeof BuiltinCommandNameSchema>
@@ -26,9 +26,6 @@ import { FastApplyConfigSchema } from "./fast-apply"
26
26
  import { WebsearchConfigSchema } from "./websearch"
27
27
 
28
28
  const AuthConfigSchema = z.object({
29
- googleSearch: z.string().optional(),
30
- openai: z.string().optional(),
31
- openrouter: z.string().optional(),
32
29
  stitch: z.string().optional(),
33
30
  firecrawl: z.string().optional(),
34
31
  context7: z.string().optional(),
@@ -150,6 +150,7 @@ export interface McpServerConfig {
150
150
  command?: string[];
151
151
  timeout?: number;
152
152
  environment?: Record<string, string>;
153
+ pythonPath?: string;
153
154
  }
154
155
 
155
156
  export interface LspServerConfig {
@@ -187,9 +188,6 @@ export interface PermissionsConfig {
187
188
  }
188
189
 
189
190
  export interface AuthKeys {
190
- googleSearch?: string;
191
- openai?: string;
192
- openrouter?: string;
193
191
  stitch?: string;
194
192
  firecrawl?: string;
195
193
  context7?: string;
@@ -9,6 +9,7 @@ import { START_WORK_TEMPLATE } from "./templates/start-work"
9
9
  import { HANDOFF_TEMPLATE } from "./templates/handoff"
10
10
  import { REMOVE_AI_SLOPS_TEMPLATE } from "./templates/remove-ai-slops"
11
11
  import { MCP_STATUS_TEMPLATE } from "./templates/mcp-status"
12
+ import { DOCTOR_TEMPLATE } from "./templates/doctor"
12
13
 
13
14
  interface LoadBuiltinCommandsOptions {
14
15
  useRegisteredAgents?: boolean
@@ -126,6 +127,12 @@ $ARGUMENTS
126
127
  description: "(builtin) Show hiai-opencode MCP server status, missing keys, and local runtime availability",
127
128
  template: `<command-instruction>
128
129
  ${MCP_STATUS_TEMPLATE}
130
+ </command-instruction>`,
131
+ },
132
+ doctor: {
133
+ description: "(builtin) Run hiai-opencode install/runtime diagnostics and explain setup issues",
134
+ template: `<command-instruction>
135
+ ${DOCTOR_TEMPLATE}
129
136
  </command-instruction>`,
130
137
  },
131
138
  }
@@ -0,0 +1,43 @@
1
+ export const DOCTOR_TEMPLATE = `# Hiai OpenCode Doctor Command
2
+
3
+ ## Purpose
4
+
5
+ Use /doctor to run the hiai-opencode install/runtime diagnostic and report actionable setup issues.
6
+
7
+ ## Execute
8
+
9
+ Run:
10
+
11
+ \`\`\`bash
12
+ hiai-opencode doctor
13
+ \`\`\`
14
+
15
+ If the binary is not on PATH, try the package-local fallback:
16
+
17
+ \`\`\`bash
18
+ node ./node_modules/@hiai-gg/hiai-opencode/assets/cli/hiai-opencode.mjs doctor
19
+ \`\`\`
20
+
21
+ ## Report
22
+
23
+ Summarize:
24
+
25
+ - config path
26
+ - enabled and disabled MCP servers
27
+ - missing env vars by name only
28
+ - static \`.mcp.json\` freshness and whether it is managed by hiai-opencode
29
+ - OpenCode Connect visibility for configured model providers
30
+ - OpenCode plugin registration sanity (including \`plugin: ["list"]\` misconfiguration warning)
31
+ - skill materialization status from skill registry
32
+ - agent count and naming summary
33
+ - LSP runtime availability
34
+ - MemPalace python source and selected interpreter (env/config/auto)
35
+ - MCP tool probes (real connect + tools/list) for stdio and basic endpoint probes for remote MCP
36
+
37
+ Rules:
38
+
39
+ - Do not print API key values.
40
+ - Do not ask for model provider env vars such as OPENROUTER_API_KEY or OPENAI_API_KEY; normal model auth belongs to OpenCode Connect.
41
+ - If \`opencode mcp list\` is empty but doctor/mcp-status sees servers, explain the runtime-vs-static config distinction and run \`hiai-opencode export-mcp .mcp.json\` if the user wants static visibility.
42
+ - Do not run package installs unless the user explicitly asks.
43
+ `
@@ -1,6 +1,6 @@
1
1
  import type { CommandDefinition } from "../claude-code-command-loader"
2
2
 
3
- export type BuiltinCommandName = "init-deep" | "ralph-loop" | "cancel-ralph" | "ulw-loop" | "refactor" | "start-work" | "stop-continuation" | "handoff" | "remove-ai-slops" | "mcp-status"
3
+ export type BuiltinCommandName = "init-deep" | "ralph-loop" | "cancel-ralph" | "ulw-loop" | "refactor" | "start-work" | "stop-continuation" | "handoff" | "remove-ai-slops" | "mcp-status" | "doctor"
4
4
 
5
5
  export interface BuiltinCommandConfig {
6
6
  disabled_commands?: BuiltinCommandName[]
@@ -0,0 +1,69 @@
1
+ import type { BuiltinSkill } from "../types"
2
+
3
+ export const hiaiOpencodeSetupSkill: BuiltinSkill = {
4
+ name: "hiai-opencode-setup",
5
+ description:
6
+ "Use when install/setup/onboarding or MCP debug mentions: install, setup, bootstrap, doctor, mcp-status, MCP not found, mcp list empty, MemPalace, RAG, firecrawl, stitch, sequential-thinking, playwright, DCP, agents, skills, or LSP.",
7
+ template: `# hiai-opencode Setup And Runtime Operations
8
+
9
+ Use this skill for hiai-opencode installation, diagnostics, and integration repair.
10
+
11
+ ## Architecture
12
+
13
+ - hiai-opencode is an OpenCode plugin, not a standalone app.
14
+ - MCP servers are external upstream tools launched by hiai-opencode wiring.
15
+ - The user-facing config is \`hiai-opencode.json\` or \`.opencode/hiai-opencode.json\`.
16
+ - Model provider credentials belong to OpenCode Connect. Do not ask for \`OPENROUTER_API_KEY\`, \`OPENAI_API_KEY\`, or \`ANTHROPIC_API_KEY\` for normal model usage.
17
+ - Service credentials are separate: \`FIRECRAWL_API_KEY\`, \`STITCH_AI_API_KEY\`, \`CONTEXT7_API_KEY\`.
18
+
19
+ ## First Diagnostic Commands
20
+
21
+ \`\`\`bash
22
+ hiai-opencode doctor
23
+ hiai-opencode mcp-status
24
+ opencode debug config
25
+ \`\`\`
26
+
27
+ If \`opencode mcp list\` is empty but doctor/mcp-status sees servers, explain that OpenCode's list may read only static \`.mcp.json\`. Refresh static visibility:
28
+
29
+ \`\`\`bash
30
+ hiai-opencode export-mcp .mcp.json
31
+ opencode mcp list --print-logs --log-level INFO
32
+ \`\`\`
33
+
34
+ ## Plugin vs MCP
35
+
36
+ Install OpenCode plugins with:
37
+
38
+ \`\`\`bash
39
+ opencode plugin @hiai-gg/hiai-opencode@latest --global
40
+ opencode plugin @tarquinen/opencode-dcp@latest --global
41
+ \`\`\`
42
+
43
+ Do not add MCP packages to the OpenCode plugin array. MCP packages are launched through \`hiai-opencode.json\` and helper scripts.
44
+
45
+ ## MCP Runtime Notes
46
+
47
+ - \`playwright\`: node/npx; browser binaries may need \`HIAI_PLAYWRIGHT_INSTALL_BROWSERS=1\`; Linux system deps may require admin rights.
48
+ - \`sequential-thinking\`: node/npx; use for complex planning, revision, and branching.
49
+ - \`firecrawl\`: requires \`FIRECRAWL_API_KEY\`.
50
+ - \`mempalace\`: prefers \`uv\`; otherwise Python 3.9+ with \`mempalace\`. Use \`mempalace_status\` first, search before answering memory questions, and never invent memories.
51
+ - \`rag\`: requires \`OPENCODE_RAG_URL\` or a reachable default \`http://localhost:9002/tools/search\`.
52
+ - \`stitch\`: requires \`STITCH_AI_API_KEY\`.
53
+ - \`context7\`: remote docs/search; key optional but recommended for limits.
54
+
55
+ ## Calling MCP
56
+
57
+ - Use native MCP tools if OpenCode exposes them.
58
+ - Use \`skill_mcp\` for skill-embedded MCP or enabled hiai-opencode MCP.
59
+ - If \`skill_mcp\` says a server is not found, check whether the skill is loaded, whether the MCP is enabled in \`hiai-opencode.json\`, and whether \`.mcp.json\` needs export.
60
+
61
+ ## Safety Rules
62
+
63
+ - Report missing keys by env var name only. Never print key values.
64
+ - Prefer project-local or user-level installs. Do not use sudo/admin rights unless the user explicitly asks.
65
+ - Do not edit unrelated OpenCode/Claude/Agents global skill folders unless the user opts in.
66
+ - Keep DCP separate: it is an optional OpenCode plugin, not part of the hiai-opencode package.
67
+ `,
68
+ allowedTools: ["Bash(*)", "Read(*)", "Edit(*)", "Glob(*)", "Grep(*)", "skill_mcp(*)"],
69
+ }
@@ -5,3 +5,4 @@ export { gitMasterSkill } from "./git-master"
5
5
  export { devBrowserSkill } from "./dev-browser"
6
6
  export { reviewWorkSkill } from "./review-work"
7
7
  export { aiSlopRemoverSkill } from "./ai-slop-remover"
8
+ export { hiaiOpencodeSetupSkill } from "./hiai-opencode-setup"
@@ -10,6 +10,7 @@ import {
10
10
  devBrowserSkill,
11
11
  reviewWorkSkill,
12
12
  aiSlopRemoverSkill,
13
+ hiaiOpencodeSetupSkill,
13
14
  } from "./skills/index"
14
15
 
15
16
  export interface CreateBuiltinSkillsOptions {
@@ -29,7 +30,15 @@ export function createBuiltinSkills(options: CreateBuiltinSkillsOptions = {}): B
29
30
  browserSkill = playwrightSkill
30
31
  }
31
32
 
32
- const skills = [browserSkill, frontendUiUxSkill, gitMasterSkill, devBrowserSkill, reviewWorkSkill, aiSlopRemoverSkill]
33
+ const skills = [
34
+ browserSkill,
35
+ hiaiOpencodeSetupSkill,
36
+ frontendUiUxSkill,
37
+ gitMasterSkill,
38
+ devBrowserSkill,
39
+ reviewWorkSkill,
40
+ aiSlopRemoverSkill,
41
+ ]
33
42
 
34
43
  if (!disabledSkills) {
35
44
  return skills