SideboardBLOCK
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
Orchestrate a fleet of coding agents on your Mac. Isolated git worktrees. A kanban of the whole fleet. An orchestrator that can drive it. A phone app, CLI, and MCP so you can reach this machine — without a cloud workspace.
Peers often spawn one agent per git worktree. Sideboard isolates the checkout — one workspace per ticket, PR, or named branch — and runs as many agents as that workspace needs. Sibling chats share the files. The remaining job is an orchestration tier: an agent that can reason about those chats, a board where you can see that, and a phone app, CLI, and MCP so you can reach this machine — without moving the repo into someone else’s cloud.
Sideboard started as a local port when Conductor moved that tier into a paid cloud, then added the pieces that still belong on this Mac: MCP orchestration, a global kanban, a phone app, and CLI / MCP so other systems can drive it. Agents are plugs (Claude Code, Codex, OpenCode, Cursor). Compute stays on this machine (corporate VPN, private git, internal APIs). The phone app is remote control, not a rented sandbox.
- A global board for you — status, live output, and fan-out across every thread
- An MCP for the agents — list threads, wait on turns, read diffs, orchestrate the fleet, and present artifacts, schemas, and files in the desktop UI
- A phone app, CLI, and MCP to this Mac — pair the phone from Settings → Remote; register MCP from any harness; script the fleet without the GUI
attach / adopt remain the door back to the native harness — move in and out of Sideboard as you choose.
Run agents in isolated thread/* worktrees from the CLI, desktop, or MCP. The Mac must stay awake for the phone to reach it, and for scheduled jobs to fire — opt in from Settings → Advanced.
Agents and backends are plugs, not the product. CLI, MCP, and the des
92efd9436e15OBSERVED · 2026-10-12Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add core --env ACTIONS_ID_TOKEN_REQUEST_TOKEN=${ACTIONS_ID_TOKEN_REQUEST_TOKEN} --env ACTIONS_ID_TOKEN_REQUEST_URL=${ACTIONS_ID_TOKEN_REQUEST_URL} --env APPLE_APP_SPECIFIC_PASSWORD=${APPLE_APP_SPECIFIC_PASSWORD} --env CLAUDE_CODE_OAUTH_TOKEN=${CLAUDE_CODE_OAUTH_TOKEN} -- npx -y @sideboard-ai/[email protected]{
"mcpServers": {
"core": {
"command": "npx",
"args": [
"-y",
"@sideboard-ai/[email protected]"
],
"env": {
"ACTIONS_ID_TOKEN_REQUEST_TOKEN": "${ACTIONS_ID_TOKEN_REQUEST_TOKEN}",
"ACTIONS_ID_TOKEN_REQUEST_URL": "${ACTIONS_ID_TOKEN_REQUEST_URL}",
"APPLE_APP_SPECIFIC_PASSWORD": "${APPLE_APP_SPECIFIC_PASSWORD}",
"CLAUDE_CODE_OAUTH_TOKEN": "${CLAUDE_CODE_OAUTH_TOKEN}"
}
}
}
}Exposed tools (93)
55 read · 35 write · 3 destructive. Blast radius: 3 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.
| Tool | Risk | Description |
|---|---|---|
Agent | read | scan auth · 4 tools · 12s |
Compact | read | Summarized conversation |
Read | read | Read auth.ts |
Sideboard | read | Sideboard desktop Brightsy MCP client |
Skill | read | Using /long-running |
TaskOutput | read | Wait for task_1 |
abletime_comment | write | Add a markdown comment on an AbleTime task (id or CRM-232). When reviewing a PR or ticket, show the draft in chat and wait until they type a next step — do not ask_user after the review. The author sees this immediately. |
abletime_create_task | write | Create an AbleTime task in a project. Call abletime_list_projects if you do not have a project id. Pass parent (CRM-232) for a spin-off. New tasks start in todo (or backlog). |
abletime_download_attachment | read | Download an AbleTime task file into |
abletime_ensure_task | write | Find or create an AbleTime task for this work, then create_workspace with sourceType=ticket. |
abletime_get_task | read | |
abletime_list_projects | write | List AbleTime projects (and categories). Use a project id on create/ensure. |
abletime_list_tasks | read | List open AbleTime tasks (excludes done/archived). Optional projectId filter. Pass updatedSince for tasks updated since then and any comments on that page. |
abletime_orientation | read | Call first when using AbleTime. Returns viewer, active tasks, and projects. |
abletime_search_tasks | read | Search AbleTime tasks by text, reference, or tag. Pass updatedSince for tasks updated since then and any comments on that page. |
abletime_update_task | write | Update an AbleTime task (id or CRM-232). Pass title, description, state, labels, project, parent, and/or relations. labels replaces tags. project is name or id (tasks stay in a project). parent is CRM-232 or |
add_project | write | Register a git repo as a Sideboard workspace |
add_stack_layer | write | Add a branch on top of the current stack ( |
archive_chat | read | Archive a thread (stops agent/dev, runs archive script, removes worktree when last chat tab). Coordinators commit, push, and open PRs by asking the worktree agent (ask_git). Merge only when the user explicitly asked. |
ask_git | read | |
ask_user | read | |
create_pr_stack | write | Create a new GitHub PR stack with one Sideboard worktree per layer (bottom→top branch names). Requires |
create_schedule | write | |
create_workspace | write | |
delete_env | destructive | Delete a Settings → Environment variable. scope=project uses the project prefix (same rule as set_env). Does not print the stored value. |
delete_schedule | destructive | Delete a local schedule. Pass id from list_schedules. |
fanout | write | Best-of-n: create one thread per agent with the same prompt (parallel attempts) |
fork_chat | read | |
fork_workspace | read | |
get_chat | read | |
get_diff | read | Compact diff summary (capped hunks, paginated) |
get_pr_checks | read | Snapshot of GitHub PR checks for a worktree thread ( |
get_pr_stack | read | Load the GitHub PR stack for a thread worktree ( |
get_run_log | write | Read the Run-tab terminal for a worktree script (same stdout/stderr as the desktop Dev pane). Default is a tail — raise |
get_turn_result | read | |
get_viewer_context | read | Read account and project user context (Settings → Agents / Projects): roles, tickets, and review queues as freeform text. Orchestration must pass repoPath from list_projects for project context. Worktree turns may omit repoPath (uses cwd). |
github_comment | write | Add a markdown comment on a GitHub issue (#123 or URL). Uses Account gh. When reviewing a PR or ticket, show the draft in chat and wait until they type a next step — do not ask_user after the review. The author sees this immediately. |
github_create_issue | write | Create a GitHub issue. Pass parent (#123) to mark a spin-off in the body. |
github_download_attachment | read | Download a GitHub issue file (github.com/user-attachments/... or githubusercontent.com) into |
github_get_issue | read | Get a GitHub issue (#123 or URL): body, comments, state, projects, attachments. Re-fetch to read new comments. projectsError means GitHub refused Projects (usually missing read:project — run |
github_list_projects | read | List open GitHub Projects for the signed-in user and this repo owner (title, number, id). Pass a title as project on github_update_issue. If GitHub says the token is missing read:project, run |
github_search_issues | read | Search or list open GitHub issues in this repo via Account gh. Default 40; pass query and/or limit (max 250) when truncated. assignee: me, unassigned, all, or a login. Pass updatedSince for new/updated tickets and new comments (e.g. “any updates since yesterday?”). |
github_update_issue | write | Update a GitHub issue (#123). Pass title, body, state (open|closed), labels, project, parent, and/or relations. labels replaces all names (pass [] to clear). project is a Project title, or |
linear_comment | write | Add a markdown comment on a Linear issue (uuid or ENG-123). When reviewing a PR or ticket, show the draft in chat and wait until they type a next step — do not ask_user after the review. The author sees this immediately. |
linear_create_issue | write | Create a Linear issue. Call linear_list_teams first. team is id/key/name; state is name/type/id; assignee is |
linear_download_attachment | read | Download a Linear file attachment into |
linear_get_issue | read | |
linear_list_projects | read | List Linear projects (id, name, slugId). Pass a name or id as project on linear_update_issue. linear_get_issue and search rows also include the project a ticket is on. |
linear_list_teams | read | List Linear teams (id, key, name), workflow states, and the active cycle. Use team key on create; state name or type on create/update; cycle name/ |
linear_search_issues | read | Search or list open Linear issues. Default 40; pass query and/or limit (max 250) when truncated. assignee: me, unassigned, all (default with query), or a user id/name. Pass updatedSince for new/updated tickets and new comments (e.g. “any updates since yesterday?”). |
linear_update_issue | write | Update a Linear issue (uuid or ENG-123). Pass title, description, state, assignee, priority, cycle, labels, project, parent, and/or relations. Cycle/project/parent: name or id, or |
list_board | read | |
list_branches | read | List git branches in a registered workspace. Pass repoPath from list_projects (unmerged into the default branch by default — for create_workspace sourceType=branch). |
list_chats | read | |
list_env | read | List Settings → Environment variable names (not values). scope=project keys use the project prefix (project name, uppercased, plus _). scope=account keys are shared by every project. Pass repoPath from list_projects when calling from orchestration so the reply includes this project prefix. |
list_issues | read | |
list_models | read | List models for an agent. Prefer Auto: do not call this unless you have a reason to pin a specific model (user request, cost/latency, capability). Omit agent to list all. |
list_projects | read | |
list_prs | read | List GitHub PRs for a registered workspace (the review surface for assigned ticket work — not the tickets). Pass repoPath from list_projects. |
list_run_scripts | write | |
list_schedules | write | List local Sideboard schedules that trigger a chat when due. Jobs fire only while Sideboard.app is running on this Mac (sleep skips until wake). |
list_teams | read | List Slack workspaces connected in Settings → Remote. Each row is team_id + name. Pass team_id to slack_list_channels, slack_list_users, slack_read, slack_post, and slack_replies. |
notify_orchestrator | read | |
open_pr_stack_layers | read | Materialize one worktree+thread per stack layer (or a single 1-based layer). Pass a thread ref already on the stack. |
posthog_api | read | |
present_artifact | read | |
present_files | read | |
present_plan | read | Draft the rollout |
present_schema | read | |
remove_project | destructive | Unregister a Sideboard workspace and archive its chats |
request_review | read | |
restore_chat | read | Restore an archived thread (recreates worktree from branch when needed) |
run_dev_script | write | |
run_schedule | write | Fire a schedule now (does not wait for nextRunAt). Queues the prompt on the target chat or starts a new Global chat. If Sideboard.app is running, the desktop drains the turn. |
run_setup | write | Re-run workspace setup (Sideboard/Conductor settings, .cursor/worktrees.json, or script/setup). New worktrees already run this automatically. |
send_to_chat | write | Steer a prompt on a workspace chat (Settings → Follow-up, default steer: interrupt the in-flight turn and start now, same as the workspace composer). Use after create_workspace to start or continue a conversation. For commit/push/PR, prefer ask_git (canonical desktop-button phrases). Send |
set_caffeinate | write | |
set_env | write | |
set_workspace_tags | write | |
slack_list_channels | read | List channels in a connected Slack workspace. Pass team_id from list_teams. |
slack_list_users | read | List or search people in a connected Slack workspace (for DMs / @mentions). Pass team_id from list_teams. Optional query matches name, display name, real name, or email. |
slack_post | write | |
slack_read | write | Read recent messages in a Slack channel or DM, or a thread when ts is set. Pass team_id from list_teams and #channel, @user, or a C.../D.../U... id. |
slack_replies | read | |
start_board_card | write | |
stop_chat | write | |
stop_dev_script | write | Stop a run script started with run_dev_script or the desktop Dev button (same as UI Stop). Omit name to stop all scripts on this worktree. Worktree turns may omit ref (uses cwd). |
stop_job | write | |
tool | read | tool |
update_schedule | write | Update a local schedule (prompt, cadence, target chat, enabled). Pass id from list_schedules. |
update_viewer_context | write | Replace account or project user context (Settings → Agents / Projects). Never call until the user confirmed. Show the proposed text, ask_user (Save this context / Do not save), wait, then pass confirmed=true. Empty context clears that field. |
wait_for_job | read | |
wait_for_turn | read |
Trust audit
BLOCKgrade F · trust 41/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | FAIL |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | FAIL |
| L3 | Class-specific surface | WARN |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (12 observation(s))
- Network
- declared (11 observation(s))
- Shell
- declared (6 observation(s))
- Dependencies
- not all pinned
- Secrets in source
- found
Findings (25)
issue-payload.ts
var run = new Function('module', 'exports', 'require', 'React', 'ReactDOM', transformed);Never tell the user “say status when it’s done.” You wait — unless you decided to stop.
<?xml version="1.0" encoding="utf-8"?><Error><Code>BlobNotFound</Code><Message>The specified blob does not exist.
icon.icns
.cursor/skills/agent-rpc
.cursor/skills/bugbot-follow-ups
.cursor/skills/glossary
.cursor/skills/graph-engineering
.cursor/skills/long-running/SKILL.md
curl -fsS -o /dev/null --max-time 1 "http://127.0.0.1:${port}"token: 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1In0.sig',
'xoxp-alice-user',
delete_env, delete_schedule, remove_project
issue-payload.test.ts
const hash = createHash('sha1').update(norm).digest('hex').slice(0, 16);return `wt-${createHash('sha1').update(norm).digest('hex').slice(0, 16)}`;ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
'../../packages/core/src/agents/message-parts.ts',
'../../packages/core/src/agents/usage.ts',
'../../packages/core/src/agents/claude-usage.ts',
'../../packages/core/src/store/usage-on-limit.ts',
AbleTime requires an HTTPS redirect, so the browser returns to `https://www.sideboard.cloud/oauth/abletime/callback` (same host as the CIMD). That page opens the desktop listener at `http://127.0.0.1:
Callback URL for the Sideboard Linear OAuth app: `http://127.0.0.1:19848/callback`. Override the client with `SIDEBOARD_LINEAR_CLIENT_ID` (secret optional — the desktop uses PKCE). You will not see th
expect(normalizePreviewUrl('127.0.0.1:8080/app')).toBe('http://127.0.0.1:8080/app');Gates applied: instruction_override, no_behavioural_pass.
92efd9436e15full audit observations/trust-audit/mcp-server/mattlevine__sideboard.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-12 | 92efd9436e15 | BLOCK | F | 41 | first audit |
Questions
What tools does @sideboard-ai/cli expose?
93 in total: 55 read-only, 35 that write, and 3 that can delete or overwrite (delete_env, delete_schedule, remove_project). Every one is listed on this page with its risk.
Is @sideboard-ai/cli safe to connect to an agent?
No — not without reading the findings first. The audit graded it F (41/100) and found 4 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 3 of its tools can destroy data, so scope the token you give it to what you actually need.
What credentials does @sideboard-ai/cli need?
It reads ACTIONS_ID_TOKEN_REQUEST_TOKEN, ACTIONS_ID_TOKEN_REQUEST_URL, APPLE_APP_SPECIFIC_PASSWORD, CLAUDE_CODE_OAUTH_TOKEN, CURSOR_API_KEY, GH_TOKEN, GIT_ASKPASS, NODE_AUTH_TOKEN, NPM_TOKEN, SIDEBOARD_ABLETIME_OAUTH_CLIENT_ID, SIDEBOARD_ABLETIME_OAUTH_REDIRECT and SIDEBOARD_GIT_AUTH_DIR from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does @sideboard-ai/cli run?
It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as @sideboard-ai/core at 0.1.293.
How current is this page?
The grade is for one exact copy of the source (92efd9436e15), read on 2026-10-12. The repository is watched and re-audited when it changes.