Cheap Labor
Cheap Labor is an MCP bridge that lets ChatGPT drive a local Codex CLI over your repo to plan, edit, and implement code while keeping expensive Codex usage for heavy work only.
Arm a session for an existing or new project (
init,create_project) and get a requiredsession_tokenfor all project tools.Explore the repo for free: list directory trees, read files, regex grep, and view git status/diff/log without spending Codex credits.
Write and edit files directly: create new files (
write_file), apply exact-match edits (edit_file), batch multiple guarded edits/writes atomically (edit_pack), and manage plans viaplan_read/plan_write/task_update.Run verification commands: execute tests, builds, and typechecks through a safety-bucketed
run_commandwith configurable approval modes (normal/auto).Delegate heavy implementation to Codex:
implementexecutes a detailed step-by-step plan in a workspace-write sandbox,deep_exploreanswers complex read-only questions, andcodex_replycontinues sessions (e.g., approval vetoes).Protect work with checkpoints and git safety: create/restore rollback checkpoints automatically before risky runs, list checkpoints, and commit locally with user-approved messages — never pushing to remotes.
Control safety and scope: switch approval modes, redact secrets, enforce project-path scoping, and keep the bridge dormant until triggered by
@cheap-labor.
Integrates with OpenAI's ChatGPT and Codex to enable an agentic coding workflow: ChatGPT handles planning, exploration, and reviewing while Codex executes implementation, with tools for local repo inspection, direct file edits, plan handoff, checkpoints, and git operations.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Cheap LaborPlan and implement a feature to export data as CSV."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Abstract
Cheap Labor exists because Codex usage is a limited pool — and most of what a coding agent does is not writing code. Reading files, exploring the repo, planning, and reviewing diffs all burn the Codex allowance without ever writing code.
Then came the key realization: ChatGPT and Codex usage are counted separately — two independent allowances. So we decided to split the work: ChatGPT does all the thinking on its own allowance, and Codex is spent only on real implementation.
That's the whole idea — a local MCP server joined over a Secure MCP Tunnel: ChatGPT on the web drives a Codex CLI on your machine, over your local repo, with a single @cheap-labor trigger.
Built With
Cheap Labor is built with a deliberately small, cross-platform stack:
Runtime: Node.js (>= 20) — bridge server runtime
Language: TypeScript — all bridge code
Protocol: MCP SDK (
@modelcontextprotocol/sdk) — stdio MCP server + clientValidation: zod — tool argument schemas
Executor: Codex CLI (
codex mcp-server) — spawned child MCP client for exploration and implementationConnectivity: Secure MCP Tunnel (
tunnel-client) — private, outbound-only link between ChatGPT web and the local server
Related MCP server: Kontrol
Prerequisites
macOS or Linux with Node.js >= 20 + npm
git
A paid ChatGPT account with developer mode
Codex CLI, logged in (
codex login)tunnel-client— installed during setup: macOS via Homebrew; Linux via the GitHub releases binary (linux-amd64/arm64) on your PATHA Secure MCP Tunnel + runtime API key from the OpenAI platform (the installer points you to the right pages)
Installation
Jump to: 1. Clone & install → 2. Use it
Clone the repo and move into it:
git clone https://github.com/psrisuphan/cheap-labor.git cd cheap-laborRun the installer — it installs deps, builds the bridge, writes your tunnel profile, validates all 25 tools, and walks you through connecting the app to ChatGPT web:
./scripts/install.sh
Use It
Start the tunnel — keep it running while you use cheap-labor:
./scripts/tunnel.sh start # stop: ./scripts/tunnel.sh stopOpen a new ChatGPT chat and type
@cheap-labor(or whatever you named the app/plugin when creating it).Confirm the project directory when asked — the session is armed.
Approval Mode — defaults to
normal(asks you before running every command). Switch to auto-approve (GPT decides the risk) with@cheap-labor, switch to auto-approve.
Uninstall
./scripts/uninstall.shCleans up everything the script can reach: legacy MCP registration, the tunnel daemon, .codex-bridge/ state in every initialized project, the tunnel profile and stored API key, and the build artifacts. Three prompts (press Enter for the recommended answer, n to keep). Afterwards it prints a manual cleanup guide for the parts only you can reach: the ChatGPT app connection, the Platform tunnel, the runtime API key, and the project folder.
How It Works
The bridge is dormant until armed. While dormant, the server ships only a short "ignore these tools" notice as its instructions, so unrelated prompts are answered without the bridge ever being considered. The full workflow rules live in the init tool's return payload and enter the conversation only after arming.
The trigger is the invocation itself — no prompt monitoring, no tag syntax, no phrase scanning:
The user invokes cheap-labor by typing
@cheap-labor. That's the only trigger.ChatGPT asks which project you want, resolves it (
find_projectsfor fuzzy names,create_projectfor new directories), confirms the exact path with you, then arms the session —init(project)(orcreate_projectdirectly for a brand-new directory) and receives asession_token.Every other tool refuses to run without a valid
session_token— a hard backstop that also blocks accidental use outside the workflow.
The Workflow
Arm the session —
@cheap-labor+ confirm the project →initreturns the token.Understand —
git_status,list_tree,read_file,grep(all free).Plan in detail — ChatGPT writes
PLAN.md/SPEC.md/TASKS.mdinto the repo's.codex-bridge/folder withplan_write. The plan is exact step-by-step instructions: which files to create/edit, what each change should be, which commands to run, and how to verify.Small edits, done directly —
write_file/edit_filehandle one-file changes for free.Delegate heavy work —
implementhands the plan to Codex, which executes the steps literally, runs builds/tests, fixes what breaks, and returnsIMPLEMENTATION COMPLETE.Review — ChatGPT reads the returned
git diffand sends targeted corrections back through the same loop.
Features
One-Trigger Activation:
@cheap-laborin any ChatGPT chat is the only trigger; the bridge stays dormant (zero model attention) until invoked — no prompt monitoring, no tag syntax, no phrase scanning.Three-Bucket Command Safety: provably-safe read-only commands (git status/log/diff, ls, cat, grep, …) run freely; dangerous ones (file deletes, git rewrites, network installs, interpreter one-liners) always require your explicit approval; everything else depends on the approval mode — ask first (
normal, default) or let ChatGPT judge safe commands itself (auto). Switch modes in chat any time withset_approval_mode.Built-In Safety Rails: project path scoping, secret redaction, checkpoints before every heavy run, and local-only commits that never push.
Cross-Platform: macOS and Linux, no public ports, outbound-only tunnel.
Tools Reference
Free bridge tools (deterministic local I/O, no Codex cost):
Tool | Purpose |
| Arm the session for a project (the single entry point); returns the |
| Directory structure, depth-limited |
| File contents, line-ranged, size-capped, secrets redacted ( |
| Regex search with path-aware include/exclude globs ( |
| Repo state + the review loop (untracked files surfaced) |
| Three-bucket execution (tests, build, typecheck): safe allowlist runs freely; dangerous commands always need your approval; the rest follows the approval mode. Output secrets redacted ( |
| Switch the global approval mode — |
| Read current bridge settings (e.g. the approval mode) |
| Create a new file directly (refuses to overwrite) |
| Exact-match edit of an existing file (content-based stale guard) |
| Batch edits/writes after validating every guard before application |
| Snapshot HEAD + working tree for rollback (auto before |
| Restore to a checkpoint (user-confirmed; itself undoable) |
| Stage + commit locally with a user-approved message; refuses existing staged work and never pushes |
| List recorded checkpoints |
| Resolve fuzzy names to candidate paths (shallow, well-known locations) |
| Create a new project directory (no git init); returns a |
| Manage |
Codex-backed tools (spend the Codex pool):
Tool | Purpose |
| Read-only Codex session for questions free tools can't answer (model upgrade per-call with your confirmation) |
| Workspace-write Codex on the current plan; returns summary + |
| Continue a session by thread id (approval veto loop, follow-ups); bound to the project that created it |
Safety Model
implement/deep_explorealways pass an explicit sandbox (workspace-write/read-only) — neverdanger-full-access.Fixed Codex model — every Codex call pins
gpt-5.6-lunawithmediumreasoning and Fast Mode off, passed as per-call overrides. The bridge never writes to~/.codex/config.toml. The one exception:implement/deep_exploreaccept a stronger model (e.g.gpt-5.6-sol), but the bridge refuses it unless the call passesmodel_confirmed: true— set only after you explicitly agree to that exact model in chat. Per-call: each non-default model run needs its own confirmation.Auto-safe approvals — Codex shell approvals surface as MCP elicitations: commands on the provably-safe allowlist are auto-approved; dangerous ones (writes, network, git mutations, interpreter one-liners) are always declined — in
automode too — and recorded so ChatGPT relays them to you for a veto. The veto is executed withcodex_reply.Approval modes —
run_commandbuckets every command. The safe allowlist (git status/log/diff/show/rev-parse,ls,cat,pwd,echo,grep,rg,sort,uniq,wc,head,tail,printf,date) always runs. Dangerous commands (file deletion/overwrite, git rewrites, network installs, interpreter one-liners) always require your approval — the bridge refuses them withoutapproved: true. Everything else follows the mode:normal(default) asks you first;autolets ChatGPT judge safe commands itself but still makes it ask you for dangerous ones. Change it any time withset_approval_mode— it applies to every chat immediately.write_fileonly creates new files;edit_fileonly edits existing ones via exact-match replacement (stale/ambiguous matches write nothing);edit_packvalidates the full batch before applying it. All cap sizes and refuse binary files.Ship mode —
checkpointsnapshots HEAD + working tree (taken automatically before everyimplement);rollbackrestores a checkpoint (itself undoable);git_commitrefuses a non-empty index, then commits locally with a user-approved message. Push/pull/reset/rebase/checkout are never exposed.Bridge tools refuse paths outside the session-approved project directory.
Git-backed tools require the approved project to be the repository root, preventing nested projects from affecting sibling directories.
read_file/grep/git_diff/run_commandredact known secret patterns by default; passredact_secrets: falsewhen a task genuinely needs the raw content.
Project Structure
cheap-labor/
├── assets/ # Logo / icons
├── scripts/ # Installer, uninstaller, tunnel control, setup
│ ├── install.sh # All-in-one installer
│ ├── uninstall.sh # Clean uninstaller
│ ├── tunnel-setup.sh # Writes the tunnel-client profile
│ ├── tunnel.sh # start / stop / restart / status / logs the tunnel daemon
│ └── setup.mjs # Prerequisite check
├── src/ # Bridge MCP server
│ ├── index.ts # Server entry, tool registration, server instructions
│ ├── git.ts # Exact repository-root boundary for Git-backed tools
│ ├── safety.ts # Project scoping, redaction, risk classification, command buckets
│ ├── projects.ts # Session approvals, ledger, find/create
│ ├── planstore.ts # .codex-bridge/ I/O
│ ├── settings.ts # Approval mode (normal / auto)
│ ├── approvals.ts # Auto-safe policy
│ ├── skips.ts # Shared directory-skip list
│ └── tools/ # context, command, codex, deepExplore,
│ # implement, edit, plans, ship
├── tests/ # Node test suite
├── dist/ # Build output (gitignored)
└── package.jsonTesting
To run the unit test suites:
npm run typecheck # tsc --noEmit
npm test # node --test (tsx)
npm run build # tsc → dist/Local Data & Logs
Cheap Labor stores its tunnel profile, runtime API key, and daemon logs locally, outside the project directory:
macOS / Linux:
~/.config/tunnel-client/
Inside this directory you will find:
cheap-labor.yaml— thetunnel-clientprofile (contains the tunnel id).cheap-labor.key— the runtime API key, chmod 600, never committed.cheap-labor.log— the tunnel daemon log.
Bridge settings (the approval mode) live in ~/.codex/cheap-labor-settings.json (chmod 600), and the list of initialized projects in ~/.codex/cheap-labor-approved-projects.json (read by the uninstaller to purge .codex-bridge/ state).
Plans and handoff files are written into each project's .codex-bridge/ folder at runtime (gitignored). Checkpoint metadata is stored under Git's private directory and snapshots are pinned under refs/bridge-checkpoints/. Codex's own configuration and auth live in ~/.codex/.
License
This project is licensed under the MIT License. See the LICENSE file for the full license text.
Available Tools
23 toolscheckpointA
Snapshot the current repo state (HEAD + working tree, tracked AND untracked) into a local checkpoint so it can be rolled back. Free local git plumbing — no Codex cost. Take one before risky edits or implement runs (implement takes one automatically). Never touches branches, history, or remotes.
Inputs: note, project, session_token.
checkpointsA
List recorded checkpoints for this project (free local git plumbing).
Inputs: project, session_token.
codex_replyA
Continue an existing Codex session by thread id. Used to relay approval decisions ('The user approved: ' / 'The user denied: ; proceed without it') and to push a session forward. Thread ids come from implement/deep_explore results.
Inputs: prompt (required), threadId (required).
create_projectA
Create a brand-new project DIRECTORY (git is NOT initialized — that's up to the user). Returns a session_token and arms the chat exactly like init — no second ask, the user's creation request IS the confirmation. Call when the user explicitly asks to create a new directory: resolve the absolute path yourself (expand ~; interpret 'Desktop', 'Documents', etc. as under the home directory), then call this directly. Never suggest shell commands like mkdir instead. Refuses paths that already exist and paths whose parent directory doesn't exist.
Inputs: project (required).
deep_exploreA
Fallback for questions the free bridge tools can't answer (e.g. 'trace how auth is wired across 30 files'). Runs the official codex mcp-server in a READ-ONLY sandbox with capped scope, and returns findings only. Costs Codex usage — always try list_tree/read_file/grep/git_* first.
Inputs: question (required), path, model, project, +1 more.
edit_fileA
Edit an existing file directly via exact-match replacement (free — no Codex usage). The search text must match the file's current content exactly, once (or set replace_all) — a stale or ambiguous match refuses with nothing written, so re-read the file and retry. Use for small, well-defined edits ChatGPT can make itself; delegate large multi-file work to implement.
Inputs: path (required), search (required), replace (required), project, +2 more.
edit_packA
Batch several edits and/or new files into ONE all-or-nothing operation (free — no Codex usage). Every guard is validated against current on-disk content first; if ANY item fails, NOTHING is written (no partial state). Same-file edits chain in order. Use for multi-file changes that are still small and well-defined; delegate heavy work to implement. Max 20 items per pack.
Inputs: edits, writes, project, session_token.
find_projectsA
Resolve a fuzzy project name (e.g. 'the app on my Desktop') to candidate paths. Scans only shallow well-known locations (home, Desktop, Documents, Projects, Developer, code, dev, src, workspace), max 2 levels deep, skipping hidden dirs. Free local I/O. Use ONLY after the user has named a project in chat — never preemptively — then show candidates to the user and ask which is the correct directory before calling init.
Inputs: query.
git_commitA
Stage the named files (or all changes) and commit them with the given message. The bridge's .codex-bridge/ folder is NEVER staged — your plans and checkpoints stay out of the commit history. Call ONLY after the user explicitly approved the message and the files in chat. Never pushes — remotes are never touched.
Inputs: message (required), files, project, session_token.
git_diffA
git diff inside a project root (unstaged by default). Free local I/O — the review loop: ChatGPT reads this and decides next steps.
Inputs: path, cached, context, project, +2 more.
git_logB
Recent commit history (oneline) of a project root. Free local I/O.
Inputs: path, count, project, session_token.
git_statusA
Working-tree status of a project root via git. Free local I/O — the first thing to check before planning or reviewing.
Inputs: path, project, session_token.
grepA
Regex search across files under a path inside a project root. Skips hidden dirs, node_modules, .git, binaries. Free local I/O — prefer over deep_explore for locating symbols/strings.
Inputs: pattern (required), path, exclude, include, +3 more.
implementA
Run Codex (workspace-write sandbox) on the current task. Reads .codex-bridge/ plan files if present, edits the repo, runs builds/tests, fixes breakage, then appends the git diff for ChatGPT to review. The task must be a DETAILED step-by-step plan (exact files, changes, commands) — Codex executes it literally and never thinks or designs. Only call after ChatGPT has written that plan. Costs Codex usage (fixed gpt-5.6-luna).
Inputs: task (required), project, max_turns, session_token.
initA
Arm the cheap-labor workflow for this chat: approves an EXISTING project and returns the session_token every other tool needs. Call it AFTER the user @-mentions cheap-labor AND names a project, once you've resolved it and they've confirmed the exact directory in chat. If the project doesn't exist yet, ask the user where to create it and call create_project instead (it arms the session too). Never call this unless the user mentioned cheap-labor.
Inputs: project (required).
list_treeA
List the directory structure under a path inside a project root. Free local I/O — prefer over deep_explore for any directory layout question.
Inputs: path, depth, project, max_entries, +2 more.
plan_readB
Read the .codex-bridge/ handoff files (PLAN.md, SPEC.md, TASKS.md) that carry the ChatGPT → Codex plan. Free local I/O.
Inputs: file, project, session_token.
plan_writeA
Write a .codex-bridge/ plan file (PLAN.md, SPEC.md, or TASKS.md). Replaces the file's entire contents. This is the handoff: implement picks these up on its next run. Plans must be detailed step-by-step instructions (exact files, changes, commands, verification) so Codex can execute them literally without thinking.
Inputs: file (required), content (required), project, session_token.
read_fileA
Read a file inside a project root, size-capped and line-ranged. Free local I/O — prefer over deep_explore for any file-content question. Refuses binary files and paths outside the approved project.
Inputs: path (required), limit, offset, project, +3 more.
rollbackA
Restore the working tree to a checkpoint (default: the latest). DESTRUCTIVE — call ONLY after the user explicitly approved the rollback in chat. Takes a fresh checkpoint of the current state first, so the rollback itself can be undone by rolling back again.
Inputs: id, project, session_token.
run_commandA
Run a verification command (tests, build, typecheck) in a project. Read-only commands run directly (free). Risky commands (writes, network, git mutations, interpreter one-liners) are delegated to Codex, which runs them under its auto-review approval (Codex's own risk assessment decides — never full access, no user interruption). No shell — pass the executable and args separately.
Inputs: command (required), args, project, timeout_sec, +1 more.
task_updateA
Update a task's status in .codex-bridge/TASKS.md (todo / in-progress / done / blocked). Matches by substring. Errors if the task line isn't found — TASKS.md is authored via plan_write, so add tasks by rewriting the file.
Inputs: task (required), status (required), note, project, +1 more.
write_fileA
Create a NEW file directly (free — no Codex usage). Parent directories are created inside the approved project as needed. Refuses to overwrite existing files (use edit_file for changes). Content is written exactly as given. Use this for small, well-defined additions ChatGPT can make itself; delegate large multi-file work to implement.
Inputs: path (required), content (required), project, session_token.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
TDQS
Scored across 23 tools
Each tool has a distinct, clearly-scoped purpose: the free I/O tools (list_tree, read_file, grep, git_*) are explicitly separated from paid Codex tools (deep_explore, implement), and file mutation tools (write_file, edit_file, edit_pack) are distinguished by mode. Even overlapping tools like codex_reply vs implement are differentiated by their trigger conditions and intended workflow stage.
All tools follow a consistent verb_object convention (create_project, read_file, git_status, plan_write, run_command). Categories are prefixed predictably (git_, plan_, edit_, write_/read_), and even the free-vs-paid distinction is hinted at in names and descriptions. No mixing of camelCase or vague verbs.
23 tools is on the upper edge of the ideal range, but the surface is justified by the rich domain: project lifecycle, file I/O, git operations, planning handoff, and Codex integration each require their own dedicated entry points. A few are thin wrappers around each other (e.g., checkpoints vs git_log), but most serve genuinely distinct guard-checked purposes.
The tool surface covers the full workflow: discovering/initializing/creating projects, inspecting state (files, git, tree, grep), writing plans and tasks, editing files directly or via Codex, checkpointing/rollback, running verification commands, and committing. The only minor gap is lack of a project deletion/teardown tool, but the bridge explicitly avoids destructive actions beyond approved rollbacks.
Maintenance
Related MCP Connectors
Shared memory MCP server for Claude Code, Codex, Gemini CLI and Cursor. Cited, editable.
A paid remote MCP for OpenAI Codex agent coordination MCP, built to return verdicts, receipts, usage
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Team memory for AI coding agents and code reviews, reviewed by humans and served over MCP.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn MCP server that provides AI coding agents with AST-accurate, context-budget-aware codebase querying, safety gates, and team policy integration via structured tools and a local plugin layer.112 npm4MIT
- AlicenseNot gradedqualityBmaintenanceA self-hosted MCP server that enables AI coding agents to read, edit, search, and run code in local projects with human review loops and policy controls.MIT
- AlicenseAqualityBmaintenanceMCP server that enables a coordinator AI agent to spawn, control, and supervise local coding agents with interactive gating for high-risk operations.1010 npmMIT
- AlicenseNot gradedqualityDmaintenanceLocal MCP server enabling Codex and ChatGPT to read/write files, execute commands, manage processes, use Git, and inspect images on the user's machine with full privileges.Apache 2.0