Skip to content

Commit ff4d3f2

Browse files
cameroncookeclaude
andcommitted
ref(runtime): Simplify daemon routing and normalize manifests
Remove legacy daemon routing knobs and CLI daemon flags so routing is driven by tool statefulness plus the explicit xcode-ide special case. Add idle shutdown with an activity lease registry so long-running tools signal lifecycle activity without hardcoded daemon imports. Clean manifest files by removing values that match schema defaults and regenerate generated tool documentation. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 10b8b4a commit ff4d3f2

131 files changed

Lines changed: 1738 additions & 1157 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77

88
### Changed
99
- Hide `xcode_tools_bridge_{status,sync,disconnect}` unless `debug: true` is enabled (these are troubleshooting tools).
10+
- Simplified CLI daemon routing: stateless tools now always execute directly, stateful tools route through daemon with auto-start, and dynamic `xcode-ide` bridge tools remain an explicit daemon-backed special-case.
11+
- Removed manifest daemon routing knobs `availability.daemon` and `routing.daemonAffinity`; manifests now use `availability.{mcp,cli}` plus optional `routing.stateful`.
12+
- Removed hidden CLI daemon-routing flags; stateful routing is now automatic and only hidden `--socket` remains for advanced socket override workflows.
13+
- Added daemon idle shutdown in CLI mode: per-workspace daemons now auto-exit after 10 minutes of inactivity when no active stateful sessions exist.
14+
- Inverted idle activity tracking to a generic daemon activity registry so long-running tools report lifecycle activity without hardcoded daemon imports.
1015

1116
## [2.0.0] - 2026-02-02
1217

docs/CLI.md

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -121,28 +121,34 @@ See [CONFIGURATION.md](CONFIGURATION.md) for the full schema.
121121
| Variable | Description |
122122
|----------|-------------|
123123
| `XCODEBUILDMCP_SOCKET` | Override socket path for all commands |
124+
| `XCODEBUILDMCP_DAEMON_IDLE_TIMEOUT_MS` | Daemon idle timeout in ms (default `600000`, set `0` to disable) |
124125
| `XCODEBUILDMCP_DISABLE_SESSION_DEFAULTS` | Disable session defaults |
125126

126127
## CLI vs MCP Mode
127128

128129
| Feature | CLI (`xcodebuildmcp <tool>`) | MCP (`xcodebuildmcp mcp`) |
129130
|---------|------------------------------|---------------------------|
130131
| Invocation | Direct terminal | MCP client (Claude, etc.) |
131-
| Session state | Per-workspace daemon | In-process |
132+
| Session state | Stateless direct + daemon for stateful tools | In-process |
132133
| Use case | Scripts, CI, manual | AI-assisted development |
133134
| Configuration | Same config.yaml | Same config.yaml |
134135

135136
Both share the same underlying tool implementations.
136137

137138
## Per-Workspace Daemon
138139

139-
The CLI uses a per-workspace daemon architecture for stateful operations (log capture, video recording, debugging). Each workspace gets its own daemon instance.
140+
The CLI uses a per-workspace daemon architecture only when needed:
141+
142+
- Stateless tools run directly in the CLI process.
143+
- Stateful tools route through the daemon (auto-started as needed).
144+
- Dynamic `xcode-ide` bridge tools are a special-case daemon-backed path for persistent bridge sessions.
140145

141146
### How It Works
142147

143148
- **Workspace identity**: The workspace root is determined by the location of `.xcodebuildmcp/config.yaml`, or falls back to the current directory.
144149
- **Socket location**: Each daemon runs on a Unix socket at `~/.xcodebuildmcp/daemons/<workspace-key>/daemon.sock`
145150
- **Auto-start**: The daemon starts automatically when you invoke a stateful tool - no manual setup required.
151+
- **Auto-shutdown**: The daemon exits after 10 minutes of inactivity, but only when there are no active stateful sessions (log capture, debugging, video capture, background swift-package processes).
146152

