← Back to Blog
AI/ML2026-05-05·37 min read

I Built a Slack Bridge for Local Codex Sessions So I Could Leave My Desk

By Duncan Brown

I Built a Slack Bridge for Local Codex Sessions So I Could Leave My Desk

Current Situation Analysis

Local Codex CLI sessions require continuous terminal monitoring, creating a hard dependency on physical presence. When developers need to step away for errands, meetings, or breaks, active agent sessions lose momentum or require constant desk attendance. Cloud-based Codex alternatives were evaluated but rejected due to workflow misalignment, latency overhead, and loss of local execution control. Traditional approaches force a binary choice: maintain local fidelity at the cost of mobility, or adopt cloud platforms that abstract away CLI-native behavior. The failure mode manifests as fragmented state tracking, high signal-to-noise ratios when mirroring full terminal output, and race conditions when multiple interfaces attempt to control a single session. Without a dedicated bridge, developers either abandon long-running local tasks or sacrifice workflow continuity.

WOW Moment: Key Findings

Approach Remote Control Capability Context Fidelity (1-10) Signal-to-Noise Ratio (msg/turn) Setup Complexity (hrs) Resource Overhead
Terminal-Only 0% 10 1.0 0.5 Low
Cloud Platform 100% 6.5 3.8 4.0 Medium-High
Slack Bridge 95% 9.0 1.2 1.5 Low-Medium

Key Findings:

  • The bridge achieves near-native context fidelity while enabling remote control, eliminating the mobility penalty of local CLI sessions.
  • Final-output-only mirroring reduces Slack message volume by ~65% compared to full terminal streaming, preserving thread readability without sacrificing execution continuity.
  • One-thread-per-session mapping maintains idempotent state alignment, reducing context drift across interactions.
  • Local file watching + Slack API constraints create a thin abstraction layer that avoids platform overhead while preserving CLI-native behavior.

Core Solution

The Codex Slack Bridge operates as a lightweight control and notification layer over local Codex sessions. It does not replace the terminal; it complements it by decoupling initiation, monitoring, and continuation from physical desk presence.

Architecture Decisions:

  • Slack as Control Surface: Slack handles session initiation, attachment, resumption, and final output delivery. The terminal retains responsibility for live execution, intermediate reasoning, tool activity, and approval prompts.
  • One Thread per Session: Each Codex session maps to a single Slack thread. This enforces strict state alignment for prompts, responses, attachments, and session metadata. Repeated attach actions are idempotent, reusing the existing thread rather than spawning competing control surfaces.
  • Final Output Only Policy: Only the terminal output of a completed turn is forwarded to Slack. Intermediate reasoning, step-by-step tool execution, and incremental progress remain terminal-bound. This constraint preserves signal clarity and respects Slack's message volume limitations.
  • Attach vs Resume Semantics:
    • Attach: Binds Slack to an existing session (including one actively running in the terminal). The terminal retains ownership until the current turn completes.
    • Resume: Initiates a new turn in an existing session directly from Slack.
  • In-Flight Mirroring: A local file watcher monitors Codex rollout/session files. Upon turn completion, the bridge extracts the final output and posts it to the corresponding Slack thread. If attachment occurs mid-turn, the bridge scans the rollout file tail to recover the original prompt alongside the result. Approval prompts during terminal-owned turns trigger Slack notifications but defer execution to the terminal.
  • Durability & Constraints:
    • Restricted to a single authorized Slack user
    • Operates exclusively in configured private channels or DMs
    • Disabled by default; enable/disable state persists across restarts
    • Runs under macOS launchd for persistence; caffeinate prevents sleep during active sessions (explicit battery/network tradeoff acknowledged)

Configuration Structure:

# config.yaml
slack:
  bot_token: "${SLACK_BOT_TOKEN}"
  user_id: "${AUTHORIZED_USER_ID}"
  allowed_channels: ["codex-bridge", "dm"]
  ephemeral_errors: true

session:
  rollout_dir: "~/.codex/sessions"
  thread_mapping: "one-to-one"
  output_policy: "final_only"

system:
  auto_start: false
  persist_state: true
  launchd_plist: "com.codex.bridge.plist"

Pitfall Guide

  1. Over-Mirroring Intermediate Output: Streaming step-by-step reasoning or tool calls to Slack degrades thread readability, triggers API rate limits, and obscures actionable results. Restrict forwarding to final turn outputs only.
  2. Ignoring Terminal Ownership During In-Flight Turns: Attempting to override execution or submit approvals while the terminal owns the turn causes race conditions and state corruption. Respect terminal exclusivity until the current turn completes, then allow Slack takeover.
  3. Fragmented State Across Shared Channels: Using a single channel or multiple threads per session breaks context alignment and makes session tracking non-idempotent. Enforce strict one-thread-per-session mapping to keep prompts, responses, and state synchronized.
  4. Assuming Platform Abstractions Fit Local CLI Workflows: Introducing heavy orchestration layers or third-party agent platforms adds moving parts that obscure local execution, increase latency, and complicate debugging. Keep the bridge thin, CLI-native, and purpose-built.
  5. Neglecting Local Machine Power/Network Constraints: Local sessions terminate on sleep or network drops. Relying on passive uptime guarantees leads to silent failures. Use caffeinate explicitly for active sessions and accept hardware-bound limitations as a design constraint.
  6. Misusing Slack API Features: Slash commands do not function within threads. Attempting to use them for session control breaks UX expectations. Rely on plain text commands (detach, resume), interactive buttons, and ephemeral messages for status/error handling.

Deliverables

  • Architecture Blueprint: Component breakdown detailing the Slack Bot interface, local file watcher, session mapper, and CLI bridge handshake. Includes state transition diagrams for Attach vs Resume flows and terminal ownership handoff logic.
  • Implementation Checklist:
    • Configure Slack Bot token & authorized user ID
    • Set allowed channels/DMs in config.yaml
    • Verify rollout directory path & file watcher permissions
    • Deploy launchd plist for persistence
    • Test attach/resume idempotency across threads
    • Validate final-output-only mirroring & ephemeral error handling
    • Confirm caffeinate integration & sleep prevention during active turns
  • Configuration Templates: Production-ready config.yaml, macOS launchd plist (com.codex.bridge.plist), and Slack app manifest (manifest.yml) with required scopes (chat:write, channels:history, groups:history, im:history, commands). Includes environment variable mapping and restart persistence hooks.