agent-switchboard 0.1.24 → 0.1.26

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/README.md CHANGED
@@ -1,341 +1,280 @@
1
1
  # Agent Switchboard
2
2
 
3
- Manage MCP servers, rules, commands, subagents, and skills in one place and apply them to local agents (Codex, Claude Code/Desktop, Cursor, Gemini, and OpenCode).
3
+ [![npm version](https://img.shields.io/npm/v/agent-switchboard)](https://www.npmjs.com/package/agent-switchboard)
4
+ [![CI](https://github.com/qyhfrank/agent-switchboard/actions/workflows/ci.yml/badge.svg)](https://github.com/qyhfrank/agent-switchboard/actions/workflows/ci.yml)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
4
6
 
5
- You can run with either `agent-switchboard` or the shorter alias `asb`.
7
+ Manage MCP servers, rules, commands, subagents, and skills from a single source of truth, then sync them to every AI coding agent you use.
6
8
 
7
- ## Installation
9
+ Alias: `asb`
8
10
 
9
- Global install:
11
+ ## Why
12
+
13
+ AI coding agents (Codex, Claude Code, Cursor, Gemini, OpenCode ...) each store MCP servers, prompt rules, slash commands, and skills in their own formats and locations. When you add a new MCP server or tweak a coding rule, you repeat the work for each agent. Configs drift, setups go stale.
14
+
15
+ Agent Switchboard solves this with **one library, one config, many targets**:
10
16
 
11
- ```bash
12
- npm i -g agent-switchboard
13
17
  ```
18
+ Libraries Config Layers Distribution
19
+ ┌──────────────┐ ┌─────────────────────┐ ┌────────────────┐
20
+ │ mcp.json │ │ User config.toml │ │ Claude Code │
21
+ │ rules/ │ │ Profile <name>.toml │ │ Codex │
22
+ │ commands/ │ ─► │ Project .asb.toml │ ─► │ Cursor │
23
+ │ subagents/ │ │ │ │ Gemini │
24
+ │ skills/ │ │ Per-agent overrides │ │ OpenCode │
25
+ └──────────────┘ └─────────────────────┘ │ Claude Desktop │
26
+ └────────────────┘
27
+ ```
28
+
29
+ All library entries are agent-agnostic Markdown files (or directories for skills). Agent Switchboard reads them, applies layered configuration and per-agent overrides, then writes the correct format to each agent's config location.
30
+
31
+ ## Compatibility
14
32
 
15
- Run once without installing:
33
+ | Feature | Claude Code | Codex | Cursor | Gemini | OpenCode | Claude Desktop |
34
+ |:-----------------|:-----------:|:-----:|:------:|:------:|:--------:|:--------------:|
35
+ | MCP servers | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
36
+ | Project-level MCP| ✓ | ✓ | ✓ | ✓ | ✓ | |
37
+ | Rules | ✓ | ✓ | ✓ mdc | ✓ | ✓ | |
38
+ | Commands | ✓ | ✓\* | ✓ | ✓ | ✓ | |
39
+ | Subagents | ✓ | | ✓ | | ✓ | |
40
+ | Skills | ✓ | ✓ | ✓ | ✓ | ✓ | |
41
+
42
+ \* Codex commands use deprecated `~/.codex/prompts/`; prefer skills instead.
43
+
44
+ Cursor rules are distributed as individual `.mdc` files to `~/.cursor/rules/` (native format), not as a single composed document.
45
+
46
+ ## Quick Start
16
47
 
17
48
  ```bash
18
- npx agent-switchboard@latest mcp
49
+ npm i -g agent-switchboard # or: npx agent-switchboard@latest mcp
19
50
  ```
20
51
 
21
- ## Quick Start
52
+ 1. **Pick your agents** -- create `~/.agent-switchboard/config.toml`:
22
53
 
23
- 1) Create `~/.agent-switchboard/mcp.json` (if missing).
24
- 2) Run the interactive UI:
54
+ ```toml
55
+ [agents]
56
+ active = ["claude-code", "codex", "cursor"]
57
+ ```
58
+
59
+ 2. **Manage MCP servers** -- launches an interactive checkbox UI:
60
+
61
+ ```bash
62
+ asb mcp
63
+ ```
64
+
65
+ 3. **Sync everything** -- pushes all libraries (rules, commands, subagents, skills) and MCP config to every active agent:
25
66
 
26
67
  ```bash
27
- agent-switchboard mcp
68
+ asb sync
28
69
  ```
29
70
 
30
- Thats it. The tool updates `~/.agent-switchboard/mcp.json` and writes agent configs.
71
+ That's it. Library content lives under `~/.agent-switchboard/` and agent configs are updated in place.
72
+
73
+ ## Command Reference
74
+
75
+ | Command | Description |
76
+ |:---------------------|:--------------------------------------------------------|
77
+ | `asb mcp` | Interactive MCP server selector |
78
+ | `asb rule` | Interactive rule snippet selector with ordering |
79
+ | `asb command` | Interactive command selector |
80
+ | `asb subagent` | Interactive subagent selector |
81
+ | `asb skill` | Interactive skill selector |
82
+ | `asb sync` | Push all libraries + MCP to agents (no UI) |
83
+ | `asb <lib> load` | Import files from a platform into the library |
84
+ | `asb <lib> list` | Show inventory, activation state, and sync timestamps |
85
+ | `asb subscribe` | Add an external library subscription |
86
+ | `asb unsubscribe` | Remove a subscription |
87
+ | `asb subscriptions` | List active subscriptions |
31
88
 
32
- ## Configure Agents
89
+ `<lib>` = `rule`, `command`, `subagent`, or `skill`.
33
90
 
34
- Agent Switchboard only applies MCP servers to the agents you list in `~/.agent-switchboard/config.toml`.
91
+ **Shared flags**: `-p, --profile <name>`, `--project <path>`, `--json` (on `list` and `subscriptions`).
35
92
 
36
- Create the file if it does not exist:
93
+ ## Configuration
94
+
95
+ ### `config.toml`
96
+
97
+ The central config file at `~/.agent-switchboard/config.toml` controls which agents and library entries are active:
37
98
 
38
99
  ```toml
39
- # ~/.agent-switchboard/config.toml
40
100
  [agents]
41
- active = ["codex", "cursor"]
101
+ active = ["claude-code", "codex", "cursor", "gemini", "opencode"]
42
102
 
43
103
  [rules]
44
- includeDelimiters = false
45
- ```
46
-
47
- Supported agent IDs:
48
- - `codex` - Codex CLI
49
- - `cursor` - Cursor IDE
50
- - `claude-code` - Claude Code CLI
51
- - `claude-desktop` - Claude Desktop app
52
- - `gemini` - Gemini CLI
53
- - `opencode` - OpenCode (supports `opencode.json` and `opencode.jsonc`)
54
-
55
- Toggle `rules.includeDelimiters` to `true` if you want each snippet surrounded by markers such as:
56
- ```
57
- <!-- your-rule-name:start -->
58
-
59
- <!-- your-rule-name:end -->
104
+ includeDelimiters = false # wrap each rule snippet in <!-- id:start/end --> markers
60
105
  ```
61
106
 
62
- Run `agent-switchboard mcp` again after updating the list.
107
+ Supported agent IDs: `claude-code`, `claude-desktop`, `codex`, `cursor`, `gemini`, `opencode`.
63
108
 
64
109
  ### Per-Agent Overrides
65
110
 
66
- You can customize which rules, commands, subagents, and skills are active for each agent using `add` and `remove` syntax:
111
+ Fine-tune which library entries reach each agent using `add` / `remove` / `active`:
67
112
 
68
113
  ```toml
69
114
  [agents]
70
115
  active = ["claude-code", "codex", "opencode"]
71
116
 
72
- # Codex: exclude skill-codex (avoid self-reference)
73
117
  codex.skills.remove = ["skill-codex"]
74
- codex.rules.remove = ["skill-codex"]
118
+ codex.rules.remove = ["skill-codex"]
75
119
 
76
- # OpenCode: same exclusions
77
- opencode.skills.remove = ["skill-codex"]
78
- opencode.rules.remove = ["skill-codex"]
79
-
80
- # Gemini: add extra command, remove a skill
81
- gemini.commands.add = ["cmd-gemini-only"]
82
- gemini.skills.remove = ["skill-go"]
120
+ gemini.commands.add = ["cmd-gemini-only"]
121
+ gemini.skills.remove = ["skill-go"]
83
122
  ```
84
123
 
85
- | Syntax | Behavior |
86
- |--------|----------|
87
- | `<agent>.<section>.active = [...]` | Completely override the global list |
88
- | `<agent>.<section>.add = [...]` | Append to the global list |
89
- | `<agent>.<section>.remove = [...]` | Remove from the global list |
90
-
91
- Sections: `mcp`, `commands`, `subagents`, `skills`, `rules`
124
+ | Syntax | Behavior |
125
+ |:----------------------------------|:---------------------------|
126
+ | `<agent>.<section>.active = [...]`| Replace the global list |
127
+ | `<agent>.<section>.add = [...]` | Append to the global list |
128
+ | `<agent>.<section>.remove = [...]`| Remove from the global list|
92
129
 
93
- ### Layered configuration & scope
130
+ Sections: `mcp`, `rules`, `commands`, `subagents`, `skills`.
94
131
 
95
- Agent Switchboard merges configuration from three TOML layers (higher priority wins):
132
+ ### Layered Configuration
96
133
 
97
- - **User default**: `<ASB_HOME>/config.toml`
98
- - **Profile**: `<ASB_HOME>/<profile>.toml`
99
- - **Project**: `<project>/.asb.toml`
134
+ Three TOML layers merge in priority order (higher wins):
100
135
 
101
- Every layer can define `[commands]`, `[subagents]`, and `[rules]` `active` lists. Use profiles to share team presets and project files to override per repository. The CLI honors these layers via scope flags:
136
+ | Layer | File | Scope |
137
+ |:--------|:--------------------------------|:----------------------------------|
138
+ | User | `<ASB_HOME>/config.toml` | Personal defaults |
139
+ | Profile | `<ASB_HOME>/<profile>.toml` | Team or workflow presets (`-p`) |
140
+ | Project | `<project>/.asb.toml` | Per-repository overrides |
102
141
 
103
142
  ```bash
104
- # Profile only
105
- agent-switchboard command -p team
143
+ asb command -p team # profile layer
144
+ asb rule --project /path/to/repo # project layer
145
+ asb subagent -p team --project /path/to/repo # both
146
+ ```
106
147
 
107
- # Project only
108
- agent-switchboard rule --project /path/to/repo
148
+ When `--project` is used, outputs target the project directory (e.g. `<project>/AGENTS.md`, `<project>/.claude/commands/`).
109
149
 
110
- # Merge profile + project
111
- agent-switchboard subagent -p team --project /path/to/repo
112
- ```
150
+ ## Libraries
151
+
152
+ All library types follow the same pattern:
113
153
 
114
- `ASB_HOME` still defaults to `~/.agent-switchboard` but can be overridden through the environment variable.
154
+ 1. **Store** entries in `~/.agent-switchboard/<type>/` as Markdown files (or directories for skills).
155
+ 2. **Import** existing platform files: `asb <type> load <platform> [path] [-r]`.
156
+ 3. **Select** active entries: `asb <type>` (interactive fuzzy-search selector).
157
+ 4. **Audit** inventory: `asb <type> list [--json]`.
115
158
 
116
- Project-aware outputs (when using `--project <path>`):
117
- - Rules: Codex writes `<project>/AGENTS.md`. Gemini writes `<project>/AGENTS.md`. OpenCode writes `<project>/.opencode/AGENTS.md`.
118
- - Commands (project-level supported):
119
- - Claude Code → `<project>/.claude/commands/`
120
- - Gemini → `<project>/.gemini/commands/`
121
- - OpenCode → `<project>/.opencode/command/`
122
- - Codex → global only (`~/.codex/prompts/`, deprecated; consider migrating to skills)
123
- - Subagents (project-level supported):
124
- - Claude Code → `<project>/.claude/agents/`
125
- - OpenCode → `<project>/.opencode/agent/`
126
- - Skills (project-level supported):
127
- - Claude Code → `<project>/.claude/skills/`
128
- - Gemini → `<project>/.gemini/skills/`
129
- - OpenCode → `<project>/.opencode/skill/`
130
- - Codex → `~/.agents/skills/` (global) or `<project>/.agents/skills/` (project-level)
159
+ Selections are saved into the highest-priority config layer. Distribution writes each entry in the format the target agent expects, skipping unchanged files (hash-based).
131
160
 
132
- ## Rule Library
161
+ ### Rules
133
162
 
134
- Rule snippets live in `~/.agent-switchboard/rules/` (respects `ASB_HOME`). Each snippet is a Markdown file and can include YAML frontmatter with `title`, `description`, `tags`, and `requires` fields. Example:
163
+ Snippets in `~/.agent-switchboard/rules/` with optional YAML frontmatter:
135
164
 
136
165
  ```markdown
137
166
  ---
138
167
  title: Prompt Hygiene
139
- tags:
140
- - hygiene
141
- requires:
142
- - claude-code
168
+ tags: [hygiene]
169
+ requires: [claude-code]
143
170
  ---
144
171
  Keep commit messages scoped to the change.
145
172
  ```
146
173
 
147
- ### Selecting and Ordering Rules
174
+ Cursor-specific options can be set via `extras.cursor` in rule frontmatter:
148
175
 
149
- Use the interactive selector (arrow keys, `Space` to toggle, just start typing to fuzzy filter) to choose the active snippets and adjust their order:
150
-
151
- ```bash
152
- agent-switchboard rule [-p <profile>] [--project <path>]
153
- ```
154
-
155
- The selected order is saved back to the highest-priority layer (project, profile, then user) before distribution. Once confirmed, Agent Switchboard composes the merged Markdown, stores the active order, and writes the document to:
156
- - `~/.claude/CLAUDE.md`
157
- - `~/.codex/AGENTS.md` (or `<project>/AGENTS.md` with `--project`)
158
- - `~/.gemini/AGENTS.md`
159
- - `~/.config/opencode/AGENTS.md` (or `%APPDATA%/opencode/AGENTS.md` on Windows)
160
-
161
- Unsupportive agents such as Claude Desktop and Cursor are reported and left untouched. If you rerun the selector without changing the order, the tool refreshes the destination files to overwrite any manual edits.
162
-
163
- ### Auditing Rules
164
-
165
- See the full inventory, activation state, and per-agent sync timestamps:
166
-
167
- ```bash
168
- agent-switchboard rule list [-p <profile>] [--project <path>]
176
+ ```markdown
177
+ ---
178
+ title: Python Rules
179
+ description: Python coding standards
180
+ extras:
181
+ cursor:
182
+ alwaysApply: false
183
+ globs: "*.py"
184
+ ---
185
+ Use type hints everywhere.
169
186
  ```
170
187
 
171
- ## Command Library
188
+ The interactive selector lets you **reorder** snippets. For most agents, rules are composed into a single document. For Cursor, each rule is written as an individual `.mdc` file with native frontmatter (`description`, `alwaysApply`, `globs`):
172
189
 
173
- - Location: `~/.agent-switchboard/commands/<slug>.md` (respects `ASB_HOME`).
174
- - Frontmatter: only global `description` (optional). Any platform-native options must live under `extras.<platform>` and are written through verbatim. No parsing, no key renaming, no documentation of platform keys here.
190
+ | Agent | Global output | Project output |
191
+ |:------------|:------------------------------------|:----------------------------------|
192
+ | Claude Code | `~/.claude/CLAUDE.md` | `<project>/.claude/CLAUDE.md` |
193
+ | Codex | `~/.codex/AGENTS.md` | `<project>/AGENTS.md` |
194
+ | Cursor | `~/.cursor/rules/<id>.mdc` | `<project>/.cursor/rules/<id>.mdc`|
195
+ | Gemini | `~/.gemini/AGENTS.md` | `<project>/.gemini/AGENTS.md` |
196
+ | OpenCode | `~/.config/opencode/AGENTS.md` | `<project>/AGENTS.md` |
175
197
 
176
- ### Import
177
-
178
- ```bash
179
- # Import an existing platform file or directory into the library
180
- # Use -r/--recursive to traverse subdirectories when <path> is a directory
181
- agent-switchboard command load <platform> [path] [-r]
182
- # <platform>: claude-code | codex | gemini | opencode
183
- # If [path] is omitted, defaults by platform:
184
- # claude-code → ~/.claude/commands
185
- # codex → ~/.codex/prompts
186
- # gemini → ~/.gemini/commands
187
- # opencode → ~/.config/opencode/command (Windows: %APPDATA%/opencode/command)
188
- ```
198
+ ### Commands
189
199
 
190
- ### Select and Distribute
200
+ Markdown files in `~/.agent-switchboard/commands/` with optional `description` and `extras.<platform>`:
191
201
 
192
202
  ```bash
193
- agent-switchboard command [-p <profile>] [--project <path>]
203
+ asb command load claude-code # import from ~/.claude/commands/
204
+ asb command load gemini [path] -r # import recursively
194
205
  ```
195
206
 
196
- The selector supports fuzzy filtering—type any part of a title, ID, or model name to narrow the list. Confirming selections saves them back into the highest-priority configuration layer before distribution. Adapters then write each selected command to the corresponding platform output in your user home (platform defaults), using the file format that platform expects. The frontmatter consists of the global `description` (if present) plus `extras.<platform>` written as-is.
207
+ Platforms: `claude-code`, `codex`, `cursor`, `gemini`, `opencode`.
197
208
 
198
- Files are only rewritten when content changes.
209
+ ### Subagents
199
210
 
200
- ### Inventory
211
+ Same format as commands, stored in `~/.agent-switchboard/subagents/`.
201
212
 
202
213
  ```bash
203
- # Inventory
204
- agent-switchboard command list [-p <profile>] [--project <path>]
214
+ asb subagent load claude-code # import from ~/.claude/agents/
205
215
  ```
206
216
 
207
- ## Subagent Library
217
+ Platforms: `claude-code`, `opencode`, `cursor`.
208
218
 
209
- - Location: `~/.agent-switchboard/subagents/<slug>.md` (respects `ASB_HOME`).
210
- - Frontmatter: only global `description` (optional). Any platform-native options must live under `extras.<platform>` and are written through verbatim. We do not parse, validate, or showcase platform key names in this README. Platforms that do not support subagent files are skipped.
219
+ ### Skills
211
220
 
212
- ### Import
221
+ Multi-file directory bundles in `~/.agent-switchboard/skills/<skill-id>/`, each containing a `SKILL.md` entry file:
213
222
 
214
- ```bash
215
- agent-switchboard subagent load <platform> [path] [-r]
216
- # <platform>: claude-code | opencode
217
- # If [path] is omitted, defaults by platform:
218
- # claude-code → ~/.claude/agents
219
- # opencode → ~/.config/opencode/agent (Windows: %APPDATA%/opencode/agent)
220
223
  ```
221
-
222
- ### Select and Distribute
223
-
224
- ```bash
225
- agent-switchboard subagent [-p <profile>] [--project <path>]
224
+ ~/.agent-switchboard/skills/my-skill/
225
+ ├── SKILL.md # name + description in frontmatter
226
+ ├── helper.py
227
+ └── templates/
228
+ └── template.txt
226
229
  ```
227
230
 
228
- Type to fuzzy filter the list, then confirm to persist the selection into the active configuration layer. Adapters write each selected subagent to the corresponding platform output in your user home (platform defaults), using the file format that platform expects. The frontmatter consists of the global `description` (if present) plus `extras.<platform>` written as-is. Platforms that do not accept subagent files are skipped with a hint.
229
-
230
- ### Inventory
231
-
232
231
  ```bash
233
- agent-switchboard subagent list [-p <profile>] [--project <path>]
232
+ asb skill load claude-code # import from ~/.claude/skills/
233
+ asb skill load codex # import from ~/.agents/skills/
234
234
  ```
235
235
 
236
- ## Skill Library
237
-
238
- Skills are multi-file bundles (directories) that provide reusable capabilities to agents. Each skill is a directory containing a `SKILL.md` file and any supporting files.
239
-
240
- - Location: `~/.agent-switchboard/skills/<skill-id>/` (respects `ASB_HOME`).
241
- - Entry file: `SKILL.md` with required `name` and `description` in frontmatter.
236
+ Entire directories are copied to each agent's skill location. Deactivated skills are cleaned up automatically.
242
237
 
243
- Example structure:
244
-
245
- ```
246
- ~/.agent-switchboard/skills/
247
- └── my-skill/
248
- ├── SKILL.md
249
- ├── helper.py
250
- └── templates/
251
- └── template.txt
252
- ```
238
+ ## Library Subscriptions
253
239
 
254
- Example `SKILL.md`:
255
-
256
- ```markdown
257
- ---
258
- name: my-skill
259
- description: A helpful skill that does something useful
260
- extras:
261
- claude-code:
262
- # Platform-specific options
263
- ---
264
- Skill instructions and content here.
265
- ```
266
-
267
- ### Import
268
-
269
- ```bash
270
- # Import skills from an existing platform directory
271
- agent-switchboard skill load <platform> [path]
272
- # <platform>: claude-code | codex
273
- # If [path] is omitted, defaults by platform:
274
- # claude-code → ~/.claude/skills
275
- # codex → ~/.agents/skills (fallback: ~/.codex/skills)
276
- ```
277
-
278
- ### Select and Distribute
240
+ Pull library entries from external directories (e.g. a team-shared repo):
279
241
 
280
242
  ```bash
281
- agent-switchboard skill [-p <profile>] [--project <path>]
243
+ asb subscribe team /path/to/team-library
244
+ asb subscriptions # list active subscriptions
245
+ asb unsubscribe team # remove
282
246
  ```
283
247
 
284
- Type to fuzzy filter the list, then confirm to persist the selection. Skills are distributed as complete directory bundles to supported platforms:
285
- - Claude Code → `~/.claude/skills/<skill-id>/`
286
- - Codex → `~/.agents/skills/<skill-id>/` (or `<project>/.agents/skills/<skill-id>/`)
287
- - Gemini → `~/.gemini/skills/<skill-id>/`
288
- - OpenCode → `~/.config/opencode/skill/<skill-id>/`
289
-
290
- ### Inventory
291
-
292
- ```bash
293
- agent-switchboard skill list [-p <profile>] [--project <path>]
294
- ```
248
+ The subscription path must contain at least one of `rules/`, `commands/`, `subagents/`, or `skills/`. Entries from subscriptions appear with a namespace prefix (e.g. `team:my-rule`) in selectors and config.
295
249
 
296
250
  ## Sync
297
251
 
298
- After curating your `active` lists in the selectors, run the unified sync command to push rules, commands, subagents, and skills to every supported agent directory:
252
+ Push all libraries and MCP config to every active agent in one step:
299
253
 
300
254
  ```bash
301
- agent-switchboard sync [-p <profile>] [--project <path>]
255
+ asb sync [-p <profile>] [--project <path>]
302
256
  ```
303
257
 
304
- The command merges the layered configuration, prints a warning that files will be overwritten without diffs, and rewrites the target files for each platform in place. Use profiles or project scopes to preview changes before applying them globally.
258
+ This merges layered config, applies per-agent overrides, and writes target files in place. Files are only rewritten when content changes.
305
259
 
306
260
  ## Environment
307
261
 
308
- - `ASB_HOME`: overrides `~/.agent-switchboard` for library/state files.
309
- - `ASB_AGENTS_HOME`: overrides the home directory used for agent config paths (defaults to OS user home).
310
-
311
- ## JSON Output
312
-
313
- All `list` subcommands support `--json` for machine-readable output:
314
-
315
- ```bash
316
- agent-switchboard rule list --json
317
- agent-switchboard command list --json
318
- agent-switchboard subagent list --json
319
- agent-switchboard skill list --json
320
- ```
262
+ | Variable | Default | Purpose |
263
+ |:-----------------|:---------------------------|:---------------------------------------------|
264
+ | `ASB_HOME` | `~/.agent-switchboard` | Library, config, and state directory |
265
+ | `ASB_AGENTS_HOME`| OS user home | Base path for agent config locations |
321
266
 
322
267
  ## Development
323
268
 
324
- Install dependencies, build, and link globally:
325
-
326
269
  ```bash
327
270
  pnpm install
328
271
  pnpm build
329
- pnpm link --global
272
+ pnpm link --global # global `agent-switchboard` points to local build
330
273
  ```
331
274
 
332
- After linking, the global `agent-switchboard` command points to your local build. Code changes take effect after running `pnpm build` again.
333
-
334
- To unlink:
275
+ Code changes take effect after `pnpm build`. To unlink: `pnpm uninstall -g agent-switchboard`.
335
276
 
336
- ```bash
337
- pnpm uninstall -g agent-switchboard
338
- ```
277
+ Other scripts: `pnpm dev` (tsx), `pnpm test`, `pnpm lint`, `pnpm typecheck`.
339
278
 
340
279
  ## License
341
280
 
@@ -1,12 +1,9 @@
1
1
  /**
2
2
  * Cursor agent adapter
3
- * Manages MCP server configuration for Cursor IDE
3
+ * Manages MCP server configuration for Cursor IDE/CLI
4
4
  */
5
5
  import type { McpServer } from '../config/schemas.js';
6
6
  import type { AgentAdapter } from './adapter.js';
7
- /**
8
- * Cursor config file structure
9
- */
10
7
  /**
11
8
  * Cursor agent adapter
12
9
  * Config location: ~/.cursor/mcp.json
@@ -1,15 +1,11 @@
1
1
  /**
2
2
  * Cursor agent adapter
3
- * Manages MCP server configuration for Cursor IDE
3
+ * Manages MCP server configuration for Cursor IDE/CLI
4
4
  */
5
5
  import fs from 'node:fs';
6
- import os from 'node:os';
7
6
  import path from 'node:path';
7
+ import { getCursorDir, getProjectCursorDir } from '../config/paths.js';
8
8
  import { loadJsonFile, mergeMcpIntoAgent, saveJsonFile, } from './json-utils.js';
9
- /**
10
- * Cursor config file structure
11
- */
12
- // Uses shared JsonAgentConfig
13
9
  /**
14
10
  * Cursor agent adapter
15
11
  * Config location: ~/.cursor/mcp.json
@@ -17,16 +13,13 @@ import { loadJsonFile, mergeMcpIntoAgent, saveJsonFile, } from './json-utils.js'
17
13
  export class CursorAgent {
18
14
  id = 'cursor';
19
15
  configPath() {
20
- const base = process.env.ASB_AGENTS_HOME && process.env.ASB_AGENTS_HOME.trim().length > 0
21
- ? process.env.ASB_AGENTS_HOME
22
- : os.homedir();
23
- return path.join(base, '.cursor', 'mcp.json');
16
+ return path.join(getCursorDir(), 'mcp.json');
24
17
  }
25
18
  /**
26
19
  * Project-level config: <project>/.cursor/mcp.json
27
20
  */
28
21
  projectConfigPath(projectRoot) {
29
- return path.join(path.resolve(projectRoot), '.cursor', 'mcp.json');
22
+ return path.join(getProjectCursorDir(projectRoot), 'mcp.json');
30
23
  }
31
24
  applyConfig(config) {
32
25
  const configPath = this.configPath();
@@ -38,7 +31,6 @@ export class CursorAgent {
38
31
  const configPath = this.projectConfigPath(projectRoot);
39
32
  const existing = loadJsonFile(configPath, { mcpServers: {} });
40
33
  const merged = mergeMcpIntoAgent(existing, config.mcpServers);
41
- // Ensure .cursor directory exists
42
34
  const dir = path.dirname(configPath);
43
35
  if (!fs.existsSync(dir))
44
36
  fs.mkdirSync(dir, { recursive: true });
@@ -1 +1 @@
1
- {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/agents/cursor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAEL,YAAY,EACZ,iBAAiB,EACjB,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB;;GAEG;AACH,8BAA8B;AAE9B;;;GAGG;AACH,MAAM,OAAO,WAAW;IACb,EAAE,GAAG,QAAiB,CAAC;IAEhC,UAAU;QACR,MAAM,IAAI,GACR,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAC1E,CAAC,CAAE,OAAO,CAAC,GAAG,CAAC,eAA0B;YACzC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,WAAmB;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IACrE,CAAC;IAED,WAAW,CAAC,MAAkE;QAC5E,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QACrC,MAAM,WAAW,GAAG,YAAY,CAAkB,UAAU,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QAClF,MAAM,MAAM,GAAG,iBAAiB,CAAC,WAAW,EAAE,MAAM,CAAC,UAAoC,CAAC,CAAC;QAC3F,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,kBAAkB,CAChB,WAAmB,EACnB,MAAkE;QAElE,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,YAAY,CAAkB,UAAU,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/E,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAoC,CAAC,CAAC;QACxF,kCAAkC;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;CACF"}
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/agents/cursor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAGvE,OAAO,EAEL,YAAY,EACZ,iBAAiB,EACjB,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB;;;GAGG;AACH,MAAM,OAAO,WAAW;IACb,EAAE,GAAG,QAAiB,CAAC;IAEhC,UAAU;QACR,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,WAAmB;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC,CAAC;IACjE,CAAC;IAED,WAAW,CAAC,MAAkE;QAC5E,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QACrC,MAAM,WAAW,GAAG,YAAY,CAAkB,UAAU,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QAClF,MAAM,MAAM,GAAG,iBAAiB,CAAC,WAAW,EAAE,MAAM,CAAC,UAAoC,CAAC,CAAC;QAC3F,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,kBAAkB,CAChB,WAAmB,EACnB,MAAkE;QAElE,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,YAAY,CAAkB,UAAU,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/E,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAoC,CAAC,CAAC;QACxF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;CACF"}
@@ -1,6 +1,6 @@
1
1
  import type { ConfigScope } from '../config/scope.js';
2
2
  import { type DistributeOutcome } from '../library/distribute.js';
3
- export type CommandPlatform = 'claude-code' | 'codex' | 'gemini' | 'opencode';
3
+ export type CommandPlatform = 'claude-code' | 'codex' | 'cursor' | 'gemini' | 'opencode';
4
4
  export interface CommandDistributionResult {
5
5
  platform: CommandPlatform;
6
6
  filePath: string;
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { stringify as toToml } from '@iarna/toml';
3
- import { getClaudeDir, getCodexDir, getGeminiDir, getOpencodePath, getProjectClaudeDir, getProjectGeminiDir, getProjectOpencodePath, } from '../config/paths.js';
3
+ import { getClaudeDir, getCodexDir, getCursorDir, getGeminiDir, getOpencodePath, getProjectClaudeDir, getProjectCursorDir, getProjectGeminiDir, getProjectOpencodePath, } from '../config/paths.js';
4
4
  import { distributeLibrary, } from '../library/distribute.js';
5
5
  import { loadLibraryStateSectionForAgent } from '../library/state.js';
6
6
  import { wrapFrontmatter } from '../util/frontmatter.js';
@@ -26,6 +26,12 @@ function resolveCommandTargetDir(platform, scope) {
26
26
  case 'codex': {
27
27
  return path.join(getCodexDir(), 'prompts');
28
28
  }
29
+ case 'cursor': {
30
+ if (projectRoot && projectRoot.length > 0) {
31
+ return path.join(getProjectCursorDir(projectRoot), 'commands');
32
+ }
33
+ return path.join(getCursorDir(), 'commands');
34
+ }
29
35
  case 'gemini': {
30
36
  if (projectRoot && projectRoot.length > 0) {
31
37
  return path.join(getProjectGeminiDir(projectRoot), 'commands');
@@ -98,12 +104,15 @@ function renderForPlatform(platform, entry) {
98
104
  const fm = buildFrontmatterForOpencode(entry);
99
105
  return wrapFrontmatter(fm, entry.content);
100
106
  }
107
+ case 'cursor': {
108
+ return `${entry.content.trimEnd()}\n`;
109
+ }
101
110
  }
102
111
  }
103
112
  export function distributeCommands(scope) {
104
113
  const entries = loadCommandLibrary();
105
114
  const byId = new Map(entries.map((e) => [e.id, e]));
106
- const platforms = ['claude-code', 'codex', 'gemini', 'opencode'];
115
+ const platforms = ['claude-code', 'codex', 'cursor', 'gemini', 'opencode'];
107
116
  // Cleanup config to remove orphan command files
108
117
  const cleanup = {
109
118
  resolveTargetDir: (p) => resolveCommandTargetDir(p, scope),