147153
### Daemon Commands
148154

@@ -198,16 +204,6 @@ Daemons:
198204
Total: 2 (1 running, 1 stale)
199205
```
200206
201-
### Opting Out of Daemon
202-
203-
If you want to disable daemon auto-start (stateful tools will error):
204-
205-
```bash
206-
xcodebuildmcp build-sim --no-daemon --scheme MyApp
207-
```
208-
209-
This is useful for CI environments or when you want explicit control.
210-
211207
## Stateful vs Stateless Tools
212208
213209
### Stateless Tools (run in-process)
@@ -230,8 +226,6 @@ When you invoke a stateful tool, the daemon auto-starts if needed.
230226
| Option | Description |
231227
|--------|-------------|
232228
| `--socket <path>` | Override the daemon socket path (hidden) |
233-
| `--daemon` | Force daemon execution for stateless tools (hidden) |
234-
| `--no-daemon` | Disable daemon usage; stateful tools will fail |
235229
| `-h, --help` | Show help |
236230
| `-v, --version` | Show version |
237231
@@ -266,4 +260,4 @@ The socket directory (`~/.xcodebuildmcp/daemons/`) should have mode 0700. If you
266260
```bash
267261
chmod 700 ~/.xcodebuildmcp
268262
chmod -R 700 ~/.xcodebuildmcp/daemons
269-
```
263+
```

docs/TOOLS-CLI.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,4 @@ XcodeBuildMCP provides 71 canonical tools organized into 13 workflow groups.
187187

188188
---
189189

190-
*This documentation is automatically generated by `scripts/update-tools-docs.ts` from the tools manifest. Last updated: 2026-02-05T21:23:22.870Z UTC*
190+
*This documentation is automatically generated by `scripts/update-tools-docs.ts` from the tools manifest. Last updated: 2026-02-06T11:40:14.287Z UTC*

docs/TOOLS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,4 @@ This document lists MCP tool names as exposed to MCP clients. XcodeBuildMCP prov
202202

203203
---
204204

205-
*This documentation is automatically generated by `scripts/update-tools-docs.ts` from the tools manifest. Last updated: 2026-02-05T21:23:22.870Z UTC*
205+
*This documentation is automatically generated by `scripts/update-tools-docs.ts` from the tools manifest. Last updated: 2026-02-06T11:40:14.287Z UTC*

docs/dev/MANIFEST_FORMAT.md

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,9 @@ description: string # Tool description (shown in tool listings)
5656
availability: # Per-runtime availability flags
5757
mcp: boolean # Available via MCP server (default: true)
5858
cli: boolean # Available via CLI (default: true)
59-
daemon: boolean # Available via daemon (default: true)
6059
predicates: string[] # Predicate names for visibility filtering (default: [])
61-
routing: # Daemon routing hints
60+
routing: # CLI daemon routing
6261
stateful: boolean # Tool maintains state (default: false)
63-
daemonAffinity: enum # 'preferred' or 'required' (optional)
6462
annotations: # MCP tool annotations (hints for clients)
6563
title: string # Human-readable title (optional)
6664
readOnlyHint: boolean # Tool only reads data (optional)
@@ -80,11 +78,7 @@ description: "List available iOS simulators."
8078
availability:
8179
mcp: true
8280
cli: true
83-
daemon: true
8481
predicates: []
85-
routing:
86-
stateful: false
87-
daemonAffinity: preferred
8882
annotations:
8983
title: "List Simulators"
9084
readOnlyHint: true
@@ -101,12 +95,8 @@ description: "Build for iOS sim."
10195
availability:
10296
mcp: true
10397
cli: true
104-
daemon: true
10598
predicates:
10699
- hideWhenXcodeAgentMode # Hidden when Xcode provides equivalent tool
107-
routing:
108-
stateful: false
109-
daemonAffinity: preferred
110100
```
111101
112102
### Example: MCP-Only Tool
@@ -120,7 +110,6 @@ description: "Manage enabled workflows at runtime."
120110
availability:
121111
mcp: true
122112
cli: false # Not available in CLI
123-
daemon: false # Not available via daemon
124113
predicates:
125114
- experimentalWorkflowDiscoveryEnabled
126115
```
@@ -142,7 +131,6 @@ tools: string[] # Array of tool IDs belonging to this workflow
142131
availability: # Per-runtime availability flags
143132
mcp: boolean # Available via MCP server (default: true)
144133
cli: boolean # Available via CLI (default: true)
145-
daemon: boolean # Available via daemon (default: true)
146134
selection: # MCP selection rules
147135
mcp:
148136
defaultEnabled: boolean # Enabled when config.enabledWorkflows is empty (default: false)
@@ -159,7 +147,6 @@ description: "Complete iOS development workflow for simulators."
159147
availability:
160148
mcp: true
161149
cli: true
162-
daemon: true
163150
selection:
164151
mcp:
165152
defaultEnabled: true # Enabled by default
@@ -183,7 +170,6 @@ description: "Diagnostic tool for the MCP server environment."
183170
availability:
184171
mcp: true
185172
cli: true
186-
daemon: true
187173
selection:
188174
mcp:
189175
defaultEnabled: false
@@ -203,7 +189,6 @@ description: "Manage enabled workflows at runtime."
203189
availability:
204190
mcp: true
205191
cli: false
206-
daemon: false
207192
selection:
208193
mcp:
209194
defaultEnabled: false
@@ -227,10 +212,8 @@ tools:
227212
| `description` | string | No | - | Tool description |
228213
| `availability.mcp` | boolean | No | `true` | Available via MCP |
229214
| `availability.cli` | boolean | No | `true` | Available via CLI |
230-
| `availability.daemon` | boolean | No | `true` | Available via daemon |
231215
| `predicates` | string[] | No | `[]` | Visibility predicates (all must pass) |
232216
| `routing.stateful` | boolean | No | `false` | Tool maintains state |
233-
| `routing.daemonAffinity` | enum | No | - | `'preferred'` or `'required'` |
234217
| `annotations.title` | string | No | - | Human-readable title |
235218
| `annotations.readOnlyHint` | boolean | No | - | Tool only reads data |
236219
| `annotations.destructiveHint` | boolean | No | - | Tool may modify/delete data |
@@ -247,7 +230,6 @@ tools:
247230
| `tools` | string[] | Yes | - | Tool IDs in this workflow |
248231
| `availability.mcp` | boolean | No | `true` | Available via MCP |
249232
| `availability.cli` | boolean | No | `true` | Available via CLI |
250-
| `availability.daemon` | boolean | No | `true` | Available via daemon |
251233
| `selection.mcp.defaultEnabled` | boolean | No | `false` | Enabled when no workflows configured |
252234
| `selection.mcp.autoInclude` | boolean | No | `false` | Auto-include when predicates pass |
253235
| `predicates` | string[] | No | `[]` | Visibility predicates (all must pass) |
@@ -402,11 +384,11 @@ The tool is defined once in `manifests/tools/clean.yaml` but referenced by both
402384

403385
## Daemon Routing
404386

405-
The `routing` field provides hints for daemon-based execution:
387+
Daemon routing is intentionally simple:
406388

407-
- **`stateful: true`**: Tool maintains state across calls (e.g., debug sessions)
408-
- **`daemonAffinity: 'preferred'`**: Prefer daemon execution but fall back to direct
409-
- **`daemonAffinity: 'required'`**: Must run via daemon (fails if daemon unavailable)
389+
- **`routing.stateful: true`**: CLI routes this tool through the daemon.
390+
- **`routing` omitted or `stateful: false`**: CLI runs the tool directly.
391+
- **Special-case**: dynamic `xcode-ide` bridge tools use daemon-backed routing for bridge session persistence.
410392

411393
## Validation
412394

0 commit comments

Comments
 (0)