A Codex port of DittoWii/cc-kimi-tmux, built on huanglune/cc-codex-tmux: a plugin and skill that lets Codex dispatch tasks to Kimi Code CLI inside visible tmux panes, collect reports through Kimi's official hooks, and resume the conversation.
cx-kimi-tmux gives Codex a visible Kimi session beside its own terminal. You can watch progress and interact with Kimi while Codex continues independent work, then let Codex pick up the completed report. Outside tmux, the same dispatcher uses Kimi's prompt mode and writes the same report artifacts.
- Visual tmux panes — real Kimi TUI in split panes or separate windows, colored borders, and pinned
cxkm:<task>labels that gain a✅on completion. Labels use the pane-scoped@cxkm_labeloption, so TUI title changes do not replace them. - Codex integration — a self-contained
kimiskill plus a native.codex-plugin/plugin.jsonmanifest. Codex can retain the dispatcher's running shell session, continue independent work, and collect its result withwrite_stdin. - Parallel dispatch — independent tasks get their own pane, brief, report path, and run lock. Assign separate files or worktrees when tasks edit the same project.
- Resume — continue a previous Kimi session with
--resume <session-id|last>, recovering its working directory when-Cis omitted. - Pane management —
list/kill <name|%id|done|all>operate on this dispatcher's registered panes. Completed panes stay available for inspection unless--closeis set. - Stop-hook delivery —
Stopdelivers a completed report,StopFailurerecords failure, andInterruptmarks the task as needing input. Hooks route by the dispatched process'sCX_KIMI_TMUX_REPORTmarker. - Unattended TUI execution — defaults to
kimi --auto, pre-seeds the selected workspace's trust marker, and verifies bootstrap submission. A startup watchdog reports failures instead of waiting indefinitely. - Environment sync — synchronizes
PATH,KIMI_CODE_HOME, and cache settings into the pane, starts the resolved Kimi executable, and clears inherited proxy variables. A trustedCX_KIMI_TMUX_ENV_FILEcan supply intentional overrides. - Headless fallback — no host tmux pane? Uses
kimi -p --output-format stream-json, preserving the report requirement. Prompt mode has its own timeout and does not receive the incompatible--autoflag. - Coexists with cc-kimi-tmux — separate hook blocks, environment markers, cache directories, and pane labels; both projects can share the same Kimi login.
- Zero build — Bash dispatcher and a Python standard-library installer. Installation validates candidate Kimi configuration, backs up changes, and supports idempotent installation and targeted removal.
- Linux or WSL; Bash ≥ 4.4
- Python ≥ 3.9; GNU coreutils, including
realpath,sha256sum, andtimeout;awk - tmux ≥ 3.2 for visible panes
- Kimi Code CLI, installed and logged in
- Codex with local skill support; native plugin installation additionally requires Codex plugin support
curlfor the optional provider connectivity check
Verified with Kimi Code CLI 0.42.0, Codex CLI 0.154.0, and tmux 3.2a. See VALIDATION.md for the test scope.
# 1. Get the code
git clone https://github.com/DittoWii/cx-kimi-tmux.git
cd cx-kimi-tmux
# 2. Install the Codex skill and Kimi completion hooks
# Links skills/kimi into ~/.agents/skills/kimi; validates and backs up
# ~/.kimi-code/config.toml before adding this plugin's marked hook block.
bash install.sh
# 3. Check dependencies, hooks, and provider connectivity
bash scripts/cx-kimi-tmux doctorStart a new Codex conversation and invoke the skill:
$kimi Review this project's error handling and write a report without changing code.
To see Kimi beside Codex, start Codex inside tmux, for example tmux new -s coding, then codex. Outside tmux, use an explicit --target %PANE or let the dispatcher fall back to prompt mode.
For a different skill location, use bash install.sh --skill-dir /path/to/.agents/skills. An existing unrelated kimi skill is preserved and reported as a conflict. Keep the checkout in place: the skill link and hooks refer to its files.
bash install.sh --hooks-only
mkdir -p ~/.local/bin
ln -s "$PWD/skills/kimi/scripts/cx-kimi-tmux" ~/.local/bin/cx-kimi-tmuxThe examples below assume ~/.local/bin is on PATH. You can also run bash /path/to/cx-kimi-tmux/scripts/cx-kimi-tmux directly.
The repository includes .codex-plugin/plugin.json and skills/ for Codex plugin packaging. If your configured marketplace publishes this plugin as cx-kimi-tmux@personal:
codex plugin add cx-kimi-tmux@personal
bash install.sh --hooks-onlyThis requires a corresponding marketplace entry; cloning the repository does not register one. The direct skill installation above works without a marketplace. With a native plugin, install only the hooks to avoid a duplicate standalone skill. The skill checks hook availability when used.
Run cx-kimi-tmux doctor and read its Provider section. Kimi working in your interactive shell does not establish that a pane inherited the same environment.
| Provider | What to check |
|---|---|
Official managed (type = "kimi") |
Kimi is logged in and its service is reachable. |
Self-hosted / third-party OpenAI-compatible (type = "openai") |
The configured base_url is directly reachable, or an intended proxy is supplied through CX_KIMI_TMUX_ENV_FILE. |
The endpoint probe is unauthenticated and always direct: HTTP 401 establishes reachability, but does not validate credentials or a model request. Add --live to send one short Kimi prompt using the launch environment. Chinese troubleshooting notes: docs/TROUBLESHOOTING.md.
Write a self-contained brief with context, allowed changes, and acceptance criteria, then dispatch it:
cx-kimi-tmux -t review -o /absolute/review.report.md -C /absolute/project --brief /absolute/review.brief.md --timeout 900| Flag | Description |
|---|---|
-t TITLE |
Task name; defaults to the report filename stem |
-o REPORT |
Final report path (required); use a unique path for each task |
-C DIR |
Kimi working directory; defaults to $PWD |
--brief FILE |
Task brief; omit to read from stdin |
--resume ID |
Continue a Kimi session; accepts an explicit ID or last |
--target %PANE |
Explicit host tmux pane; useful from the Codex app |
-w |
Use a separate tmux window |
--close |
Close the Kimi pane after delivery |
--timeout S |
Completion wait limit; 0 means unlimited. Pane mode detaches on timeout; headless mode terminates Kimi. The startup watchdog is separate. |
--allow-last-message |
If the report is missing, accept the last nonempty assistant message |
-- ... |
Extra Kimi flags, such as -m or --add-dir; prompt, session, output format, and approval flags are managed by the dispatcher |
The dispatcher checks the current tmux environment, terminal, and process ancestry to locate the host pane. If it cannot find one, it uses headless mode; --target selects an explicit pane on the tmux server in use.
cx-kimi-tmux --resume <session-id> -t followup -o /absolute/followup.report.md --brief /absolute/followup.brief.mdRead the Kimi session ID from the report footer or <report>.meta.json. Omit -C to recover the previous working directory from the dispatcher's registry or Kimi's session_index.jsonl. Use a new report path for each follow-up. Prefer an explicit ID when several tasks run; last may refer to a different task.
cx-kimi-tmux doctor # Dependencies, hooks, provider, direct endpoint probe
cx-kimi-tmux doctor --live # Also sends one short Kimi prompt
cx-kimi-tmux list # Registered tmux panes and their states
cx-kimi-tmux kill review # Close the task named review
cx-kimi-tmux kill %42 # Close a registered pane by ID
cx-kimi-tmux kill done # Close delivered panes
cx-kimi-tmux kill all # Close all panes registered by this dispatcherClosing a pane does not delete its Kimi session. These commands manage tmux panes; headless processes belong to the command session that launched them.
| Variable | Default | Description |
|---|---|---|
CX_KIMI_TMUX_MODE |
pane |
pane / window / exec |
CX_KIMI_TMUX_TARGET |
Current pane discovery | Explicit tmux target; overridden by --target |
CX_KIMI_TMUX_PANE_WIDTH |
40% |
Width of the first split |
CX_KIMI_TMUX_MAIN_WIDTH |
60% |
Main pane width under the default layout |
CX_KIMI_TMUX_LAYOUT |
main-vertical |
main-vertical / none |
CX_KIMI_TMUX_APPROVAL |
auto |
TUI: auto → --auto, yolo → -y, manual → stock interactive behavior. Headless fallback requires the default setting. |
CX_KIMI_TMUX_REQUIRE_REPORT |
1 |
Require a nonempty report; 0 permits a nonempty last-message fallback |
CX_KIMI_TMUX_CLOSE_DONE |
0 |
1 closes panes after delivery |
CX_KIMI_TMUX_TIMEOUT |
0 |
Completion wait limit; overridden by --timeout |
CX_KIMI_TMUX_ENTRY_TIMEOUT |
120 |
TUI startup and prompt-injection watchdog in seconds |
CX_KIMI_TMUX_CACHE_DIR |
${XDG_CACHE_HOME:-~/.cache}/cx-kimi-tmux |
Pane and session registries |
KIMI_CODE_HOME |
~/.kimi-code |
Kimi configuration, credentials, and session data |
CX_KIMI_TMUX_DOCTOR_LIVE_TIMEOUT |
90 |
Limit for the live diagnostic prompt in seconds |
CX_KIMI_TMUX_ENV_FILE |
Unset | Trusted shell file sourced after environment sync and proxy clearing |
Both modes clear uppercase and lowercase HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, and NO_PROXY. Supply intentional proxy or API-key exports through CX_KIMI_TMUX_ENV_FILE; keep credentials out of briefs and the repository. Set shared data paths such as KIMI_CODE_HOME in the dispatcher's environment so its own session lookup uses the same directory as Kimi.
Kimi runs with the permissions of its process. Default TUI --auto execution and workspace trust markers do not create a Codex sandbox. manual preserves interactive TUI approval; headless fallback is rejected for manual / yolo because prompt mode cannot preserve those settings.
| Code | Meaning |
|---|---|
0 |
Report delivered; .done and .meta.json are available |
2 |
Invalid arguments, startup failure, hook failure, or report delivery failure |
124 in tmux mode |
Completion wait timed out; Kimi keeps running and the hook can deliver later |
124 in headless mode |
Kimi was terminated at the configured timeout |
| Other nonzero codes | Underlying Kimi failure, passed through by headless mode |
Codex main session
│
├── writes a task brief
├── starts cx-kimi-tmux through exec_command
│ │
│ ├── pre-seeds workspace trust in auto/yolo mode
│ ├── splits a tmux pane and starts the Kimi TUI
│ ├── waits for the input box, pastes and verifies the bootstrap prompt
│ ├── Kimi completes its turn → Stop hook fires
│ │ CX_KIMI_TMUX_REPORT attributes the event to this task
│ │ report present → writes .meta.json and .done
│ └── dispatcher exits with the delivery result
│
├── continues independent work while the command session is running
└── waits via write_stdin, reads the report, resumes with the Kimi session ID
The Codex command-session ID and Kimi session ID are different identifiers. The plugin relies on Codex retaining and waiting on its shell session; it does not inject text into Codex's input box or guarantee automatic wake-up after the Codex turn has ended.
| cc-kimi-tmux | cx-kimi-tmux |
|---|---|
Claude Code skill and run_in_background |
Codex skill / plugin and a resumable shell command session |
KIMI_TMUX_*, ~/.cache/kimi-tmux, @km_label |
CX_KIMI_TMUX_*, ~/.cache/cx-kimi-tmux, @cxkm_label |
| Bash installer adds the Kimi hook block | Python installer validates candidate configuration, backs up, and atomically replaces it |
| Kimi TUI with Stop-hook delivery | Same TUI mechanism, with dispatch-marker-only hook attribution |
| Headless last-message delivery | Required report by default; last-message fallback only when allowed |
| Pane completion-wait timeout | Pane timeout detaches; headless timeout terminates Kimi |
The original tmux delegation design comes from huanglune/cc-codex-tmux. See UPSTREAM.md for the pinned Kimi-port revision and adaptation notes.
- Delivered — a completed report or explicitly allowed nonempty last message is available, with
.doneand metadata. A report file alone does not establish success. needs-input— the TUI turn ended without a required report, or the user interrupted it. Inspect the pane and resolve the blocker; a later completed turn can deliver the report.failed— startup, injection, Kimi, or finalization failed. Inspect.state,.pane.log,.entry.log, and.events.jsonlfor headless runs.pane-dead-at-entry— Kimi exited before the task started. Check the pane log for configuration or executable errors.inject-partial— only part of the bootstrap reached the input box. The dispatcher stops rather than submitting a duplicated prompt.- Timeout — pane mode leaves Kimi running; headless mode terminates it. Do not reuse an active task's report path.
Report-side artifacts include .brief, .state, .launch.sh, .latest.stop.json, .meta.json, .done, .pane.log, .stamp, .entry.log, and .events.jsonl in headless mode. <report>.run prevents simultaneous dispatches from using the same report.
- TUI input detection depends on Kimi's terminal appearance. Changes to its input box or hook payloads may require a dispatcher update.
- Concurrent new sessions in one working directory use the upstream
wire.jsonltimestamp heuristic for session discovery. Hook attribution uses the task's environment marker; verify session IDs against Kimi'ssession_index.jsonlif resume selects an unexpected conversation. - One completed turn is the delivery boundary. Write briefs that explain when to write the final report and what completion means.
- Platform coverage is Linux with the versions listed above. Native Windows and macOS are not covered by the current validation.
bash uninstall.sh
# If installed as a native Codex plugin:
bash uninstall.sh --hooks-only
codex plugin remove cx-kimi-tmux@personalOnly this project's marked Kimi hooks and its own skill link are removed. Other hooks, Kimi credentials, reports, and caches remain. If you installed with --skill-dir, pass the same option when uninstalling. Remove any standalone CLI symlink separately.
python3 -m unittest discover -s tests -v
bash -n skills/kimi/scripts/cx-kimi-tmuxThe 18 integration tests use a fake Kimi executable and make no model requests. Real headless and tmux smoke tests, plugin installation, and hook validation are recorded in VALIDATION.md.
MIT — adapted from DittoWii/cc-kimi-tmux, originally ported from huanglune/cc-codex-tmux (MIT, © huanglune). Both upstream copyright notices are preserved in LICENSE.