Skip to content

Repository files navigation

中文 | English

CodeCLI

Unified session orchestrator for terminal-based AI coding tools.

CodeCLI wraps Claude Code, Cursor Agent, OpenAI Codex CLI, OpenCode, and Bash into one control layer. Run multiple AI sessions simultaneously and manage them from your local terminal, Telegram, WeChat, an HTTP bridge, or a LangChain tool — all sharing one command system.

Why CodeCLI?

When you run multiple AI CLIs at once, things get messy fast:

  • Switching between terminal windows for different tools
  • Can't see session status remotely
  • A tool is stuck on a y/n confirmation and you're not at your desk
  • TUI output is noisy and hard to read in messaging apps
  • No unified way to manage sessions across tools

CodeCLI solves this by putting all your AI sessions behind one command interface, accessible from anywhere.

Supported Tools

Tool Command Default Executable
Claude Code /claude [cwd] claude
Cursor Agent /cursor [cwd] agent
OpenAI Codex CLI /codex [cwd] codex
OpenCode /opencode [cwd] opencode
Bash /bash [cwd] [cmd] bash

CodeCLI does not install these tools — you install them yourself, and CodeCLI launches, manages, and orchestrates them.

Channels

Channel Command Use Case
Local CLI python main.py cli Direct terminal access
Telegram python main.py telegram Remote control from your phone
WeChat python main.py weixin Remote control via WeChat (QR login)
HTTP python main.py http API bridge for external systems
Embedded Tool / LangChain create_tool_adapter() In-process agent integration

All transports use the shared message router, with channel-specific capabilities and delivery behavior. python main.py tool is a lifecycle mode, not a standalone RPC service.

Quick Start

Requirements: Python 3.10+, at least one AI CLI tool installed.

# Clone the repository
git clone https://github.com/ax128/CodeCLI.git
cd CodeCLI

# Install dependencies
pip install -r requirements.lock   # pinned for reproducible installs
# or: pip install -r requirements.txt

# Create runtime config (required)
cp config/codecli.example.json config/codecli.json

# Run locally
python main.py cli

# Start a Claude session
/claude /path/to/project

# Send a task
Review this project and list potential issues

# Check status
/status

# See output
/output

Remote via Telegram

  1. Create a bot with @BotFather and get your token
  2. Copy config: cp config/codecli.example.json config/codecli.json
  3. Pick a Telegram config name <name> (e.g. agent) and set default_channel.chat to <name>
  4. Set channels.telegram.<name>.enabled=true and configure botToken
  5. If chatId is empty, run python main.py telegram and send any message to the bot within 120s — CodeCLI discovers and saves the chat ID
  6. Optional: set channels.telegram.<name>.bindToken (or bindTokenEnv) to require sending /bind <token> instead, so a third party can't bind the bot first during discovery
  7. To enable /file, set fileTransferPassword to a strong non-placeholder value; an empty value disables file transfer

Remote via WeChat

python main.py weixin
# First run: QR code is drawn in the terminal (install deps first: pip install -e .[weixin], or pip install Pillow qrcode), then scan with WeChat; credentials saved automatically
# Subsequent runs: connects directly

Or login separately: python -m cli_orchestrator.weixin_login

WeChat uses a compact mobile /help view by default. Use /help cursor for Cursor-specific advanced commands.

Note: the WeChat channel is text-only (no images/files/voice).

Remote via HTTP bridge

  1. In config/codecli.json, set channels.http.<name>.enabled=true
  2. Configure either a strong inline authToken or an authTokenEnv whose environment variable is set; leave authTokenEnv empty when using the inline token
  3. Run python main.py http (uses default_channel.http) or python main.py http:<name>
  4. POST messages and poll events (default template uses 127.0.0.1:8787, /message, /events; auth via X-CodeCLI-Token or Authorization: Bearer ...):
# Send one message
curl -sS -X POST "http://127.0.0.1:8787/message" \
  -H "Content-Type: application/json" \
  -H "X-CodeCLI-Token: <authToken>" \
  -d '{"sender":"alice","text":"/status"}'

# Poll events (drains the queue for that sender)
curl -sS "http://127.0.0.1:8787/events?sender=alice" \
  -H "X-CodeCLI-Token: <authToken>"

Responses: POST /message returns {"ok": true, "accepted": true, "channel_key": "..."} and GET /events returns {"ok": true, "events": [{"text": "...", ...}]}.

Undelivered events are capped per sender by maxEventsPerSender (default 100; oldest are dropped once the cap is hit). Set eventsStorePath to persist the queue across restarts; leave it empty for memory-only events. Delivery is best effort: in-memory pending replies, event queues, and ephemeral sender registrations are bounded and may be discarded after expiry, capacity pressure, channel shutdown, or repeated transport failure.

Server Deployment

./start.sh telegram        # Run as background daemon with Telegram
./start.sh weixin          # Run as background daemon with WeChat
./start.sh                 # Use default channel from config

The Bash/Linux script starts a new instance with nohup, writes its PID plus Linux process-start token under logs/, and tails logs/codecli.out. It only stops the process recorded by this checkout when /proc confirms its working directory, exact Python argv, and stored start token. If identity cannot be verified, the script exits without deleting the PID file or starting a duplicate. Press Ctrl+C to detach; CodeCLI keeps running.

Key Features

