Skip to main content
Glama


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 + client

  • Validation: zod — tool argument schemas

  • Executor: Codex CLI (codex mcp-server) — spawned child MCP client for exploration and implementation

  • Connectivity: 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 PATH

  • A 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

  1. Clone the repo and move into it:

    git clone https://github.com/psrisuphan/cheap-labor.git
    cd cheap-labor
  2. Run 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

  1. Start the tunnel — keep it running while you use cheap-labor:

    ./scripts/tunnel.sh start    # stop: ./scripts/tunnel.sh stop
  2. Open a new ChatGPT chat and type @cheap-labor (or whatever you named the app/plugin when creating it).

  3. Confirm the project directory when asked — the session is armed.

  4. 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.sh

Cleans 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:

  1. The user invokes cheap-labor by typing @cheap-labor. That's the only trigger.

  2. ChatGPT asks which project you want, resolves it (find_projects for fuzzy names, create_project for new directories), confirms the exact path with you, then arms the session — init(project) (or create_project directly for a brand-new directory) and receives a session_token.

  3. Every other tool refuses to run without a valid session_token — a hard backstop that also blocks accidental use outside the workflow.

The Workflow

  1. Arm the session — @cheap-labor + confirm the project → init returns the token.

  2. Understand — git_status, list_tree, read_file, grep (all free).

  3. Plan in detail — ChatGPT writes PLAN.md / SPEC.md / TASKS.md into the repo's .codex-bridge/ folder with plan_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.

  4. Small edits, done directly — write_file / edit_file handle one-file changes for free.

  5. Delegate heavy work — implement hands the plan to Codex, which executes the steps literally, runs builds/tests, fixes what breaks, and returns IMPLEMENTATION COMPLETE.

  6. Review — ChatGPT reads the returned git diff and sends targeted corrections back through the same loop.


Features

  • One-Trigger Activation: @cheap-labor in 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 with set_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

init

Arm the session for a project (the single entry point); returns the session_token + an operation-mode brief

list_tree

Directory structure, depth-limited

read_file

File contents, line-ranged, size-capped, secrets redacted (redact_secrets: false to disable)

grep

Regex search with path-aware include/exclude globs (*.ts, src/**/*.ts), secrets redacted (redact_secrets: false to disable)

git_status / git_diff / git_log

Repo state + the review loop (untracked files surfaced)

run_command

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 (redact_secrets: false to disable)

set_approval_mode

Switch the global approval mode — normal (ask first) or auto (ChatGPT judges safe commands itself); dangerous commands always ask

get_settings

Read current bridge settings (e.g. the approval mode)

write_file

Create a new file directly (refuses to overwrite)

edit_file

Exact-match edit of an existing file (content-based stale guard)

edit_pack

Batch edits/writes after validating every guard before application

checkpoint

Snapshot HEAD + working tree for rollback (auto before implement)

rollback

Restore to a checkpoint (user-confirmed; itself undoable)

git_commit

Stage + commit locally with a user-approved message; refuses existing staged work and never pushes

checkpoints

List recorded checkpoints

find_projects

Resolve fuzzy names to candidate paths (shallow, well-known locations)

create_project

Create a new project directory (no git init); returns a session_token

plan_read / plan_write / task_update

Manage .codex-bridge/ handoff files

Codex-backed tools (spend the Codex pool):

Tool

Purpose

deep_explore

Read-only Codex session for questions free tools can't answer (model upgrade per-call with your confirmation)

implement

Workspace-write Codex on the current plan; returns summary + git diff (model upgrade per-call with your confirmation)

codex_reply

Continue a session by thread id (approval veto loop, follow-ups); bound to the project that created it


Safety Model

  • implement / deep_explore always pass an explicit sandbox (workspace-write / read-only) — never danger-full-access.

  • Fixed Codex model — every Codex call pins gpt-5.6-luna with medium reasoning and Fast Mode off, passed as per-call overrides. The bridge never writes to ~/.codex/config.toml. The one exception: implement / deep_explore accept a stronger model (e.g. gpt-5.6-sol), but the bridge refuses it unless the call passes model_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 auto mode too — and recorded so ChatGPT relays them to you for a veto. The veto is executed with codex_reply.

  • Approval modes — run_command buckets 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 without approved: true. Everything else follows the mode: normal (default) asks you first; auto lets ChatGPT judge safe commands itself but still makes it ask you for dangerous ones. Change it any time with set_approval_mode — it applies to every chat immediately.

  • write_file only creates new files; edit_file only edits existing ones via exact-match replacement (stale/ambiguous matches write nothing); edit_pack validates the full batch before applying it. All cap sizes and refuse binary files.

  • Ship mode — checkpoint snapshots HEAD + working tree (taken automatically before every implement); rollback restores a checkpoint (itself undoable); git_commit refuses 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_command redact known secret patterns by default; pass redact_secrets: false when 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.json

Testing

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 — the tunnel-client profile (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 tools
checkpointA

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

    A4.1/5.0

    Scored across 23 tools

    Disambiguation5/5

    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.

    Naming Consistency5/5

    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.

    Tool Count4/5

    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.

    Completeness5/5

    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

    ActivityInactive
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      An 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 npm
      4
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      A 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
    • A
      license
      A
      quality
      B
      maintenance
      MCP server that enables a coordinator AI agent to spawn, control, and supervise local coding agents with interactive gating for high-risk operations.
      10
      10 npm
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Local 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