mac-developer-bridge
Give ChatGPT a real terminal on your Mac. Open-source MCP bridge for shell, files, PTY sessions, jobs, and Codex history.
Install / Use
claude mcp add alexanderradahl -- npx -y github:alexanderradahl/mac-developer-bridgeIf the server publishes to npm under a different name, use that package instead — check the repo README.
MCP Server
Model Context Protocol server
Quality Score
Category
AutomationSupported Platforms
Tags
Skill content
View source on GitHubMac Developer Bridge
Give ChatGPT a real terminal on your Mac.
Mac Developer Bridge turns a ChatGPT conversation into the reasoning layer for your actual Mac. It can run shell commands, edit files, start interactive terminal sessions, manage long-running jobs, and read stored Codex threads without starting another Codex model turn.

Example: “Find the Codex session I was working on yesterday, inspect the live repo, fix CI, push the result, and tell me what changed.”
That is the kind of workflow this project is built for.
[!WARNING] Mac Developer Bridge deliberately gives an MCP client the effective permissions of your macOS user. It is not sandboxed and has no command or path allowlist. Read SECURITY.md before enabling it.
The idea
ChatGPT has the reasoning. Your Mac has the source code, terminal, credentials, build tools, local services, and work in progress. Mac Developer Bridge connects the two over MCP without adding another model or agent loop in the middle.
flowchart LR
A[ChatGPT] -->|MCP| B[Mac Developer Bridge]
B --> C[Shell, Git and local CLIs]
B --> D[Filesystem]
B --> E[Real PTY sessions]
B --> F[Background jobs]
B --> G[Stored Codex history]
B --> H[Audit log and kill switch]
The bridge itself makes no OpenAI model call. It exposes deterministic local tools; ChatGPT supplies the reasoning. The Codex-history tools use read-only codex app-server methods and never call turn/start.
What this unlocks
- Recover a stored Codex thread, inspect the repo it refers to, and continue the work from ChatGPT.
- Run tests, builds, Git, package managers, database CLIs, AppleScript, and other tools already installed on your Mac.
- Keep interactive shells and terminal programs alive through a real PTY instead of pretending stdin is a terminal.
- Start long-running local jobs, inspect their logs later, and stop the whole process group.
- Read and modify files anywhere your macOS user can access.
This is intentionally different from a local coding agent. There is no second reasoning loop. ChatGPT remains the agent; the Mac is the execution environment.
Quick start
For a personal ChatGPT account, the menu-bar app is the easiest path. You need macOS, Node.js 18+, cloudflared, a hostname/tunnel, and ChatGPT Developer mode.
git clone https://github.com/alexanderradahl/mac-developer-bridge.git
cd mac-developer-bridge
./menubar/build.sh
open /Applications/MacDevBridge.app
Use Start, then Copy ChatGPT Setup from the menu-bar app. The detailed OAuth and Cloudflare setup is in Connecting to ChatGPT and DEPLOY.md.
Workspace users who have access to OpenAI Secure MCP Tunnel can use install.sh instead. See Transports.
Want to see what to ask it to do? Start with the copy-paste workflows.
If this is useful, star the repo so other developers can find it. If you build something interesting with it, share the exact workflow in What are you making ChatGPT do on your Mac?.
This is an independent open-source project and is not an official OpenAI or Cloudflare product. OpenAI, ChatGPT, Codex, and Cloudflare are trademarks of their respective owners.
Open source
Mac Developer Bridge is released under the MIT License. Bug reports and focused pull requests are welcome; see CONTRIBUTING.md. Security-sensitive reports should follow the guidance in SECURITY.md rather than being posted publicly.
Capabilities
- Arbitrary shell commands through
/bin/zsh -lc, under the logged-in macOS user - Detached background jobs with persistent stdout/stderr logs, status inspection, and process-group termination
- Unrestricted file read, write, append, list, stat, copy, move, chmod, symlink, mkdir, and recursive delete
- Unified-diff application through
git apply - Stored Codex thread discovery and reading without resuming a thread or starting a Codex model turn
- Paginated Codex turn retrieval for histories too large for a single response
- Local JSONL auditing
- Outbound-only private connectivity through OpenAI Secure MCP Tunnel, or a plain-HTTP loopback front end that Cloudflare Tunnel publishes over HTTPS
- Per-user persistence through a macOS LaunchAgent
- Fail-closed unlock latch:
bridge.mjsre-reads the unlock file before every tool call, so removing it refuses the next call and exits — unless the process inheritedMAC_DEV_BRIDGE_FULL_ACCESS_ACK, which bypasses the file entirely - Local kill switch (
scripts/disable.sh), which stops the front end, the bridge, detachedshell_startjob groups, interactive pty sessions, and federated child MCP servers, verifying the same targets it signalled
Git, package managers, Vercel CLI, database CLIs, AppleScript, browser CLIs, build tools, and other installed programs remain reachable through shell_exec; the bridge deliberately maintains no command allowlist.
Tools
| Tool | Purpose |
|---|---|
| bridge_status | Runtime identity, paths, permissions context, shell, audit mode, and Codex binary |
| shell_exec | Run any foreground shell command, optionally with cwd, env, stdin, timeout, and output cap |
| shell_start | Start a detached long-running process |
| shell_job_status | Inspect running state and log tails |
| shell_job_list | List persistent job metadata |
| shell_job_kill | Signal a background process group |
| fs_read | Read text or base64 with offset pagination |
| fs_write | Atomic replace, create, append, or binary write |
| fs_list | Recursive or non-recursive directory listing |
| fs_stat | lstat metadata and symlink target |
| fs_manage | mkdir, remove, move, copy, chmod, or symlink |
| apply_patch | Apply or check a unified diff with git apply |
| codex_thread_read | Read a stored Codex thread without resuming it |
| codex_thread_list | Search and page stored Codex threads |
| codex_thread_turns_list | Page stored turns with full, summary, or omitted items |
| audit_tail | Read the local bridge audit tail |
Interactive terminal sessions
A real pty, allocated by lib/ptyhelper.pl (core Perl, no dependency added). Advertised only when the helper runs on this host; otherwise the six tools are absent rather than broken.
| Tool | Purpose |
|---|---|
| pty_start | Start a program on a real terminal and return a session id |
| pty_read | Read the transcript from a byte cursor, optionally long-polling |
| pty_write | Send keystrokes, including control characters |
| pty_resize | Change the window size, confirmed by a kernel read-back |
| pty_signal | Signal the session's process group |
| pty_close | End the session and reclaim it |
Limits that will be visible in normal use:
- Line length. While the terminal is in canonical mode — the default, and what every interactive prompt uses — the line discipline discards an input line of 1024 bytes or more instead of truncating it.
pty_writerefuses such a write withPTY_WRITE_CANON_LIMITrather than reporting bytes the program will never see. Bytes accumulate across calls until a\ror\n, so chunking does not evade it. Send lines of at most 1023 bytes. A session that has put its terminal in raw mode is checked and allowed. - Concurrency. The session cap is taken, not merely checked, so concurrent
pty_startcalls cannot exceed it. - Retention. Each session keeps the last
MAC_DEV_BRIDGE_PTY_RING_BYTESof output in a fixed ring;pty_readreportslostByteswhen a cursor falls behind it. - Containment. See SECURITY.md —
pty_closereportsleaderGroupGone,ttyProcessesKilledanduncontainedPidsseparately, andcontainmentVerifiedis true only when nothing survived.
Federated child MCP servers
If a provider registry is configured, each provider's tools are advertised with a key__tool prefix and proxied. There is no built-in provider: the registry is operator-supplied. Personal-browser-profile mode requires a per-use operator grant — see SECURITY.md.
Bridge environment
These are read by bridge.mjs on both transports.
| Variable | Default | Purpose |
|---|---|---|
| MAC_DEV_BRIDGE_DATA_DIR | ~/Library/Application Support/MacDeveloperBridge | State, job metadata, federation roots. |
| MAC_DEV_BRIDGE_LOG_DIR | ~/Library/Logs/MacDeveloperBridge | Log directory. |
| MAC_DEV_BRIDGE_AUDIT_LOG | $LOG_DIR/audit.jsonl | Audit JSONL path. |
| MAC_DEV_BRIDGE_AUDIT_MODE | metadata | off, metadata, or full. full records tool arguments; see the caveat in SECURITY.md. |
| MAC_DEV_BRIDGE_UNLOCK_FILE | $DATA_DIR/FULL_ACCESS_ENABLED | The revocable unlock latch. Re-read before every tool call. |
| MAC_DEV_BRIDGE_UNLOCK_RECHECK_MS | 3000 | How often the latch is re-read while a pty session or a federated child exists and the client is silent. Bounds how long either can outlive a removed unlock file. |
| MAC_DEV_BRIDGE_SHELL | login shell | Shell used for shell_exec/shell_start. |
| MAC_DEV_BRIDGE_DEFAULT_OUTPUT_BYTES | 1000000 | Default per-call output cap. |
| MAC_DEV_BRIDGE_MAX_OUTPUT_BYTES | 8000000 | Ceiling a call may request. |
| MAC_DEV_BRIDGE_PTY_PERL | /usr/bin/perl | Interpreter for the pty helper. |
| MAC_DEV_BRIDGE_PTY_HELPER | lib/ptyhelper.pl beside bridge.mjs | Helper script path. |
| MAC_DEV_BRIDGE_PTY_MAX_SESSIONS | 8 (1–64) | Live session cap. kern.tty.ptmx_max is 511 system-wide, so this protects the operator's own Terminal.app, not just this process. |
| MAC_DEV_BRIDGE_PTY_RING_BYTES | 262144 (4 KiB–4 MB) | Per-session output retention. Total retention is this times the session cap. |
| MAC_DEV_BRIDGE_PTY_IDLE_TIMEOUT_MS | 900000 (1 s–1 h) | Idle reclaim window, and a ceiling: pty_start may request a shorter one, never a longer. A live session's effective value is in bridge_status. |
| MAC_DEV_BRIDGE_PTY_MAX_LIFETIME_MS | 28800000 (5 s–24 h) | Hard ceiling, enforced even on an actively used session. |
| MAC_DEV_BRIDGE_PTY_START_TIMEOUT_MS | 5000 | How long pty_start waits for the helper to report a real pty. |
| MAC_DEV_BRIDGE_MCP_SERVERS | — | Path to a child-MCP provider registry JSON file. |
| MAC_DEV_BRIDGE_MCP_SERVERS_JSON | — | The same registry inline. Takes precedence. |
| MAC_DEV_BRIDGE_MCP_START_DEADLINE_MS | 15000 (1 s–120 s) | Wall-clock ceiling on one provider's whole startup — handshake, grant check, and every tools/list page. A provider that exceeds it is abandoned rather than left holding up the tool surface. |
| MAC_DEV_BRIDGE_MCP_PING_IDLE_MS | 30000 | Idle interval after which a federated child is pinged; a child that fails the ping is treated as hung and restarted. |
| MAC_DEV_BRIDGE_PERSONAL_APPROVAL_FILE | $DATA_DIR/PERSONAL_BROWSER_APPROVED | Where the single-use personal-browser grant is read from. The bridge never creates it. |
| MAC_DEV_BRIDGE_FULL_ACCESS_ACK | — | Environment form of the acknowledgement. Not revocable; see below. |
What “full access” means
The MCP server runs with the effective permissions of the macOS account that launches it. It has no path allowlist, shell-command allowlist, sandbox, or internal per-command approval gate.
macOS still enforces TCC privacy controls, Full Disk Access, ACLs, SIP, Keychain access controls, and sudo authentication. Non-interactive MCP shell calls do n
Truncated for display — read the full file on GitHub.
Related Skills
momen-cursurrules-prompt-file
40.6kCursor rules for building custom frontends with Momen.app as headless BaaS with GraphQL API, actionflows, AI agents, and Stripe integration.
pyspark-etl-best-practices-cursorrules-prompt-file
40.6kCursor rules for PySpark ETL development with code style, joins, window functions, map operations, and Iceberg patterns.
semiotic-react-dataviz-cursorrules-prompt-file
40.6kCursor rules for Semiotic data visualization library with 30+ chart types, MCP server, and AI-assisted chart generation.
Agent-Reach
72.0kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