Multi-session management — Run multiple AI sessions in parallel, switch between them with /use <id>, send to a specific session with /1 text.

Clean output delivery — TUI chrome, ANSI codes, spinners, and box-drawing characters are stripped. Telegram and WeChat remote chat channels deliver final results by default, while HTTP keeps explicit request/response acknowledgements.

Output mode controlresult mode (default) delivers only completed output. stream mode delivers incremental updates. Automatic policy switches to stream for long-running tasks like test suites.

Key injection/enter, /esc, /tab, /y, /n, /key ctrl+c — handle confirmations and navigate TUI tools remotely.

State detection — Automatically detects running, idle, completed, need_confirmation, error, stopped.

Cross-channel ownership — Sessions track which channel started them. Use /handoff and /claim to transfer ownership between channels.

Message verification gate — Optional password protection with configurable TTL and startup grace period.

LangChain integration — Use CodeCLI as a LangChain Tool or LangGraph ToolNode, with structured responses including status_hint, next_suggested_commands, and normalized session state.

Quick Command Reference

The table below is a summary. See the complete command reference for aliases, Cursor advanced commands, channel differences, and error behavior.

Category Commands
Start /claude, /cursor, /codex, /opencode, /bash, /start <cmd>
Send direct text, /1 text, /send [id|#id] [--output result|stream] <text>, /send [id] -- <text>
Confirm /y, /n, /enter, /esc, /tab, /key <name>
Monitor /status, /output, /screen, /logs, /watch, /list, /all
Mode /mode [id] [result|stream]
Manage /use <id>, /stop, /stopall, /kill <id>, /restart
Paths /cd, /pwd, /ls [--all] [path], /paths, /cat <file>
Ownership /owner, /handoff, /claim
System /ping, /info, /help, /reboot, /exit

All commands with [id] default to the active session when omitted.

Configuration

cp config/codecli.example.json config/codecli.json

config/codecli.json is required for all modes. Telegram and HTTP channels will not start unless their enabled flag is set to true (HTTP also requires a strong non-placeholder token from either authToken or authTokenEnv).

Key sections in config/codecli.json:

Section Purpose
default_channel Which channel starts by default
channels.telegram Bot token, chat ID, file transfer password
channels.weixin WeChat token, account ID (auto-filled by QR login)
channels.http HTTP bridge bind address, port, auth token
cli_path Override executable paths for each tool
security.verification Optional message password gate
output_policy.rules Custom automatic output mode rules
worked_path Saved directory aliases (p1, p2, ...)

See config/codecli.example.json for the full template.

LangChain / Tool Integration

LangChain is optional and not included in requirements.txt / requirements.lock. Install it before using create_langchain_tool(...) (e.g. pip install langchain pydantic).

from cli_orchestrator import create_langchain_tool

tool = create_langchain_tool(response_format="content")
result = tool.invoke({"message": "/claude /workspace/project"})
print(result["reply_text"])
print(result["active_session"])

For LangGraph ToolNode, use response_format="content_and_artifact". See the embedded Tool API contract for the complete structured response and best-effort delivery limits.

Documentation

Architecture

Chat routes all channel messages into a shared command/session layer. SessionManager owns lifecycle and ordered notifications. Provider adapters select either structured headless subprocesses (Claude, Cursor, Codex, OpenCode) or PTY transport (primarily Bash and custom commands). Channel capabilities and known compatibility leftovers are detailed in the architecture document.

Development Checks

Install the optional development toolchain first:

pip install -e ".[dev]"

Then run the checks appropriate to your change:

python -m compileall cli_orchestrator      # Compile check
python -m pip check                        # Dependency check
python -m mypy cli_orchestrator            # Static type check
python -m pytest                           # Test suite

The full verification gate (used before a release) is:

python -m compileall -q cli_orchestrator
python -m mypy cli_orchestrator
python -m pytest --cov=cli_orchestrator --cov-report=term
pip-audit -r requirements.lock
python -m build

The test suite under tests/ documents the intended behavior contract (commands, channels, process wrappers, security boundaries).

Security Notes

  • Never commit config/codecli.json — it may contain real tokens and passwords
  • config/codecli.example.json is the safe template for version control
  • Treat logs/ and sessions/ as local runtime data, not release artifacts
  • The message verification gate adds optional password protection for remote channels
  • The embedded Tool API bypasses the message gate (designed for in-process programmatic access)
  • Leave Telegram fileTransferPassword empty to disable /file; never use CHANGE_ME
  • Claude sessions launch with --permission-mode acceptEdits plus an explicit --allowedTools allowlist (Read,Write,Edit,Glob,Grep,Bash,WebFetch) rather than bypassPermissions. Anything outside the allowlist still triggers a confirmation prompt, which CodeCLI surfaces as need_confirmation. The list is defined once in cli_orchestrator/tools/claude.py (CLAUDE_ALLOWED_TOOLS) and shared by the interactive launch, print mode and the session process — narrow it there if you want a stricter policy.
  • WeChat token can be supplied out-of-band via channels.weixin.<name>.tokenEnv (name of an environment variable), same as authTokenEnv for the HTTP channel

License

MIT License. See LICENSE.

About

Unified orchestrator for AI coding CLIs — manage Claude Code, Cursor, Codex & OpenCode sessions from terminal, Telegram, WeChat or HTTP. Multi-session, multi-channel, one command system.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages