REST API Reference
Complete reference for the MultiTerminal REST API running on http://localhost:5050. All endpoints accept and return JSON.
200 OK with an empty body for a pure acknowledgement) — there is no { "success": true } envelope. Errors are ProblemDetails (RFC 7807, application/problem+json): { type, title, status, detail, traceId }. Clients distinguish success from failure by HTTP status, never by a body flag. Full rules — including the migration/unwrap convention — live in API/CONVENTIONS.md. When adding a new endpoint example below, mirror what the controller actually returns so these docs never drift from the code.
Health & Discovery
/
Basic health check. Returns a confirmation that the API is running.
Response
"MultiTerminal API is running"
curl
curl http://localhost:5050/
/health
Health check with port information.
Response
{
"status": "healthy",
"port": 5050
}
curl
curl http://localhost:5050/health
/api/tools
Self-documenting endpoint. Lists all available API endpoints with method, path, and description.
Response
{
"baseUrl": "http://localhost:5050",
"endpoints": [
{ "method": "GET", "path": "/", "description": "Health check - API is running" },
{ "method": "POST", "path": "/api/messaging/register", "description": "Register a terminal (name, docId)" },
...
]
}
curl
curl http://localhost:5050/api/tools
Messaging
Terminal registration and inter-terminal messaging. All messaging endpoints are under /api/messaging.
/api/messaging/register
Register a terminal with the messaging system. Returns a unique terminal ID used for subsequent messaging calls.
Request Body
{
"name": "Alice",
"docId": "abc123"
}
Response
{
"terminalId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
Error Response (application/problem+json)
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"detail": "Terminal already registered",
"traceId": "00-a1b2c3d4e5f6-01"
}
curl
curl -X POST http://localhost:5050/api/messaging/register \
-H "Content-Type: application/json" \
-d '{"name":"Alice","docId":"abc123"}'
/api/messaging/send
Send a direct message to another terminal by name.
Request Body
{
"fromTerminalId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"to": "Bob",
"message": "Hello, can you help with the database migration?"
}
Response
{
"success": true,
"messageId": "a1b2c3d4",
"error": null
}
curl
curl -X POST http://localhost:5050/api/messaging/send \
-H "Content-Type: application/json" \
-d '{"fromTerminalId":"a1b2c3d4","to":"Bob","message":"Hello!"}'
/api/messaging/broadcast
Broadcast a message to all registered terminals.
Request Body
{
"fromTerminalId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"message": "Build is ready for testing!"
}
Response
{
"success": true,
"recipientCount": 3,
"error": null
}
curl
curl -X POST http://localhost:5050/api/messaging/broadcast \
-H "Content-Type: application/json" \
-d '{"fromTerminalId":"a1b2c3d4","message":"Build ready!"}'
/api/messaging/messages/{terminalId}
Get pending messages for a terminal. Messages are consumed on read (delivered once).
Response
[
{
"from": "Bob",
"to": "Alice",
"message": "Sure, I can help!",
"timestamp": "2026-03-05T10:30:00Z"
}
]
curl
curl http://localhost:5050/api/messaging/messages/a1b2c3d4
/api/messaging/terminals
List all registered terminals with their names, IDs, and last-active timestamps.
Response
[
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Alice",
"docId": "abc123",
"lastActiveAt": "2026-03-05T10:30:00Z"
}
]
curl
curl http://localhost:5050/api/messaging/terminals
/api/messaging/disconnect
Disconnect a terminal by name. Used by session-end hooks for cleanup.
Request Body
{
"name": "Alice"
}
Response
{
"name": "Alice"
}
curl
curl -X POST http://localhost:5050/api/messaging/disconnect \
-H "Content-Type: application/json" \
-d '{"name":"Alice"}'
Tasks
CRUD operations for kanban tasks. All task endpoints are under /api/tasks.
/api/tasks
List all tasks, optionally filtered by status.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
status | string | all | Filter: all, todo, in_progress, done, suggestion |
Response
[
{
"id": "c0ce8037",
"title": "Add dark mode",
"description": "Implement dark mode theme switching",
"status": "in_progress",
"assignee": "Alice",
"createdBy": "Alice",
"createdAt": "2026-03-05T08:00:00Z",
"priority": "normal",
"subStatus": "active",
"checklistJson": "[...]",
"plan": "...",
"continuationNotes": "..."
}
]
curl
curl http://localhost:5050/api/tasks?status=in_progress
/api/tasks/{taskId}
Get a specific task by ID.
Response
{
"id": "c0ce8037",
"title": "Add dark mode",
"status": "in_progress",
...
}
Error (404)
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
"title": "Not Found",
"status": 404,
"detail": "Task c0ce8037 not found",
"traceId": "00-a1b2c3d4e5f6-01"
}
curl
curl http://localhost:5050/api/tasks/c0ce8037
/api/tasks/{taskId}/detail
Get full task detail including parsed checklist with notes history, helpers, and progress summary.
Response
{
"task": { "id": "c0ce8037", "title": "Add dark mode", ... },
"checklistSummary": {
"total": 5,
"done": 2,
"coding": 1,
"testing": 1,
"pending": 1
},
"checklist": [
{
"item": "Create theme service",
"status": "done",
"notes": [
{ "text": "Implemented ThemeService with light/dark toggle", "at": "2026-03-05T09:00:00Z", "by": "Alice" }
],
"assignee": "Alice",
"cycleCount": 0
}
]
}
curl
curl http://localhost:5050/api/tasks/c0ce8037/detail
/api/tasks
Create a new kanban task.
Request Body
{
"title": "Fix login bug",
"description": "Users get 500 error on login when password contains special characters",
"createdBy": "Alice",
"status": "todo",
"priority": "high"
}
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
title | string | Yes | - | Task title |
description | string | Yes | - | Task description |
createdBy | string | Yes | - | Creator name |
status | string | No | todo | Initial status |
priority | string | No | normal | low, normal, high |
Response
{
"taskId": "a1b2c3d4",
"task": { "id": "a1b2c3d4", "title": "Fix login bug", ... }
}
curl
curl -X POST http://localhost:5050/api/tasks \
-H "Content-Type: application/json" \
-d '{"title":"Fix login bug","description":"Details","createdBy":"Alice","status":"todo","priority":"high"}'
/api/tasks/{taskId}/status
Update a task's status.
Request Body
{
"status": "in_progress",
"updatedBy": "Alice"
}
Response
{ "status": "in_progress" }
curl
curl -X PATCH http://localhost:5050/api/tasks/c0ce8037/status \
-H "Content-Type: application/json" \
-d '{"status":"in_progress","updatedBy":"Alice"}'
/api/tasks/{taskId}/assign
Assign (claim) a task to a team member.
Request Body
{ "assignee": "Alice" }
Response
{ "assignee": "Alice" }
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/assign \
-H "Content-Type: application/json" \
-d '{"assignee":"Alice"}'
/api/tasks/{taskId}/activate
Set a task as the active task for its assignee. Auto-pauses any other active tasks for the same person (enforces "one active task" rule).
Request Body
{ "updatedBy": "Alice" }
Response
{
"pausedTaskIds": ["d4e5f6a7"],
"pausedTaskTitles": ["Refactor auth module"],
"branchCandidates": [{ "branch": "task/9f9c3141", "outcome": "Adds OAuth login", "linkedTaskTitle": "Auth epic" }]
}
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/activate \
-H "Content-Type: application/json" \
-d '{"updatedBy":"Alice"}'
/api/tasks/{taskId}/helpers
Add a helper to a task. Helpers assist without being the primary assignee.
Request Body
{
"helper": "Bob",
"addedBy": "Alice"
}
Response
{ "helperCount": 2 }
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/helpers \
-H "Content-Type: application/json" \
-d '{"helper":"Bob","addedBy":"Alice"}'
/api/tasks/{taskId}/helpers/{helperName}
Remove a helper from a task.
Response
{ "helperCount": 1 }
curl
curl -X DELETE http://localhost:5050/api/tasks/c0ce8037/helpers/Bob
/api/tasks/{taskId}
Delete a task.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
deletedBy | string | Yes | Name of person deleting |
Response
200 OK (empty body)
curl
curl -X DELETE "http://localhost:5050/api/tasks/c0ce8037?deletedBy=Alice"
Checklist Workflow
Enhanced checklist management with state machine transitions. The lifecycle is: pending → coding → testing → done (cycling allowed between coding and testing).
/api/tasks/{taskId}/checklist
Replace all checklist items. Use for initial setup or bulk editing.
Request Body
{
"checklistJson": "[{\"item\":\"Setup database\",\"status\":\"pending\",\"notes\":[]},{\"item\":\"Create API\",\"status\":\"pending\",\"notes\":[]}]"
}
Response
200 OK (empty body)
curl
curl -X PATCH http://localhost:5050/api/tasks/c0ce8037/checklist \
-H "Content-Type: application/json" \
-d '{"checklistJson":"[{\"item\":\"Setup database\",\"status\":\"pending\",\"notes\":[]}]"}'
/api/tasks/{taskId}/checklist/append
Append items to the existing checklist (preserves existing items). Appended items default to status pending.
Request Body
{
"itemsJson": "[{\"item\":\"Add validation\",\"status\":\"pending\",\"notes\":[]}]"
}
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/checklist/append \
-H "Content-Type: application/json" \
-d '{"itemsJson":"[{\"item\":\"Add validation\",\"status\":\"pending\",\"notes\":[]}]"}'
/api/tasks/{taskId}/checklist/{itemIndex}/transition
Transition a checklist item to a new status. Enforces the state machine and tracks cycle count for escalation.
Request Body
{
"newStatus": "testing",
"notes": "Implemented database schema and CRUD operations",
"updatedBy": "Alice"
}
Response
{
"itemName": "Setup database",
"previousStatus": "coding",
"newStatus": "testing",
"cycleCount": 0,
"escalationTriggered": false
}
Note: If cycleCount reaches 3, escalationTriggered becomes true and an inbox notification is sent to the PM.
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/checklist/0/transition \
-H "Content-Type: application/json" \
-d '{"newStatus":"testing","notes":"Schema and CRUD done","updatedBy":"Alice"}'
/api/tasks/{taskId}/checklist/{itemIndex}/assign
Assign a checklist item to a specific agent.
Request Body
{ "assignee": "Alice" }
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/checklist/0/assign \
-H "Content-Type: application/json" \
-d '{"assignee":"Alice"}'
/api/tasks/{taskId}/plan
Set or update the implementation plan (markdown formatted).
Request Body
{
"plan": "## Phase 1: Database\n- Create migrations\n- Add indexes\n\n## Phase 2: API\n- REST endpoints\n- Validation",
"updatedBy": "Alice"
}
Response
200 OK (empty body)
curl
curl -X PATCH http://localhost:5050/api/tasks/c0ce8037/plan \
-H "Content-Type: application/json" \
-d '{"plan":"## Phase 1\n- Step 1","updatedBy":"Alice"}'
/api/tasks/{taskId}/summary
Update implementation summary and/or test results. Pass null for fields you don't want to change.
Request Body
{
"implementationSummary": "Added ThemeService with dark/light toggle and CSS variable support",
"testResults": "All 12 unit tests passing. Manual UI verification complete.",
"updatedBy": "Alice"
}
Response
200 OK (empty body)
curl
curl -X PATCH http://localhost:5050/api/tasks/c0ce8037/summary \
-H "Content-Type: application/json" \
-d '{"implementationSummary":"Added theme service","updatedBy":"Alice"}'
/api/tasks/{taskId}/continuation
Update continuation notes for session handoff. Describes where to pick up work.
Request Body
{
"continuationNotes": "Working on checklist item 3 (API validation). File: Controllers/TasksController.cs. Next: add input sanitization for title field.",
"updatedBy": "Alice"
}
Response
200 OK (empty body)
curl
curl -X PATCH http://localhost:5050/api/tasks/c0ce8037/continuation \
-H "Content-Type: application/json" \
-d '{"continuationNotes":"Pick up at item 3","updatedBy":"Alice"}'
Inbox & Notifications
Inbox notifications for task events like checklist items ready for testing, escalations, and helper requests. Endpoints are under /api/tasks/inbox.
/api/tasks/inbox/{userId}
Get inbox messages for a user.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
unreadOnly | boolean | false | Only return unread messages |
limit | integer | 50 | Max messages to return |
Response
{
"success": true,
"messages": [
{
"id": "abc12345",
"userId": "Owner",
"taskId": "c0ce8037",
"taskTitle": "Add dark mode",
"checklistItemIndex": 2,
"checklistItemName": "Add validation",
"type": "ready_for_testing",
"summary": "Alice finished 'Add validation' - ready for testing",
"createdAt": "2026-03-05T10:30:00Z",
"createdBy": "Alice",
"readAt": null,
"replyText": null,
"repliedAt": null
}
],
"unreadCount": 5,
"totalCount": 1,
"error": null
}
Message types: ready_for_testing, escalation, task_complete, helper_request
curl
curl "http://localhost:5050/api/tasks/inbox/Owner?unreadOnly=true"
/api/tasks/inbox/{messageId}/read
Mark a single inbox message as read.
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/tasks/inbox/abc12345/read
/api/tasks/inbox/{userId}/read-all
Mark all inbox messages as read for a user.
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/tasks/inbox/Owner/read-all
/api/tasks/inbox/{messageId}/reply
Reply to an inbox message. Auto-marks the message as read.
Request Body
{ "replyText": "Looks good, marking as done" }
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/tasks/inbox/abc12345/reply \
-H "Content-Type: application/json" \
-d '{"replyText":"Looks good, marking as done"}'
/api/tasks/inbox/{userId}/unread-count
Get unread inbox message count for a user.
Response
{ "count": 5 }
curl
curl http://localhost:5050/api/tasks/inbox/Owner/unread-count
Attachments
Image attachments for tasks and checklist items. Stored as binary blobs in SQLite.
/api/tasks/{taskId}/attachments
Get attachment metadata for a task, optionally filtered by checklist item index.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
itemIndex | integer | - | Filter by checklist item index |
Response
[
{
"id": "att-12345",
"taskId": "c0ce8037",
"checklistItemIndex": 0,
"fileName": "screenshot.png",
"mimeType": "image/png",
"addedBy": "Alice",
"addedAt": "2026-03-05T10:00:00Z"
}
]
curl
curl "http://localhost:5050/api/tasks/c0ce8037/attachments?itemIndex=0"
/api/tasks/attachments/{attachmentId}/image
Get raw binary image data for an attachment. Returns the file with appropriate MIME type.
Response
Raw binary image data with Content-Type header (e.g., image/png).
curl
curl http://localhost:5050/api/tasks/attachments/att-12345/image -o screenshot.png
/api/tasks/attachments/{attachmentId}/base64
Get attachment image as base64-encoded string with metadata. Useful for agents that need to analyze images.
Response
{
"base64": "iVBORw0KGgoAAAANSUhEUgAA...",
"mimeType": "image/png",
"fileName": "screenshot.png"
}
curl
curl http://localhost:5050/api/tasks/attachments/att-12345/base64
/api/tasks/{taskId}/attachments
Add a base64-encoded image attachment to a task or checklist item.
Request Body
{
"checklistItemIndex": 0,
"fileName": "bug-screenshot.png",
"mimeType": "image/png",
"base64Data": "iVBORw0KGgoAAAANSUhEUgAA...",
"addedBy": "Alice"
}
Response
{ "attachmentId": "att-67890" }
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/attachments \
-H "Content-Type: application/json" \
-d '{"checklistItemIndex":0,"fileName":"bug.png","mimeType":"image/png","base64Data":"...","addedBy":"Alice"}'
/api/tasks/attachments/{attachmentId}
Delete an attachment by ID.
Response
200 OK (empty body)
curl
curl -X DELETE http://localhost:5050/api/tasks/attachments/att-12345
Office Panel
Agent presence tracking for the Office Panel UI. Triggers walk-in/exit animations. Endpoints are under /api/office.
/api/office/agents
Notify that an agent has been spawned. Triggers walk-in animation in the Office Panel.
Request Body
{
"name": "Alice",
"spawnedBy": "Owner"
}
Response
{ "agentName": "Alice" }
curl
curl -X POST http://localhost:5050/api/office/agents \
-H "Content-Type: application/json" \
-d '{"name":"Alice","spawnedBy":"Owner"}'
/api/office/agents/{name}
Notify that an agent has departed. Triggers exit animation in the Office Panel.
Response
{ "agentName": "Alice" }
curl
curl -X DELETE http://localhost:5050/api/office/agents/Alice
/api/office/agents
List all currently active office agents.
Response
[
{ "name": "Alice", "spawnedBy": "Owner", "spawnedAt": "2026-03-05T10:00:00Z" },
{ "name": "Bob", "spawnedBy": "Alice", "spawnedAt": "2026-03-05T10:05:00Z" }
]
curl
curl http://localhost:5050/api/office/agents
/api/office/agents/cleanup
Remove stale/ghost office agents older than a specified number of minutes.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
olderThanMinutes | integer | 30 | Remove agents older than this |
Response
{
"removedCount": 2,
"removedAgents": ["Ghost1", "Ghost2"]
}
curl
curl -X DELETE "http://localhost:5050/api/office/agents/cleanup?olderThanMinutes=60"
/api/office/agents/clear-all
Force-clear all office agents. Nuclear option for ghost cleanup.
Response
{
"removedCount": 5,
"removedAgents": ["Ghost1", "Ghost2", "Ghost3", "Ghost4", "Ghost5"]
}
curl
curl -X DELETE http://localhost:5050/api/office/agents/clear-all
Agent Spawning
/api/spawn/agent
Spawn a headless AgentProcess with piped stdin/stdout. The agent runs Claude Code in stream-json mode and its conversation is displayed in the Agent Panel.
Request Body
{
"agentName": "Agent Alice",
"workingDir": "H:\\DevLaptop\\ClarionPowerShell\\MultiTerminal",
"initialPrompt": "Implement the dark mode feature",
"mcpConfigPath": "C:\\Users\\<username>\\.claude\\mcp-config.json",
"spawnerName": "Owner",
"taskDescription": "Add dark mode toggle to the settings panel",
"subagentType": "coder"
}
| Field | Type | Required | Description |
|---|---|---|---|
agentName | string | Yes | Name for the spawned agent |
workingDir | string | No | Working directory for the agent |
initialPrompt | string | No | Initial prompt to send to the agent |
mcpConfigPath | string | No | Path to MCP configuration |
spawnerName | string | No | Who is spawning this agent |
taskDescription | string | No | Description of the task for the agent |
subagentType | string | No | Type of subagent (e.g., coder, reviewer) |
Response
{
"agentName": "Agent Alice",
"processId": 12345,
"sessionId": "a1b2c3d4"
}
curl
curl -X POST http://localhost:5050/api/spawn/agent \
-H "Content-Type: application/json" \
-d '{"agentName":"Agent Alice","workingDir":"H:\\DevLaptop\\MyProject","initialPrompt":"Fix the bug","spawnerName":"Owner"}'
Agent Panels
/api/agent-panels/close
Close an agent panel by transcript path. Called by the SubagentStop hook when a subagent finishes.
Request Body
{
"transcriptPath": "C:\\Users\\<username>\\.claude\\teams\\my-team\\Agent Alice\\transcript.jsonl"
}
Response
{
"transcriptPath": "C:\\Users\\John\\.claude\\projects\\...\\transcript.jsonl"
}
curl
curl -X POST http://localhost:5050/api/agent-panels/close \
-H "Content-Type: application/json" \
-d '{"transcriptPath":"C:\\Users\\<username>\\.claude\\teams\\my-team\\Agent Alice\\transcript.jsonl"}'
Knowledge Base
Institutional memory system for decisions, patterns, gotchas, and code digests. Endpoints are under /api/knowledge.
/api/knowledge/search
Search knowledge entries by text query, category, project, and tags. Uses FTS5 full-text search.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
query | string | - | Search text |
category | string | - | decision, pattern, gotcha, anti_pattern, debug_insight, preference |
projectId | string | - | Filter by project |
tags | string | - | Comma-separated tags |
limit | integer | 20 | Max results (max 500) |
Response
{
"results": [
{
"id": 1,
"projectId": "proj-123",
"category": "gotcha",
"title": "PowerShell single-quote injection",
"content": "Always escape single quotes with Replace(\"'\", \"''\") before interpolating into PowerShell commands",
"sourceType": "session",
"tags": "security,powershell",
"confidence": "confirmed",
"createdAt": "2026-02-28T10:00:00Z"
}
],
"totalCount": 1
}
curl
curl "http://localhost:5050/api/knowledge/search?query=injection&category=gotcha&limit=10"
/api/knowledge
Create a new knowledge entry.
Request Body
{
"title": "Always use parameterized queries",
"content": "Never interpolate user input into SQL strings. Use SQLiteParameter for all values.",
"category": "pattern",
"projectId": "proj-123",
"sourceType": "review",
"tags": "security,sql,database",
"confidence": "confirmed"
}
Response
{ "id": 42 }
curl
curl -X POST http://localhost:5050/api/knowledge \
-H "Content-Type: application/json" \
-d '{"title":"Use parameterized queries","content":"Never interpolate...","category":"pattern","confidence":"confirmed"}'
/api/knowledge/{id}
Update an existing knowledge entry. Accepts a dictionary of field names to values.
Request Body
{
"confidence": "confirmed",
"tags": "security,sql,database,critical"
}
Accepted fields: category, title, content, tags, confidence, superseded_by
Response
200 OK (empty body)
curl
curl -X PUT http://localhost:5050/api/knowledge/42 \
-H "Content-Type: application/json" \
-d '{"confidence":"confirmed","tags":"security,sql"}'
/api/knowledge/digest
Get the code digest (pre-analyzed summary) for a specific file.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
filePath | string | Yes | Absolute path to the source file |
projectId | string | No | Project ID |
Response
{
"id": 1,
"projectId": "proj-123",
"filePath": "H:\\DevLaptop\\...\\MessageBroker.cs",
"fileHash": "abc123def456...",
"purpose": "Central hub routing all messages, caching tasks/terminals/profiles",
"keyClasses": "[\"MessageBroker\"]",
"keyMethods": "[\"SendMessage\",\"RegisterTerminal\",\"CreateTask\"]",
"patterns": "ConcurrentDictionary caching, event-driven UI updates",
"gotchas": "Thread-safety required for all dictionary access",
"dependencies": "[\"TaskDatabase\",\"ActivityService\"]",
"lineCount": 4254,
"digestModel": "haiku"
}
curl
curl "http://localhost:5050/api/knowledge/digest?filePath=H%3A%5CDevLaptop%5C...%5CMessageBroker.cs"
/api/knowledge/digest
Save or update a code digest for a file.
Request Body
{
"projectId": "proj-123",
"filePath": "H:\\DevLaptop\\...\\TaskDatabase.cs",
"fileHash": "sha256-hash-here",
"purpose": "SQLite persistence layer for tasks, profiles, and activity",
"keyClasses": "[\"TaskDatabase\"]",
"keyMethods": "[\"GetTask\",\"SaveTask\",\"LoadTaskHelpers\"]",
"patterns": "SQLite with manual migrations, connection pooling",
"gotchas": "Must call EnsureSchema() before any operations",
"dependencies": "[\"System.Data.SQLite\"]",
"lineCount": 2694,
"digestModel": "haiku"
}
Response
{ "id": 5 }
curl
curl -X POST http://localhost:5050/api/knowledge/digest \
-H "Content-Type: application/json" \
-d '{"projectId":"proj-123","filePath":"...","fileHash":"abc123","purpose":"..."}'
/api/knowledge/digest/stale
Check which digests are stale by comparing file hashes. Supply a dictionary of file paths to current hashes.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
projectId | string | No | Filter by project |
Request Body
{
"fileHashes": {
"H:\\DevLaptop\\...\\MessageBroker.cs": "currenthash123",
"H:\\DevLaptop\\...\\TaskDatabase.cs": "currenthash456"
}
}
Response
{
"stale": [
{
"filePath": "H:\\DevLaptop\\...\\MessageBroker.cs",
"storedHash": "oldhash789",
"currentHash": "currenthash123"
}
],
"count": 1
}
curl
curl -X POST "http://localhost:5050/api/knowledge/digest/stale?projectId=proj-123" \
-H "Content-Type: application/json" \
-d '{"fileHashes":{"path1":"hash1","path2":"hash2"}}'
Session Lineage
Import, query, and search Claude Code session transcripts. Supports lineage chaining for tracking agent cycling. Endpoints are under /api/session-lineage.
/api/session-lineage/import
Import a Claude Code session JSONL file and link it to a kanban task. Extracts messages and indexes them with FTS5 for full-text search.
Request Body
{
"sessionFilePath": "C:\\Users\\<username>\\.claude\\projects\\...\\sessions\\abc123.jsonl",
"taskId": "c0ce8037",
"agentName": "Alice",
"parentSessionId": "prev-session-id",
"sessionType": "coding"
}
| Field | Type | Required | Description |
|---|---|---|---|
sessionFilePath | string | Yes | Path to JSONL file (must be within ~/.claude/projects) |
taskId | string | Yes | Kanban task ID |
agentName | string | Yes | Agent who ran the session |
parentSessionId | string | No | Parent session for lineage chaining |
sessionType | string | No | Semantic label: coding, review, testing |
Response
{
"sessionId": "def456",
"messageCount": 127
}
curl
curl -X POST http://localhost:5050/api/session-lineage/import \
-H "Content-Type: application/json" \
-d '{"sessionFilePath":"C:\\Users\\<username>\\.claude\\...\\abc123.jsonl","taskId":"c0ce8037","agentName":"Alice"}'
/api/session-lineage/task/{taskId}/sessions
Get all session lineage records for a task, newest first.
Response
[
{
"sessionId": "def456",
"parentSessionId": "abc123",
"taskId": "c0ce8037",
"agentName": "Alice",
"sessionType": "coding",
"summary": "Implemented database migrations and CRUD endpoints",
"startedAt": "2026-03-05T08:00:00Z",
"endedAt": "2026-03-05T09:30:00Z"
}
]
curl
curl http://localhost:5050/api/session-lineage/task/c0ce8037/sessions
/api/session-lineage/{sessionId}/chain
Get the full lineage chain for a session, ordered root to leaf. Walks parent_session_id links.
Response
[
{ "sessionId": "abc123", "agentName": "Alice", "sessionType": "coding", ... },
{ "sessionId": "def456", "agentName": "Alice", "sessionType": "review", "parentSessionId": "abc123", ... }
]
curl
curl http://localhost:5050/api/session-lineage/def456/chain
/api/session-lineage/sync
Incrementally sync sessions from a Claude project folder. Skips already-imported sessions.
Request Body
{
"claudeProjectPath": "C:\\Users\\<username>\\.claude\\projects\\H--DevLaptop-...",
"agentName": "Alice",
"taskId": "c0ce8037"
}
Response
{
"imported": 3,
"skipped": 12,
"failed": 0,
"total": 15
}
curl
curl -X POST http://localhost:5050/api/session-lineage/sync \
-H "Content-Type: application/json" \
-d '{"claudeProjectPath":"C:\\Users\\<username>\\.claude\\projects\\...","agentName":"Alice"}'
/api/session-lineage/latest
Get the most recent session for a project. Optionally filter by agent name to get a specific agent's last session. If no cached summary exists, returns the last 10 assistant messages for lazy summary generation.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
projectPath | string | Yes | Filesystem path to the project |
agentName | string | No | Filter by agent name (e.g. "Alice"). Returns the most recent session for this specific agent. |
Response
{
"session": {
"sessionId": "def456",
"taskId": "c0ce8037",
"agentName": "Alice",
"sessionType": "coding",
"startedAt": "2026-03-05T08:00:00Z"
},
"summary": "Implemented database migrations and CRUD endpoints for the knowledge base",
"recentMessages": null
}
curl
# Latest session across all agents
curl "http://localhost:5050/api/session-lineage/latest?projectPath=H%3A%5CDevLaptop%5C..."
# Latest session for a specific agent
curl "http://localhost:5050/api/session-lineage/latest?projectPath=H%3A%5CDevLaptop%5C...&agentName=Alice"
/api/session-lineage/{sessionId}/summary
Save a generated summary for a session.
Request Body
{ "summary": "Implemented the knowledge base with FTS5 search, CRUD endpoints, and code digest system" }
Response
200 OK (empty body)
curl
curl -X PUT http://localhost:5050/api/session-lineage/def456/summary \
-H "Content-Type: application/json" \
-d '{"summary":"Implemented knowledge base..."}'
/api/session-lineage/search
Full-text search across session messages. Uses FTS5 when available, falls back to LIKE.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
taskId | string | No* | Filter by task |
query | string | No* | Search text |
role | string | No | user or assistant |
agentName | string | No | Filter by agent |
limit | integer | No | Max results (default 50, max 1000) |
* At least one of taskId or query is required.
Response
{
"results": [
{
"sessionId": "def456",
"messageIndex": 42,
"role": "assistant",
"content": "I implemented the FTS5 search indexing...",
"toolName": null,
"timestamp": "2026-03-05T09:15:00Z"
}
],
"totalCount": 3
}
curl
curl "http://localhost:5050/api/session-lineage/search?taskId=c0ce8037&query=FTS5&role=assistant&limit=20"
Projects
Project context endpoints for agent orientation. Endpoints are under /api/projects.
/api/projects/{projectId}/context
Get the full project context: project record joined with all association tables (agents, MCP servers, specialist agents, paths, prompts, skills) in a single response.
Response
{
"project": {
"id": "proj-123",
"name": "MultiTerminal",
"description": "Multi-agent coordination system",
"path": "H:\\DevLaptop\\ClarionPowerShell\\MultiTerminal",
"deployPath": "H:\\DevLaptop\\ClarionPowerShell\\Deploy",
"buildCommand": "dotnet build",
"projectType": "WinForms",
"gitRepoUrl": "...",
"gitDefaultBranch": "main",
"isPinned": true,
"teamLead": "Owner"
},
"agents": [
{ "agentName": "Alice", "role": "backend", "preferredModel": "sonnet" }
],
"mcpServers": [
{ "serverName": "multiterminal-mcp", "isEnabled": true }
],
"specialistAgents": [
{ "agentType": "verifier", "isEnabled": true, "customPrompt": null }
],
"paths": [
{ "pathType": "source", "pathValue": "H:\\DevLaptop\\...", "description": "Main source" }
],
"prompts": [
{ "promptType": "system", "promptText": "...", "displayOrder": 0 }
],
"skills": [
{ "skillName": "kanban-task", "isEnabled": true }
]
}
curl
curl http://localhost:5050/api/projects/proj-123/context
/api/projects/contexts
List all project contexts with their full association data.
Response
{
"count": 3,
"contexts": [ ... ]
}
curl
curl http://localhost:5050/api/projects/contexts
Team
/api/team/roster
Get the team roster for a project, merged with profile data. Returns each agent's name, preferred model, instructions, role, and skills.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
projectPath | string | Yes | Absolute path to the project directory |
Response
{
"projectName": "MultiTerminal",
"projectPath": "H:\\DevLaptop\\ClarionPowerShell\\MultiTerminal",
"agents": [
{
"name": "Alice",
"hasProfile": true,
"preferredModel": "sonnet",
"agentInstructions": "Backend systems architect specializing in C# and SQLite",
"role": "backend",
"skills": ["database", "api-design", "c-sharp"],
"isOnline": true,
"isTeamLead": false
}
]
}
curl
curl "http://localhost:5050/api/team/roster?projectPath=H%3A%5CDevLaptop%5CClarionPowerShell%5CMultiTerminal"
Debug
Debug logging for system diagnostics. Endpoints are under /api/debug.
/api/debug/logs
Get debug log entries with filtering and pagination. Ordered by most recent first.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
count | integer | 50 | Number of entries to return |
offset | integer | 0 | Skip entries for pagination |
source | string | - | Filter by component (e.g., InboxMonitor, MessageBroker) |
level | string | - | Trace, Info, Warning, Error |
search | string | - | Text search within messages (case-insensitive) |
Response
{
"total": 1234,
"offset": 0,
"count": 2,
"entries": [
{
"timestamp": "10:30:45.123",
"source": "InboxMonitor",
"level": "Info",
"message": "Nudge sent to terminal Alice for task c0ce8037"
},
{
"timestamp": "10:30:44.987",
"source": "MessageBroker",
"level": "Trace",
"message": "Message delivered from Bob to Alice"
}
]
}
curl
curl "http://localhost:5050/api/debug/logs?count=20&source=InboxMonitor&level=Info"
/api/debug/logs
Clear all debug log entries.
Response
{ "message": "Debug logs cleared", "previousCount": 1234 }
curl
curl -X DELETE http://localhost:5050/api/debug/logs
/api/debug/pause
Pause debug logging. New entries are silently discarded until resumed.
Response
{ "isPaused": true }
curl
curl -X POST http://localhost:5050/api/debug/pause
/api/debug/resume
Resume debug logging.
Response
{ "isPaused": false }
curl
curl -X POST http://localhost:5050/api/debug/resume
/api/debug/status
Get debug log status.
Response
{
"count": 1234,
"isPaused": false,
"maxCapacity": 10000
}
curl
curl http://localhost:5050/api/debug/status
Code Search
Fast code and file search powered by ripgrep (bundled as tools/rg.exe). Endpoints are under /api/search.
/api/search/content
Search file contents using ripgrep regex. Returns matches with file paths, line numbers, and search statistics.
Request
{
"pattern": "class.*Service",
"path": "H:\\DevLaptop\\ClarionPowerShell\\MultiTerminal",
"caseInsensitive": false,
"glob": "*.cs",
"fileType": null,
"maxCount": 10,
"context": 2,
"before": 0,
"after": 0,
"multiline": false,
"fixedStrings": false,
"filesWithMatches": false,
"count": false
}
Response
{
"matchCount": 15,
"matches": [
{
"filePath": "Services/RipgrepService.cs",
"lineNumber": 10,
"text": " public class RipgrepService",
"line": "Services/RipgrepService.cs:10: public class RipgrepService"
}
],
"stats": {
"matchedLines": 15,
"matches": 15,
"searchedFiles": 80,
"elapsedMs": 12.3
}
}
curl
curl -X POST http://localhost:5050/api/search/content \
-H "Content-Type: application/json" \
-d '{"pattern":"class.*Service","path":"H:\\\\project","glob":"*.cs"}'
/api/search/files
Find files matching a glob pattern or file type filter.
Request
{
"path": "H:\\DevLaptop\\ClarionPowerShell\\MultiTerminal",
"glob": "*.cs",
"fileType": null
}
Response
{
"fileCount": 80,
"files": [
"H:\\DevLaptop\\ClarionPowerShell\\MultiTerminal\\MainForm.cs",
"..."
]
}
curl
curl -X POST http://localhost:5050/api/search/files \
-H "Content-Type: application/json" \
-d '{"path":"H:\\\\project","glob":"*.cs"}'
/api/search/status
Check if ripgrep is available.
Response
{ "available": true }
curl
curl http://localhost:5050/api/search/status
Task Relationships
Blocking and dependency relationships between tasks. Automatically creates inverse relationships. Endpoints are under /api/tasks/{taskId}/relationships.
/api/tasks/{taskId}/relationships
Add a relationship between two tasks. Automatically creates the inverse relationship (e.g., if A blocks B, then B is blocked_by A).
Request Body
{
"targetTaskId": "d4e5f6a7",
"type": "blocks",
"createdBy": "Alice"
}
| Field | Type | Required | Description |
|---|---|---|---|
targetTaskId | string | Yes | Target task ID |
type | string | Yes | blocks, depends_on, related_to |
createdBy | string | Yes | Who created the relationship |
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/relationships \
-H "Content-Type: application/json" \
-d '{"targetTaskId":"d4e5f6a7","type":"blocks","createdBy":"Alice"}'
/api/tasks/{taskId}/relationships
Get all relationships for a task.
Response
{
"relationships": [
{
"sourceTaskId": "c0ce8037",
"targetTaskId": "d4e5f6a7",
"type": "blocks",
"createdBy": "Alice"
}
]
}
curl
curl http://localhost:5050/api/tasks/c0ce8037/relationships
/api/tasks/{taskId}/relationships/{relatedTaskId}
Remove a relationship between two tasks (removes both directions).
Response
200 OK (empty body)
curl
curl -X DELETE http://localhost:5050/api/tasks/c0ce8037/relationships/d4e5f6a7
Task File Links
Link files to tasks for code review context and agent orientation. Supports optional line ranges. Endpoints are under /api/tasks/{taskId}/files.
/api/tasks/{taskId}/files
Link a file to a task.
Request Body
{
"filePath": "H:\\DevLaptop\\ClarionPowerShell\\MultiTerminal\\Services\\TaskDatabase.cs",
"description": "Core persistence layer being modified",
"lineStart": 100,
"lineEnd": 250,
"addedBy": "Alice"
}
Response
{ "fileCount": 3 }
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/files \
-H "Content-Type: application/json" \
-d '{"filePath":"H:\\\\path\\\\to\\\\file.cs","description":"Relevant file","addedBy":"Alice"}'
/api/tasks/{taskId}/files
Get all files linked to a task.
Response
{
"files": [
{
"filePath": "H:\\DevLaptop\\...\\TaskDatabase.cs",
"description": "Core persistence layer",
"lineStart": 100,
"lineEnd": 250,
"addedBy": "Alice",
"addedAt": "2026-03-10T10:00:00Z"
}
]
}
curl
curl http://localhost:5050/api/tasks/c0ce8037/files
/api/tasks/{taskId}/files/unlink
Unlink a file from a task.
Request Body
{ "filePath": "H:\\DevLaptop\\...\\TaskDatabase.cs" }
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/files/unlink \
-H "Content-Type: application/json" \
-d '{"filePath":"H:\\\\path\\\\to\\\\file.cs"}'
/api/tasks/{taskId}/code-review
Get code review diff data for all linked files in a task. Returns file list with git diff output for each.
Response
{
"taskId": "c0ce8037",
"fileCount": 2,
"files": [
{
"filePath": "H:\\DevLaptop\\...\\TaskDatabase.cs",
"description": "Core persistence layer",
"hasDiff": true,
"diff": "--- a/Services/TaskDatabase.cs\n+++ b/Services/TaskDatabase.cs\n..."
}
]
}
curl
curl http://localhost:5050/api/tasks/c0ce8037/code-review
Task Reports
Persisted agent reports (HTML/markdown) linked to kanban tasks. Generated by specialist agents (verifier, code-reviewer, security-auditor). Endpoints are under /api/tasks/{taskId}/reports.
/api/tasks/{taskId}/reports
List reports for a task (metadata only, no content).
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
agentName | string | - | Filter by agent name |
limit | integer | 50 | Max reports to return |
Response
{
"taskId": "c0ce8037",
"count": 2,
"reports": [
{
"id": "rpt12345",
"taskId": "c0ce8037",
"agentName": "verifier",
"reportType": "html",
"verdict": "PASS",
"score": 95,
"createdAt": "2026-03-10T10:00:00Z",
"createdBy": "Alice"
}
]
}
curl
curl "http://localhost:5050/api/tasks/c0ce8037/reports?agentName=verifier"
/api/tasks/{taskId}/reports/{reportId}
Get full report content by ID.
Response
{
"id": "rpt12345",
"task_id": "c0ce8037",
"agent_name": "verifier",
"report_type": "html",
"report_content": "<h1>Verification Report</h1>...",
"verdict": "PASS",
"score": 95
}
curl
curl http://localhost:5050/api/tasks/c0ce8037/reports/rpt12345
/api/tasks/{taskId}/reports
Save a new agent report.
Request Body
{
"agentName": "verifier",
"reportContent": "<h1>Verification Report</h1><p>All checks passed.</p>",
"reportType": "html",
"verdict": "PASS",
"score": 95,
"invocationId": "inv-abc123",
"createdBy": "Alice"
}
Response
{ "reportId": "rpt12345" }
curl
curl -X POST http://localhost:5050/api/tasks/c0ce8037/reports \
-H "Content-Type: application/json" \
-d '{"agentName":"verifier","reportContent":"...","verdict":"PASS","score":95,"createdBy":"Alice"}'
Agent Stats
Aggregated agent performance statistics and invocation tracking. Endpoints are under /api/agents.
/api/agents/stats
Get aggregated performance stats per agent (invocation counts, average scores, verdicts).
Response
[
{
"agentName": "verifier",
"totalInvocations": 15,
"avgScore": 87,
"passCount": 12,
"failCount": 3
}
]
curl
curl http://localhost:5050/api/agents/stats
/api/agents/invocations
List recent agent invocations with optional filters.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
agentName | string | - | Filter by agent name |
taskId | string | - | Filter by task |
limit | integer | 50 | Max results (max 500) |
Response
[
{
"id": "inv-abc123",
"agentName": "verifier",
"taskId": "c0ce8037",
"invokedBy": "Alice",
"modelUsed": "opus",
"verdict": "PASS",
"score": 95,
"findingsCount": 0,
"durationMs": 45000,
"invokedAt": "2026-03-10T10:00:00Z",
"completedAt": "2026-03-10T10:00:45Z"
}
]
curl
curl "http://localhost:5050/api/agents/invocations?agentName=verifier&limit=20"
/api/agents/invocations
Record a new agent invocation.
Request Body
{
"agentName": "verifier",
"taskId": "c0ce8037",
"invokedBy": "Alice",
"modelUsed": "opus",
"verdict": "PASS",
"score": 95,
"findingsCount": 0,
"durationMs": 45000,
"reportSummary": "All checks passed"
}
Response
{ "invocationId": "inv-abc123" }
curl
curl -X POST http://localhost:5050/api/agents/invocations \
-H "Content-Type: application/json" \
-d '{"agentName":"verifier","taskId":"c0ce8037","invokedBy":"Alice","verdict":"PASS","score":95}'
Notifications
Runtime notifications from Claude Code hooks. Stores events in the DB and forwards them to the in-process Multi-Connect gateway, which delivers Web Push (VAPID) notifications to your phone. Rate limited to 100/minute. Endpoints are under /api/notifications.
/api/notifications
Receive a Claude Code runtime notification. Stores in the DB, fires a broker event, and forwards to the in-process Multi-Connect gateway for Web Push delivery to the phone.
Request Body
{
"notification_type": "task_complete",
"title": "Task completed",
"message": "Alice finished 'Add dark mode'",
"session_id": "abc123",
"agent_name": "Alice",
"cwd": "H:\\DevLaptop\\ClarionPowerShell\\MultiTerminal"
}
Response
{ "id": "ntf12345" }
curl
curl -X POST http://localhost:5050/api/notifications \
-H "Content-Type: application/json" \
-d '{"notification_type":"task_complete","title":"Task completed","message":"Alice finished task"}'
/api/notifications
Query notification history.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Max notifications (max 500) |
unreadOnly | boolean | false | Only return unread notifications |
Response
[
{
"id": "ntf12345",
"notificationType": "task_complete",
"title": "Task completed",
"message": "Alice finished 'Add dark mode'",
"agentName": "Alice",
"readAt": null,
"createdAt": "2026-03-10T10:00:00Z"
}
]
curl
curl "http://localhost:5050/api/notifications?unreadOnly=true&limit=20"
/api/notifications/{id}/read
Mark a notification as read.
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/notifications/ntf12345/read
/api/notifications/unread-count
Get count of unread notifications.
Response
{ "count": 5 }
curl
curl http://localhost:5050/api/notifications/unread-count
Owner Profile
Owner identity and git configuration. Used by agents for git operations. Endpoints are under /api/owner-profile.
/api/owner-profile
Get the owner profile (git identity, GitHub config).
Response
{
"configured": true,
"fullName": "Jane Smith",
"email": "user@example.com",
"gitHubUsername": "jhickey",
"hasGitHubToken": true,
"createdAt": "2026-02-01T10:00:00Z",
"updatedAt": "2026-03-01T10:00:00Z"
}
curl
curl http://localhost:5050/api/owner-profile
Removed: GET /api/owner-profile/github-token returned the stored PAT
({ "token": "ghp_xxxx..." }) for agent use during git operations. Task ea7d9cf9
deleted it, together with GET /api/source-accounts/{id}/token and the token
field of GET /api/projects/{projectId}/source-account. None of the three ever had a
consumer, and each fetch wrote the credential into an agent's session transcript on disk. Use
hasGitHubToken above to test for presence; to do authenticated work, have the service
perform the operation and return its result rather than handing out the credential.
Companions
Status of configured companion processes (external services managed by MultiTerminal). Endpoints are under /api/companions.
/api/companions/status
Get the status of all configured companion processes.
Response
[
{
"name": "MCP Gateway",
"status": "running",
"pid": 12345
}
]
curl
curl http://localhost:5050/api/companions/status
MCP Gateway
Query MCP Gateway server status and discovered tools. Reads from the gateway's SQLite database. Endpoints are under /api/gateway.
/api/gateway/servers
List all gateway backend servers with live connection status and tool counts.
Response
{
"servers": [
{
"name": "sqlite",
"connected": true,
"enabled": true,
"toolCount": 12
}
],
"summary": {
"total": 5,
"connected": 4,
"enabled": 5,
"totalTools": 45
}
}
curl
curl http://localhost:5050/api/gateway/servers
/api/gateway/tools
List all discovered tools across all connected gateway backends. Filter by server or profile.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
server | string | - | Filter by server name |
profile | string | - | Filter by gateway profile |
Response
{
"profile": "(all)",
"totalTools": 45,
"serverBreakdown": [
{ "server": "sqlite", "toolCount": 12 }
],
"tools": [
{
"serverName": "sqlite",
"toolName": "query",
"description": "Execute a SQL query"
}
]
}
curl
curl "http://localhost:5050/api/gateway/tools?server=sqlite"
/api/gateway/tools/{server__toolname}
Get a specific tool's full schema by namespaced name (format: server__toolname).
Response
{
"serverName": "sqlite",
"toolName": "query",
"description": "Execute a SQL query",
"inputSchema": { ... }
}
curl
curl http://localhost:5050/api/gateway/tools/sqlite__query
Browser Tabs
Per-terminal tabbed browser (WebView2) management. All endpoints use POST with JSON bodies. Endpoints are under /api/browser-tabs.
/api/browser-tabs/open
Open a new browser tab in a terminal's HUD area.
Request Body
{
"terminalId": "Alice",
"title": "Dashboard",
"url": "file:///H:/docs/index.html",
"content": null
}
Response
{ "tabId": "tab-abc123" }
curl
curl -X POST http://localhost:5050/api/browser-tabs/open \
-H "Content-Type: application/json" \
-d '{"terminalId":"Alice","title":"Dashboard","content":"<h1>Hello</h1>"}'
/api/browser-tabs/update
Update an existing browser tab's content, URL, or title.
Request Body
{
"terminalId": "Alice",
"tabId": "tab-abc123",
"title": "Updated Dashboard",
"content": "<h1>Updated</h1>"
}
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/browser-tabs/update \
-H "Content-Type: application/json" \
-d '{"terminalId":"Alice","tabId":"tab-abc123","content":"<h1>Updated</h1>"}'
/api/browser-tabs/close
Close a browser tab.
Request Body
{
"terminalId": "Alice",
"tabId": "tab-abc123"
}
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/browser-tabs/close \
-H "Content-Type: application/json" \
-d '{"terminalId":"Alice","tabId":"tab-abc123"}'
/api/browser-tabs/execute-script
Execute JavaScript in a browser tab and return the result.
Request Body
{
"terminalId": "Alice",
"tabId": "tab-abc123",
"script": "document.getElementById('status').textContent"
}
Response
{ "result": "Ready" }
curl
curl -X POST http://localhost:5050/api/browser-tabs/execute-script \
-H "Content-Type: application/json" \
-d '{"terminalId":"Alice","tabId":"tab-abc123","script":"document.title"}'
/api/browser-tabs/console-logs
Get console log messages from a browser tab.
Request Body
{
"terminalId": "Alice",
"tabId": "tab-abc123",
"limit": 10
}
Response
{ "logs": "[{\"level\":\"log\",\"message\":\"Hello\",\"timestamp\":\"...\"}]" }
curl
curl -X POST http://localhost:5050/api/browser-tabs/console-logs \
-H "Content-Type: application/json" \
-d '{"terminalId":"Alice","tabId":"tab-abc123","limit":10}'
/api/browser-tabs/element-content
Read the content of a DOM element by CSS selector.
Request Body
{
"terminalId": "Alice",
"tabId": "tab-abc123",
"selector": "#results",
"property": "innerHTML"
}
Response
{ "content": "<p>Results here</p>" }
curl
curl -X POST http://localhost:5050/api/browser-tabs/element-content \
-H "Content-Type: application/json" \
-d '{"terminalId":"Alice","tabId":"tab-abc123","selector":"h1","property":"textContent"}'
/api/browser-tabs/capture-screenshot
Capture a PNG screenshot of a browser tab's content.
Request Body
{
"terminalId": "Alice",
"tabId": "tab-abc123"
}
Response
{ "imageBase64": "iVBORw0KGgoAAAANSUhEUgAA..." }
curl
curl -X POST http://localhost:5050/api/browser-tabs/capture-screenshot \
-H "Content-Type: application/json" \
-d '{"terminalId":"Alice","tabId":"tab-abc123"}'
/api/browser-tabs/post-message
Send a JSON message to a browser tab's page (received via window.chrome.webview.addEventListener).
Request Body
{
"terminalId": "Alice",
"tabId": "tab-abc123",
"data": "{\"type\":\"update\",\"cpu\":47}"
}
Response
200 OK (empty body)
curl
curl -X POST http://localhost:5050/api/browser-tabs/post-message \
-H "Content-Type: application/json" \
-d '{"terminalId":"Alice","tabId":"tab-abc123","data":"{\"type\":\"update\"}"}'
/api/browser-tabs/get-messages
Get messages sent from a browser tab's page via window.chrome.webview.postMessage().
Request Body
{
"terminalId": "Alice",
"tabId": "tab-abc123",
"limit": 20
}
Response
{ "messages": "[{\"data\":{\"type\":\"click\"},\"timestamp\":\"...\"}]" }
curl
curl -X POST http://localhost:5050/api/browser-tabs/get-messages \
-H "Content-Type: application/json" \
-d '{"terminalId":"Alice","tabId":"tab-abc123"}'
Terminal Streaming
WebSocket endpoint for real-time terminal I/O streaming. Binary frames carry raw VT/ANSI escape sequences; text frames carry JSON control messages.
/api/terminal/{id}/stream
WebSocket endpoint for streaming terminal I/O. Upgrades HTTP to WebSocket. Protocol: binary frames = raw terminal I/O, text frames = JSON control messages (resize, disconnect, status).
Note
This is a WebSocket endpoint. Use a WebSocket client, not curl.
// JavaScript example
const ws = new WebSocket("ws://localhost:5050/api/terminal/my-terminal/stream");
ws.binaryType = "arraybuffer";
ws.onmessage = (e) => { /* handle terminal output */ };
/api/terminal/streams
List active terminal streams with subscriber counts.
Response
{
"streams": [
{ "terminalId": "Alice", "subscriberCount": 2 },
{ "terminalId": "Bob", "subscriberCount": 1 }
]
}
curl
curl http://localhost:5050/api/terminal/streams
XAML Preview
Render WPF XAML to PNG images for visual preview without launching the app. Endpoints are under /api/xaml.
/api/xaml/render
Render a WPF XAML snippet to a base64-encoded PNG image. Runs on an STA thread for WPF rendering.
Request Body
{
"xaml": "<Border xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' Background='#1e1e2e' Padding='20'><TextBlock Text='Hello World' Foreground='White' FontSize='24'/></Border>",
"width": 520,
"height": 400
}
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
xaml | string | Yes | - | WPF XAML markup (must include xmlns) |
width | integer | No | 520 | Render width in pixels |
height | integer | No | 400 | Render height in pixels |
Response
{
"imageBase64": "iVBORw0KGgoAAAANSUhEUgAA...",
"width": 520,
"height": 400
}
curl
curl -X POST http://localhost:5050/api/xaml/render \
-H "Content-Type: application/json" \
-d '{"xaml":"<Border xmlns=...>...</Border>","width":520,"height":400}'
Code Graph
Query the Roslyn-built C# code graph (symbols and their relationships). Endpoints are under /api/code-graph. Registered C# projects are indexed automatically by the CodeGraphWatcher background service — it sweeps and refreshes stale graphs shortly after app startup and re-indexes on edit, so you normally don't index by hand. Read endpoints return 503 ProblemDetails (application/problem+json) with "detail":"CodeGraph not available" only before the project has been indexed (e.g. the brief window before the startup sweep completes, or for a directory that isn't a registered project). To index any directory immediately, use POST /api/code-graph/index (or the index_code_graph MCP tool). The callers, callees, impact, and inheritance endpoints accept either symbolId (preferred, from a search result) or symbolName.
/api/code-graph/search
Search symbols by name, with an optional type filter.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Symbol name to search for |
type | string | No | Filter by symbol type: class, method, interface, etc. |
Response
{
"count": 1,
"results": [
{ "id": 42, "name": "MessageBroker", "type": "class", "filePath": "MCPServer/Services/MessageBroker.cs", "line": 35 }
]
}
curl
curl "http://localhost:5050/api/code-graph/search?query=MessageBroker&type=class"
/api/code-graph/callers
Get the direct callers of a symbol.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
symbolId | integer | No* | Symbol ID (from a search result) |
symbolName | string | No* | Symbol name (resolved to an ID server-side) |
* Supply symbolId or symbolName. Returns 404 if the symbol is not found.
Response
{
"symbolId": 42,
"count": 2,
"results": [
{ "id": 88, "name": "SendMessage", "type": "method", "filePath": "...", "line": 410 }
]
}
curl
curl "http://localhost:5050/api/code-graph/callers?symbolId=42"
/api/code-graph/callees
Get the direct callees of a symbol (what it calls). Same parameters and response shape as callers.
curl
curl "http://localhost:5050/api/code-graph/callees?symbolName=SendMessage"
/api/code-graph/impact
Transitive impact analysis (blast radius) — everything that transitively depends on the symbol.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
symbolId | integer | No* | Symbol ID |
symbolName | string | No* | Symbol name |
maxDepth | integer | No | Maximum traversal depth. Default: 10 |
* Supply symbolId or symbolName.
Response
{ "symbolId": 42, "count": 7, "results": [ ... ] }
curl
curl "http://localhost:5050/api/code-graph/impact?symbolId=42&maxDepth=5"
/api/code-graph/inheritance
Inheritance / implementation tree for a type. Same symbolId/symbolName parameters as callers.
Response
{ "symbolId": 42, "count": 3, "results": [ ... ] }
curl
curl "http://localhost:5050/api/code-graph/inheritance?symbolId=42"
Branch Metadata
Per-branch outcome labels (the one-line "what this branch delivers" shown on branch rows) and the task context an agent uses to draft them. Endpoints are under /api/branch-metadata/{projectId}. The project must be registered — unknown project IDs return 404 ProblemDetails with "detail":"unknown project". The branch name travels in the body (POST) or the branch query string (GET) rather than the URL path, so names containing / (the task/<id> convention) round-trip without route-escaping issues.
/api/branch-metadata/{projectId}/outcome
Upsert the outcome label for a branch.
Request Body
{
"branchName": "task/9f9c3141",
"outcome": "Allow agents to search past sessions by meaning",
"draftedBy": "Alice"
}
Response
{
"projectId": "proj-123",
"branchName": "task/9f9c3141",
"outcome": "Allow agents to search past sessions by meaning",
"draftedBy": "Alice",
"updatedAt": "2026-06-27T10:00:00Z"
}
curl
curl -X POST http://localhost:5050/api/branch-metadata/proj-123/outcome \
-H "Content-Type: application/json" \
-d '{"branchName":"task/9f9c3141","outcome":"Allow agents to search past sessions by meaning","draftedBy":"Alice"}'
/api/branch-metadata/{projectId}/draft-context
Get the task context an agent needs to draft an outcome for a branch (the agent does the rewrite; this only fetches context). Resolves the source task from originatingTaskId if supplied (must belong to the same project), otherwise from the most recent task linked to the branch.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
branch | string | Yes | Branch name |
originatingTaskId | string | No | Explicit source task ID (must belong to this project) |
Response
{
"projectId": "proj-123",
"branchName": "task/9f9c3141",
"sourceTaskId": "9f9c3141",
"sourceTaskTitle": "Add semantic session search",
"sourceTaskDescription": "...",
"promptHint": "Rewrite the supplied task title + description as a one-sentence user-facing capability..."
}
curl
curl "http://localhost:5050/api/branch-metadata/proj-123/draft-context?branch=task/9f9c3141"
/api/branch-metadata/{projectId}/outcomes
Get all branch outcomes for a project.
Response
{
"projectId": "proj-123",
"outcomes": [
{
"branchName": "task/9f9c3141",
"outcome": "Allow agents to search past sessions by meaning",
"draftedBy": "Alice",
"updatedAt": "2026-06-27T10:00:00Z"
}
]
}
curl
curl http://localhost:5050/api/branch-metadata/proj-123/outcomes