@psnext/s-subagents 0.1.20260522-1

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.
@@ -0,0 +1,24 @@
1
+ [
2
+ {
3
+ "id": "hook-1779457904343-864",
4
+ "name": "Code review",
5
+ "description": "Review the code for all coding standard",
6
+ "triggerType": "file_saved",
7
+ "filePaths": "src/*.js",
8
+ "prompt": "Analyze the recently saved file and provide a comprehensive code review with actionable feedback. Focus on:\n\n**Code Quality & Standards:**\n- Adherence to language-specific coding conventions and style guidelines\n- Proper naming conventions for variables, functions, and classes\n- Code structure, readability, and maintainability\n- Consistent formatting and indentation\n\n**Best Practices:**\n- Error handling and edge case management\n- Performance considerations and potential optimizations\n- Security vulnerabilities or concerns\n- Code reusability and DRY principles\n- Proper commenting and documentation\n\n**Technical Review:**\n- Logic correctness and potential bugs\n- Resource management (memory, file handles, connections)\n- Appropriate use of design patterns\n- Type safety and null checks where applicable\n\n**Output Format:**\nProvide specific, line-referenced feedback when possible. Categorize issues by severity (Critical, Major, Minor, Suggestion). Include positive observations alongside improvement recommendations. Keep comments constructive and educational, explaining the \"why\" behind each suggestion.\n\nIf no issues are found, acknowledge good practices observed in the code.",
9
+ "agentId": "coding-agent",
10
+ "parameters": {
11
+ "task": "Analyze the recently saved file and provide a comprehensive code review with actionable feedback. Focus on:\n\n**Code Quality & Standards:**\n- Adherence to language-specific coding conventions and style guidelines\n- Proper naming conventions for variables, functions, and classes\n- Code structure, readability, and maintainability\n- Consistent formatting and indentation\n\n**Best Practices:**\n- Error handling and edge case management\n- Performance considerations and potential optimizations\n- Security vulnerabilities or concerns\n- Code reusability and DRY principles\n- Proper commenting and documentation\n\n**Technical Review:**\n- Logic correctness and potential bugs\n- Resource management (memory, file handles, connections)\n- Appropriate use of design patterns\n- Type safety and null checks where applicable\n\n**Output Format:**\nProvide specific, line-referenced feedback when possible. Categorize issues by severity (Critical, Major, Minor, Suggestion). Include positive observations alongside improvement recommendations. Keep comments constructive and educational, explaining the \"why\" behind each suggestion.\n\nIf no issues are found, acknowledge good practices observed in the code.",
12
+ "files": [
13
+ "src/*.js"
14
+ ],
15
+ "context": "Review the code for all coding standard"
16
+ },
17
+ "enabled": false,
18
+ "createdBy": "user",
19
+ "tags": [],
20
+ "debounceDuration": "120000",
21
+ "createdAt": "2026-05-22T13:51:44.411Z",
22
+ "updatedAt": "2026-05-22T13:51:44.411Z"
23
+ }
24
+ ]
@@ -0,0 +1,15 @@
1
+ {
2
+ "filename": "index.ts",
3
+ "path": "index.ts",
4
+ "version": "1.1",
5
+ "files": {},
6
+ "promptMessage": {
7
+ "0dbda967": {
8
+ "value": "Cannot find name 'node:child_process'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.ts"
9
+ }
10
+ },
11
+ "localPrompts": {},
12
+ "remotePrompts": {},
13
+ "figma": {},
14
+ "jira": {}
15
+ }
@@ -0,0 +1,101 @@
1
+ {
2
+ "index.ts": {
3
+ "filename": "index.ts",
4
+ "path": "index.ts",
5
+ "version": "1.2",
6
+ "contextFile": "51adc022-context.json",
7
+ "chunks": {
8
+ "33a9a4": {
9
+ "user": "Rakesh Ravuri",
10
+ "model": "claude-sonnet-4-5@20250929",
11
+ "timestamp": 1779458883,
12
+ "platform": "VisualStudioCode",
13
+ "product": "AIPP",
14
+ "productVersion": "2.5.0",
15
+ "source": "chat",
16
+ "type": "compareCode",
17
+ "extraContext": {
18
+ "promptMessage": "0dbda967"
19
+ },
20
+ "hash": "0d52ee42",
21
+ "messageId": "system_980f1e50-55e7-11f1-92a0-cdb27b9735e4",
22
+ "codeBlockId": "system_980f1e50-55e7-11f1-92a0-cdb27b9735e4-Codeblock-2",
23
+ "isActive": false
24
+ },
25
+ "ee44cb": {
26
+ "user": "Rakesh Ravuri",
27
+ "model": "claude-sonnet-4-5@20250929",
28
+ "timestamp": 1779458886,
29
+ "platform": "VisualStudioCode",
30
+ "product": "AIPP",
31
+ "productVersion": "2.5.0",
32
+ "source": "chat",
33
+ "type": "insertCode",
34
+ "extraContext": {
35
+ "promptMessage": "0dbda967"
36
+ },
37
+ "hash": "0d52ee42",
38
+ "messageId": "system_980f1e50-55e7-11f1-92a0-cdb27b9735e4",
39
+ "codeBlockId": "system_980f1e50-55e7-11f1-92a0-cdb27b9735e4-Codeblock-2",
40
+ "isActive": true
41
+ },
42
+ "3caf2e": {
43
+ "user": "Rakesh Ravuri",
44
+ "model": "claude-sonnet-4-5@20250929",
45
+ "timestamp": 1779458886,
46
+ "platform": "VisualStudioCode",
47
+ "product": "AIPP",
48
+ "productVersion": "2.5.0",
49
+ "source": "chat",
50
+ "type": "pasteCode",
51
+ "extraContext": {
52
+ "promptMessage": "0dbda967"
53
+ },
54
+ "hash": "0d52ee42",
55
+ "messageId": "system_980f1e50-55e7-11f1-92a0-cdb27b9735e4",
56
+ "codeBlockId": "system_980f1e50-55e7-11f1-92a0-cdb27b9735e4-Codeblock-2",
57
+ "isActive": false
58
+ }
59
+ },
60
+ "lines": {
61
+ "32": {
62
+ "chunkId": "ee44cb",
63
+ "hash": "699fd80f",
64
+ "encoded": "%7D",
65
+ "prevChunkIds": []
66
+ },
67
+ "55": {
68
+ "chunkId": "ee44cb",
69
+ "hash": "2ef1d392",
70
+ "encoded": "%7D",
71
+ "prevChunkIds": []
72
+ },
73
+ "71": {
74
+ "chunkId": "ee44cb",
75
+ "hash": "f064f9d6",
76
+ "encoded": "%7D",
77
+ "prevChunkIds": []
78
+ },
79
+ "429": {
80
+ "chunkId": "ee44cb",
81
+ "hash": "bd760bbf",
82
+ "encoded": "%7D,",
83
+ "prevChunkIds": [
84
+ "ee44cb"
85
+ ]
86
+ },
87
+ "872": {
88
+ "chunkId": "ee44cb",
89
+ "hash": "c3395656",
90
+ "encoded": "%7D,",
91
+ "prevChunkIds": []
92
+ },
93
+ "913": {
94
+ "chunkId": "ee44cb",
95
+ "hash": "f8f5c1fc",
96
+ "encoded": "%7D,",
97
+ "prevChunkIds": []
98
+ }
99
+ }
100
+ }
101
+ }
@@ -0,0 +1,87 @@
1
+ {
2
+ "tsconfig.json": {
3
+ "filename": "tsconfig.json",
4
+ "path": "tsconfig.json",
5
+ "version": "1.2",
6
+ "contextFile": null,
7
+ "chunks": {
8
+ "ba71e7": {
9
+ "user": "Rakesh Ravuri",
10
+ "model": "claude-sonnet-4-5@20250929",
11
+ "timestamp": 1779458900,
12
+ "platform": "VisualStudioCode",
13
+ "product": "AIPP",
14
+ "productVersion": "2.5.0",
15
+ "source": "chat",
16
+ "type": "createFileWithCode",
17
+ "extraContext": {},
18
+ "hash": "0d52ee42",
19
+ "messageId": "2f82f3d1-de96-4e70-b6f0-6bd10a200ad6",
20
+ "codeBlockId": null,
21
+ "isActive": true
22
+ }
23
+ },
24
+ "lines": {
25
+ "0": {
26
+ "chunkId": "ba71e7",
27
+ "hash": "47009686",
28
+ "encoded": "%7B",
29
+ "prevChunkIds": []
30
+ },
31
+ "1": {
32
+ "chunkId": "ba71e7",
33
+ "hash": "c1221f13",
34
+ "encoded": "%22compilerOptions%22:%20%7B",
35
+ "prevChunkIds": []
36
+ },
37
+ "2": {
38
+ "chunkId": "ba71e7",
39
+ "hash": "dbfbff26",
40
+ "encoded": "%22types%22:%20%5B%22node%22%5D,",
41
+ "prevChunkIds": []
42
+ },
43
+ "4": {
44
+ "chunkId": "ba71e7",
45
+ "hash": "57c8aecd",
46
+ "encoded": "%22esModuleInterop%22:%20true,",
47
+ "prevChunkIds": []
48
+ },
49
+ "5": {
50
+ "chunkId": "ba71e7",
51
+ "hash": "54a5ae06",
52
+ "encoded": "%22skipLibCheck%22:%20true,",
53
+ "prevChunkIds": []
54
+ },
55
+ "6": {
56
+ "chunkId": "ba71e7",
57
+ "hash": "fe5f646c",
58
+ "encoded": "%22target%22:%20%22ES2020%22,",
59
+ "prevChunkIds": []
60
+ },
61
+ "9": {
62
+ "chunkId": "ba71e7",
63
+ "hash": "e58a5dfb",
64
+ "encoded": "%7D,",
65
+ "prevChunkIds": []
66
+ },
67
+ "10": {
68
+ "chunkId": "ba71e7",
69
+ "hash": "ce5ebcb5",
70
+ "encoded": "%22include%22:%20%5B%22**/*.ts%22%5D,",
71
+ "prevChunkIds": []
72
+ },
73
+ "11": {
74
+ "chunkId": "ba71e7",
75
+ "hash": "b7a45cbe",
76
+ "encoded": "%22exclude%22:%20%5B%22node_modules%22%5D",
77
+ "prevChunkIds": []
78
+ },
79
+ "12": {
80
+ "chunkId": "ba71e7",
81
+ "hash": "6a3f2143",
82
+ "encoded": "%7D",
83
+ "prevChunkIds": []
84
+ }
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,118 @@
1
+
2
+ SAMPLE LOCAL PROMPT
3
+ ───────────────────────────────
4
+ Welcome to your Slingshot Local Prompt setup!
5
+
6
+ ───────────────────────────────
7
+ HOW IT WORKS
8
+ ───────────────────────────────
9
+ You can add your own ".prompt.md" files under either of these folders available at the root of your repository
10
+ (In case you don't see these folders, you can either create them manually or follow the steps mentioned below):
11
+
12
+ • .slingshot/prompts/ ← recommended option
13
+ • .github/prompts/
14
+
15
+ All prompt files with the ".prompt.md" extension inside these folders are automatically available in the Prompt Select Drawer.
16
+
17
+ ───────────────────────────────
18
+ HOW TO CREATE A PROMPT
19
+ ───────────────────────────────
20
+ You can create a new prompt file by:
21
+ • Clicking on "Add/Edit Prompt File" from the Slash Command Drawer
22
+ OR
23
+ • Running the Slingshot command "Create or Open Prompt File"
24
+
25
+ ───────────────────────────────
26
+ HOW TO USE A PROMPT
27
+ ───────────────────────────────
28
+ You can use your local prompt by:
29
+ • Clicking on "Attach Prompt Commands" from the Slash Command Drawer
30
+ OR
31
+ • Typing the shortcut key "~" in the chat input box
32
+
33
+ The filename of your prompt will act as the command name.
34
+ You can use multiple local prompts at a time, but only one non-local prompt.
35
+
36
+ ───────────────────────────────
37
+ USING PLACEHOLDERS AND VARIABLES
38
+ ───────────────────────────────
39
+ You can reference the following VSCode workspace variables in your prompts:
40
+ When creating custom prompts, users can reference the following workspace variables to dynamically insert context-specific information:
41
+
42
+ - ${userHome}: Path of the user's home folder.
43
+ - ${workspaceFolder}: Path of the folder opened in VS Code.
44
+ - ${workspaceFolderBasename}: Name of the folder opened in VS Code without any slashes (/).
45
+ - ${file}: Currently opened file.
46
+ - ${fileWorkspaceFolder}: Currently opened file's workspace folder.
47
+ - ${relativeFile}: Currently opened file relative to workspaceFolder.
48
+ - ${relativeFileDirname}: Currently opened file's dirname relative to workspaceFolder.
49
+ - ${fileBasename}: Currently opened file's basename.
50
+ - ${fileBasenameNoExtension}: Currently opened file's basename with no file extension.
51
+ - ${fileExtname}: Currently opened file's extension.
52
+ - ${fileDirname}: Currently opened file's folder path.
53
+ - ${fileDirnameBasename}: Currently opened file's folder name.
54
+ - ${cwd}: Task runner's current working directory upon the startup of VS Code.
55
+ - ${lineNumber}: Currently selected line number in the active file.
56
+ - ${columnNumber}: Currently selected column number in the active file.
57
+ - ${selectedText}: Currently selected text in the active file.
58
+ - ${execPath}: Path to the running VS Code executable.
59
+ - ${pathSeparator}: Character used by the operating system to separate components in file paths.
60
+
61
+ Additionally, you can define custom placeholders such as "{file_name}". These placeholders can be replaced with specific values when the prompt is used.
62
+
63
+ **Rules for Placeholders:**
64
+ - Do not include special characters like "?", "*", "+", "^", "|", "&", "!", "@", "#", "$", "%", "^", "(", ")", "=", "[", "]", ";", ":", "'", """, "<", ">", ",", ".", "/", "", "~", and "" ` "" within placeholders.
65
+ - Do not use double curly brackets "{{}}".
66
+ - Ensure placeholders are clearly defined and meaningful.
67
+
68
+ ───────────────────────────────
69
+ ENVIRONMENT VARIABLES
70
+ ───────────────────────────────
71
+ You can reference environment variables from your system using the %{VARIABLE_NAME} syntax:
72
+
73
+ Common examples:
74
+ - %{HOME}: User's home directory path
75
+ - %{USER}: Current username
76
+ - %{PATH}: System PATH environment variable
77
+ - %{NODE_ENV}: Node.js environment (development, production, etc.)
78
+ - %{API_KEY}: Custom API keys or secrets
79
+ - %{DATABASE_URL}: Database connection strings
80
+
81
+ You can also reference local environment variables defined in your .env file
82
+
83
+ Example usage:
84
+ "Hello %{USER}! Working in %{NODE_ENV} environment from %{HOME} working on %{MY_CUSTOM_VAR}"
85
+
86
+ Note: Environment variables are resolved at prompt execution time, if you add new variables to your .env file, you may need to refresh VS Code window. Type %{ in your prompt to see available variables with autocomplete.
87
+
88
+ ───────────────────────────────
89
+ REFERENCING PROMPTS AND FILES
90
+ ───────────────────────────────
91
+ You can reference other local prompts and files within a prompt:
92
+ • Reference prompts using ~{promptname} syntax.
93
+ • Reference files using #{path/to/file.txt} syntax.
94
+
95
+ ───────────────────────────────
96
+ SAMPLE PROMPT
97
+ ───────────────────────────────
98
+ For example:
99
+
100
+ My Custom Code Generation Prompt
101
+ --------------------------------
102
+ ## Follow all the below best practices while generating code
103
+
104
+ - Ensure code readability with meaningful variable and function names
105
+ - Maintain consistent formatting and indentation
106
+ - Avoid deep nesting and keep functions short and focused
107
+ - Handle errors and exceptions gracefully
108
+ - Write efficient and performant logic
109
+ - Add comments where necessary for complex logic
110
+ - Follow security best practices and avoid hardcoding secrets
111
+ - Include necessary input validations and edge case handling
112
+ - Prefer reusability and modularity over duplication
113
+ - Follow project-specific coding conventions and linting rules
114
+
115
+ ───────────────────────────────
116
+ TIP
117
+ ───────────────────────────────
118
+ Keep your prompts clear, short, and well-structured for the best results.
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,3 @@
1
+ {
2
+ "Slingshot.readFileLineLimit": 3000
3
+ }
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # Minimal Subagents
2
+
3
+ A [sling](https://www.npmjs.com/package/@psnext/slingcli) extension that registers a single `subagent` tool with three agents:
4
+
5
+ | Agent | Tools | Model | Purpose |
6
+ |-------|-------|-------|---------|
7
+ | **scout** | read, grep, find, ls | claude-haiku-4-5 | Fast codebase recon |
8
+ | **researcher** | web_search, web_fetch | claude-sonnet-4-6 | Web research |
9
+ | **worker** | read, write, edit, safe_bash, web_search, web_fetch, subagent | claude-sonnet-4-6 | Code changes (can dispatch scout/researcher to protect its own context) |
10
+
11
+ `worker` is allowlisted to spawn only `scout` and `researcher` (via `subagent_agents` in its frontmatter), so the chain stops at depth 2 — a worker cannot recurse into another worker.
12
+
13
+ ## Dependencies
14
+
15
+ `safe_bash` ships in this repo (`tools/safe-bash.ts`). `web_search` and `web_fetch` do not — `researcher` and `worker` depend on them. Grab those two extensions from [amosblomqvist/pi-config](https://github.com/amosblomqvist/pi-config) (`extensions/web-search/`, `extensions/web-fetch/`) and drop them into `~/.pi/agent/extensions/`. Without them the affected agents will launch with an empty tool allowlist and silently do nothing useful.
16
+
17
+ ## Usage
18
+
19
+ One tool call = one subagent:
20
+ ```json
21
+ { "agent": "scout", "task": "Find all auth-related files in src/" }
22
+ ```
23
+
24
+ To fan out, emit multiple `subagent` tool calls in the same assistant turn — pi runs them in parallel automatically. A per-process semaphore caps simultaneous subagents at `maxConcurrency` (default 4); calls past the cap wait their turn.
25
+
26
+ Each subagent runs as an isolated `pi` process with no inherited context — all context must be in the task description.
27
+
28
+ ## Config
29
+
30
+ Optional `config.json` next to `index.ts`:
31
+
32
+ ```json
33
+ { "maxConcurrency": 4 }
34
+ ```
35
+
36
+ ## Output
37
+
38
+ Subagents return text only — there's no file handoff. If the parent needs artifacts, instruct the subagent to `write` them and return the path.
39
+
40
+ Large outputs (>`DEFAULT_MAX_BYTES`) are head-truncated before being returned to the parent.
41
+
42
+ ## UI
43
+
44
+ Two levels, toggled with `ctrl+o`:
45
+
46
+ - **Collapsed (default):** the tool call shows one line — `subagent <agent> <60-char task preview>`. The result block shows the agent header (status, tool count, duration), the chronological tool log (one line per call, running calls marked with `▸`), the latest prose "thinking" line, and a usage line (tokens in/out, cache, cost, context-window gauge).
47
+ - **Expanded:** the call header streams the full task body live as the parent writes it (like `write`/`edit`). The result block additionally renders the subagent's full final output as markdown. Nested children (when a worker spawns scout/researcher) render inline, indented under the row that dispatched them, with their own per-row context gauge.
48
+
49
+ ## Registering Agents from Other Extensions
50
+
51
+ Other extensions can dynamically register and unregister agents at runtime. This is useful for domain-specific agents that should only be available when a particular extension is active.
52
+
53
+ ### 1. Define agent `.md` files
54
+
55
+ Create markdown files with YAML frontmatter in your extension's directory (e.g. `my-extension/agents/my-agent.md`):
56
+
57
+ ```markdown
58
+ ---
59
+ name: my-agent
60
+ description: Does a specific thing
61
+ tools: web_search, video_extract
62
+ model: claude-sonnet-4-20250514
63
+ ---
64
+
65
+ You are an agent that does a specific thing...
66
+ ```
67
+
68
+ Frontmatter fields:
69
+ - **name** (required) — unique agent name, used in `{ agent: "my-agent" }` calls
70
+ - **description** — short description
71
+ - **tools** — comma-separated list of tools the agent needs (builtin or extension). Include `subagent` here to let this agent spawn other agents.
72
+ - **model** — model identifier (defaults to `anthropic/claude-sonnet-4-6`)
73
+ - **thinking** — reasoning level: `off`, `low`, `medium`, `high` (defaults to `medium`)
74
+ - **subagent_agents** — if `subagent` is in `tools`, restrict which agents this one may spawn. Comma-separated list of agent names. Omit for no restriction. Enforced by passing `PI_SUBAGENT_ALLOWED` env to the child `pi` process — the child's subagents extension filters its registry before any tool description sees it, so the child LLM literally can't reference an agent outside the allowlist.
75
+
76
+ The markdown body becomes the agent's system prompt.
77
+
78
+ ### 2. Register agents via `globalThis.__pi_subagents`
79
+
80
+ Pi loads extensions via jiti, which creates separate module instances. Direct imports from the subagents extension will reference a different `agents` array than the one the `subagent` tool uses. Use the `globalThis` bridge instead:
81
+
82
+ ```typescript
83
+ import { parseFrontmatter } from "@earendil-works/pi-coding-agent";
84
+ import * as fs from "node:fs";
85
+ import * as path from "node:path";
86
+
87
+ interface AgentConfig {
88
+ name: string;
89
+ description: string;
90
+ tools: string[];
91
+ model: string;
92
+ thinking: string; // "off" | "low" | "medium" | "high"
93
+ systemPrompt: string;
94
+ filePath: string;
95
+ subagentAgents?: string[]; // optional spawn-allowlist when `subagent` is in tools
96
+ }
97
+
98
+ const AGENTS_DIR = path.join(path.dirname(new URL(import.meta.url).pathname), "agents");
99
+
100
+ function registerMyAgents(): void {
101
+ const subagents = (globalThis as any).__pi_subagents as
102
+ | { registerAgent: (config: AgentConfig) => void; unregisterAgent: (name: string) => void }
103
+ | undefined;
104
+ if (!subagents) return; // subagents extension not loaded
105
+
106
+ for (const entry of fs.readdirSync(AGENTS_DIR)) {
107
+ if (!entry.endsWith(".md")) continue;
108
+ const filePath = path.join(AGENTS_DIR, entry);
109
+ const content = fs.readFileSync(filePath, "utf-8");
110
+ const { frontmatter, body } = parseFrontmatter<Record<string, string>>(content);
111
+ if (!frontmatter.name) continue;
112
+
113
+ const tools = (frontmatter.tools || "").split(",").map(t => t.trim()).filter(Boolean);
114
+ const subagentAgents = frontmatter.subagent_agents
115
+ ? frontmatter.subagent_agents.split(",").map(t => t.trim()).filter(Boolean)
116
+ : undefined;
117
+ try {
118
+ subagents.registerAgent({
119
+ name: frontmatter.name,
120
+ description: frontmatter.description || "",
121
+ tools,
122
+ model: frontmatter.model || "anthropic/claude-sonnet-4-6",
123
+ thinking: frontmatter.thinking || "medium",
124
+ systemPrompt: body,
125
+ filePath,
126
+ ...(subagentAgents ? { subagentAgents } : {}),
127
+ });
128
+ } catch {
129
+ // Already registered — skip
130
+ }
131
+ }
132
+ }
133
+ ```
134
+
135
+ Call `registerMyAgents()` when your extension activates (e.g. in a command handler). The agents become available to the `subagent` tool immediately.
136
+
137
+ ### 3. Adding custom tool support
138
+
139
+ If your agents need tools beyond the built-in set, those tools must be mapped in the `CUSTOM_TOOL_EXTENSIONS` record in `subagents/index.ts`:
140
+
141
+ ```typescript
142
+ const CUSTOM_TOOL_EXTENSIONS: Record<string, string> = {
143
+ web_search: path.join(EXT_BASE, "web-search", "index.ts"),
144
+ web_fetch: path.join(EXT_BASE, "web-fetch", "index.ts"),
145
+ safe_bash: path.join(TOOLS_DIR, "safe-bash.ts"),
146
+ video_extract: path.join(EXT_BASE, "video-extract", "index.ts"),
147
+ youtube_search: path.join(EXT_BASE, "youtube-search", "index.ts"),
148
+ google_image_search: path.join(EXT_BASE, "google-image-search", "index.ts"),
149
+ };
150
+ ```
151
+
152
+ Built-in tools (`read`, `write`, `edit`, `bash`, `grep`, `find`, `ls`) work automatically. Any other tool the agent lists in its frontmatter must have a corresponding entry here pointing to the extension's `index.ts`.
153
+
154
+ The `subagent` tool itself is listed in `CUSTOM_TOOL_EXTENSIONS` pointing back to this extension's own `index.ts` — that's how an agent like `worker` can recursively spawn other agents. Recursion is bounded only by each agent's `subagent_agents` allowlist (e.g. worker can spawn scout/researcher, neither of which declares the `subagent` tool, so the chain stops at depth 2).
155
+
156
+ ## Structure
157
+
158
+ ```
159
+ subagents/
160
+ ├── index.ts # Extension entry point
161
+ ├── agents/ # Built-in agent configs (frontmatter + system prompt)
162
+ └── tools/ # Extensions loaded into subagent processes
163
+ └── safe-bash.ts # bash with dangerous command blocking
164
+ ```
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: researcher
3
+ description: Web researcher — searches the web and synthesizes findings
4
+ tools: web_search, web_fetch
5
+ model: claude-sonnet-4-5@20250929
6
+ thinking: medium
7
+ ---
8
+
9
+ You are a research specialist. Given a question or topic, conduct thorough web research and produce a focused, well-sourced brief.
10
+
11
+ Process:
12
+ 1. Break the question into 2-4 searchable facets
13
+ 2. Search with `web_search` using varied angles
14
+ 3. Read the answers. Identify what's well-covered, what has gaps.
15
+ 4. For the 2-3 most promising source URLs, use `web_fetch` to get full page content
16
+ 5. Synthesize everything into a brief that directly answers the question
17
+
18
+ Search strategy — always vary your angles:
19
+ - Direct answer query (the obvious one)
20
+ - Authoritative source query (official docs, specs, primary sources)
21
+ - Practical experience query (case studies, benchmarks, real-world usage)
22
+ - Recent developments query (only if the topic is time-sensitive)
23
+
24
+ Evaluation — what to keep vs drop:
25
+ - Official docs and primary sources outweigh blog posts and forum threads
26
+ - Recent sources outweigh stale ones
27
+ - Sources that directly address the question outweigh tangentially related ones
28
+ - Drop: SEO filler, outdated info, beginner tutorials (unless that's the audience)
29
+
30
+ If the first round of searches doesn't fully answer the question, search again with refined queries targeting the gaps.
31
+
32
+ Output format:
33
+
34
+ ## Summary
35
+ 2-3 sentence direct answer.
36
+
37
+ ## Findings
38
+ Numbered findings with inline source citations:
39
+ 1. **Finding** — explanation. [Source](url)
40
+ 2. **Finding** — explanation. [Source](url)
41
+
42
+ ## Sources
43
+ - Kept: Source Title (url) — why relevant
44
+ - Dropped: Source Title — why excluded
45
+
46
+ ## Gaps
47
+ What couldn't be answered. Suggested next steps.
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: scout
3
+ description: Fast codebase recon — explores files, finds patterns, maps architecture
4
+ tools: read, grep, find, ls
5
+ model: gpt-5.4-nano
6
+ thinking: medium
7
+ ---
8
+
9
+ You are a scout agent. Quickly investigate a codebase and return structured findings.
10
+
11
+ Thoroughness (infer from task, default medium):
12
+ - Quick: Targeted lookups, key files only
13
+ - Medium: Follow imports, read critical sections
14
+ - Thorough: Trace all dependencies, check tests/types
15
+
16
+ Strategy:
17
+ 1. grep/find to locate relevant code
18
+ 2. Read key sections (not entire files)
19
+ 3. Identify types, interfaces, key functions
20
+ 4. Note dependencies between files
21
+
22
+ Output format:
23
+
24
+ ## Files Found
25
+ List with exact line ranges:
26
+ 1. `path/to/file.ts` (lines 10-50) — Description
27
+ 2. `path/to/other.ts` (lines 100-150) — Description
28
+
29
+ ## Key Code
30
+ Critical types, interfaces, or functions with actual code snippets.
31
+
32
+ ## Architecture
33
+ Brief explanation of how the pieces connect.
34
+
35
+ ## Start Here
36
+ Which file to look at first and why.