Skip to content

Latest commit

 

History

1,146 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mekugi

A mekugi is the small peg that pins a Japanese sword's handle to the blade. Take it out and the handle comes off. Leave it in and the blade is still the blade.

Mekugi adds compact, recoverable tools and live subagent activity to stock Codex. Codex keeps editing, execution, the sandbox, permissions, command sessions, and patch review. No fork, no config edits, no daemon.

Features · Install · Usage · UI · Metrics · Configuration · Documentation

Features

Agent-facing

  • Fewer tokens and round trips. Session helpers offer bounded and batched reads, semantic symbol lookup, and structural outlines.
  • Recoverable output and changes. Continue omitted output without rerunning, and review, revert, or reapply captured edits by ID. Gaps in coverage are labeled.
  • Leaner instructions. Omit marked instruction blocks for the session without changing instruction files or unmarked policy.
  • Duplicate-output references. Repeated tool-output text in model input uses references to earlier visible output by default in Mekugi mode. Disable with --duplicate-output=false. Full host results, retained evidence, and the UI stay intact; see the projection contract.
  • Task journal. Record plans, results, constraints, and blockers as durable work state, rather than repeating status summaries in conversation.
  • Session continuity. Retained journal and change evidence survives resume, forks, side threads, and compaction, subject to storage retention.
  • Custom tools. Extend the agent's capabilities with your own JavaScript tool plugins.

User-facing

  • Auto resume accidental stop. Continue unfinished journal work when the agent stops, including after answering a follow-up. Explicit user stops, blockers, and pending questions are respected. See the Journal pane.
  • Native terminal UI. Main, Diff, Activity, Journal, and Agents share one terminal without an external pane manager.
  • Task journal. Plans, results, and blockers stay visible without extra model requests for status reports. Work established complete by the final tool result needs no separate model-generated completion acknowledgment. See the Journal pane.
  • Live subagent activity. See model, effort, progress, and message excerpts in Main or the Agents pane, alongside elapsed time and edit activity.
  • Live diffs. Inspect streaming previews and saved edits; click an Edit event to open its captured file and hunk.
  • Readable command output. Open searchable retained output. With mekugi-exec, supported Bash and Linux dash-backed sh command lists show each command's streamed output, exit status, and timing. Markdown file links open local source in the same dialog. Supported single commands and pipelines, including Bash timed commands, show measured command time excluding startup and matching.
  • File, directory and skill attachments. Send selected contents or a bounded directory tree directly without a separate agent read; unreadable or oversized attachments have explicit notices.
  • Composer additions. Mention selected messages or diffs, and ask /btw side questions without interrupting Main.
  • Usage, throughput and cost. See per-thread usage and estimated API costs in Agents, with output tokens/sec in Main's composer and child-agent rows, plus launch-wide average throughput, usage coverage, retries, and diagnostics in /session.
  • Other providers and tiers. Use Grok or OpenCode Go and Zen, and choose service tiers.
  • Diagnostics. Inspect past sessions, record debug evidence, or replay the UI offline with CPU and heap profiling.

Bounded output and leaner instructions aim to reduce tokens and round trips; these savings don't guarantee better results on every task. For controlled comparisons, use codex-setup-ab.

Install

Requirements:

  • Codex CLI for tool execution in every launch mode.
  • For configured JavaScript plugins only: Node.js 24+ as node. Plugins declaring regex grammars also require ripgrep as rg on the router's PATH.
  • Built-in frontends need neither Node.js nor Bun; semantic lookup requires the language servers listed under agent-facing tools.
  • Any interpreter your agent picks, such as python3, on the executor's PATH.

Release binaries

Download an archive from GitHub Releases. Each archive includes mekugi and mekugi-exec; Go and a C toolchain are not needed.

Platform Archive Minimum OS
Linux x86-64 mekugi_linux_amd64.tar.gz glibc 2.39, such as Ubuntu 24.04
Linux ARM64 mekugi_linux_arm64.tar.gz glibc 2.39, such as Ubuntu 24.04
macOS Apple Silicon mekugi_darwin_arm64.tar.gz macOS 15

For example, install the Linux x86-64 release into ~/.local/bin:

(
  set -eu
  mekugi_install_tmp=$(mktemp -d)
  trap 'rm -rf "$mekugi_install_tmp"' EXIT
  cd "$mekugi_install_tmp"
  curl -fLO https://github.com/yusing/mekugi/releases/latest/download/mekugi_linux_amd64.tar.gz
  curl -fLO https://github.com/yusing/mekugi/releases/latest/download/SHA256SUMS
  sha256sum --ignore-missing -c SHA256SUMS
  tar -xzf mekugi_linux_amd64.tar.gz
  mkdir -p "$HOME/.local/bin"
  install -m 755 mekugi mekugi-exec "$HOME/.local/bin/"
)

Use the archive for your platform. On macOS, verify it with shasum -a 256 --ignore-missing -c SHA256SUMS instead of sha256sum. Add ~/.local/bin to your PATH if needed. Installing replaces both binaries at that destination. Linux releases need glibc and do not run on stock Alpine Linux; use a source build for other environments.

Build from source

Source installs require Go 1.27+, CGO enabled, and a C toolchain:

go install github.com/yusing/mekugi/cmd/mekugi@latest github.com/yusing/mekugi/cmd/mekugi-exec@latest

Add $GOBIN, or $(go env GOPATH)/bin if that is unset, to your PATH.

From a checkout with Make, run make install. It regenerates the optional plugin shared core and installs mekugi and mekugi-exec. make uninstall removes only those binaries. Running sessions keep their worker executable, so start a new session to pick up an update.

Usage

Start Mekugi

Choose a mode and authenticate with the provider it uses:

Launch Models Authentication
mekugi Authenticated third-party providers, using grok: and opencode*: IDs Grok credentials or OpenCode API keys; no Codex login
mekugi grok Grok only, using plain IDs such as grok-4.7 Grok credentials; no Codex login
mekugi codex Codex only, no third-party models codex login with ChatGPT authentication

Standalone mode fails at startup if no third-party provider has credentials. Its default uses Grok's model selection when authenticated, otherwise the first available OpenCode Go model, then Zen.

Mekugi opens its terminal workspace. Codex's configured approval and sandbox policy applies, and Mekugi also asks before remote repository writes; see Approvals. Add --yolo to disable Codex approvals and sandboxing; Mekugi's remote-write guard stays enabled. The guard requires unsandboxed command execution: configure sandbox_mode="danger-full-access" or use --yolo. Use --vcs-guard=false to disable the guard while retaining Codex's configured approval and sandbox policy.

Mekugi flags go before codex, grok, or standalone Codex arguments. Interactive launches accept --yolo, model and config options, and resume, resume THREAD_ID or resume --last; enter prompts in the UI. Noninteractive commands keep their ordinary Codex arguments and output:

mekugi exec "Explain this repository"

Launch behavior and limits

Independent sessions can run side by side. Ctrl-C during startup cancels the launch. On UI exit, Mekugi prints commands to resume with the original options or replay offline. Noninteractive commands retain Codex's exit status.

  • There is no standalone router or daemon. Fixed ports, custom provider endpoints, and --oss are not supported.
  • OpenAI sessions need secure WebSockets to ChatGPT. Mekugi falls back to HTTP only when ChatGPT explicitly rejects the upgrade, and never silently replays a request.
  • Grok and OpenCode requests use HTTP and their own credentials. Third-party credentials do not enable those providers in mekugi codex.
  • Mekugi-mode sessions require a model with Codex's JavaScript exec interface. Mekugi forces that interface for the invocation; unsupported models fail before inference.
  • Invocation-only overrides disable the plan tool and collaboration-mode instructions, route gpt-5.6-terra to gpt-6-sol, and select standard cybersecurity safeguards rather than Daybreak. No configuration files change.
  • Private replay records include tool inputs and change evidence. Native Codex tracing also records prompts and responses in a temporary directory with no disk cap; it is removed at shutdown, but a forced kill can leave it behind.

Approvals

Without --yolo, Codex's command, edit, and permission approval requests open a dialog above Main's composer with Codex's offered approval scopes, including session, command-prefix, or permission grants when available. It opens by itself only over an empty composer; otherwise a banner waits until you press Ctrl-B, then q. Number keys choose while the reason is empty; arrows choose, Enter confirms, and Esc hides the dialog without answering.

For command approvals in Mekugi mode, typing or pasting selects denial and edits an optional reason; Enter confirms. Your composer draft and attachments stay parked and return when the dialog closes. Hiding and reopening keeps the reason. Questions and approvals share the dock, so only one is open at a time. The model receives the native command rejection and your feedback in the current turn, without a new prompt or turn. Edit and permission choices stay unchanged. Proxy-free direct UI and passthrough retain Codex's original decisions without typed denial reasons.

In interactive UI launches, Mekugi asks before remote repository writes reached through guarded shell commands by default, independently of Codex's approval policy, including with --yolo. Disable only this guard with mekugi --vcs-guard=false codex or mekugi --vcs-guard=false for standalone mode. Command tracking remains enabled. Headless and noninteractive commands have no guard. Guarded writes include:

  • git push to any remote, including tag and mirror pushes, plus git send-email, git svn dcommit, git p4 submit, and Git LFS pushes and locks
  • gh commands that change GitHub state; unrecognized gh commands count as writes
  • hg push and hg email; svn commit, import, lock, and commands that change a repository URL directly, such as svn copy ^/trunk ^/tags/v1
  • jj git push and jj gerrit upload; unrecognized jj commands, including aliases, count as writes

Git aliases, git submodule foreach, rebase --exec, and bisect run scripts are checked before they run. Read-only commands such as git fetch or gh pr view run without asking.

The guard offers approval once, approval for this exact command and workdir for the UI session, or denial with an optional typed or pasted reason. Session approval matches the expanded argument list, workdir, and resolved executable; it also releases identical requests already waiting. It grants no command-prefix permission and expires when the UI closes, including before a resumed launch.

If you deny it, don't answer within 5 minutes, or the approval connection is blocked or unreachable, only that command fails, with exit status 1; the shell continues as it would after any failure. A user denial reports your supplied reason, or that no reason was given, on stderr. The denied command never runs. This shell exit status belongs to the guard; native Codex approval denial remains a tool rejection. If the command stops while waiting, its request is withdrawn. For example, git add -A; git commit -m msg; git push origin main; git log still runs git log, while the same list joined with && stops at the push.

Git subcommands that are neither built in nor aliases, such as git subtree push or a third-party git-* command, also ask, since they can push out of the guard's sight. A tool whose own write runs another guarded tool, such as gh pr create pushing your branch, asks again for that inner command.

The guard needs the default --mode mekugi, mekugi-exec installed beside mekugi, Codex's native command-hook support, and unsandboxed command execution (sandbox_mode="danger-full-access" or --yolo). Sandboxed execution is unsupported. Mekugi never silently changes Codex's approval or sandbox policy. It keeps Codex's selected shell, including Bash, sh and zsh. Direct commands and supported wrappers such as env, command, exec, xargs and timeout are guarded by name or by absolute or relative executable path, including paths with spaces and expanded paths such as "$tools/git". Nested shell -c commands are checked after their payload expands. Shell arguments, sandbox permissions and command sessions remain Codex-owned.

Before each new user turn, Mekugi verifies that the guard hook is enabled and trusted. A missing guard or a competing trusted synchronous shell hook blocks the turn with an explanation and preserves your draft. Explicit CLI overrides of hooks or hooks.PreToolUse conflict with the enabled guard and prevent launch. User configuration files are unchanged.

This is protection against accidental remote writes, not a process sandbox. It does not comprehensively intercept executable words computed entirely at runtime, eval, env -S payloads, sourced files, script files, or arbitrary programs that internally execute absolute VCS paths. Bash/zsh startup guards provide additional PATH and known-absolute-path coverage inside scripts, but these limits still apply. Hook failures outside Mekugi's handler follow Codex's failure policy and need not block execution. See the execution contract.

Headless slice plans

The headless --yolo subcommand reads one prompt from stdin and runs a new session to completion, continuing unfinished journal work and any planned slices:

mekugi --journal-compaction=slice headless --yolo < prompt.txt

Use off to continue slices in one context, or slice to reset between them. Unlike the UI, headless journal continuations have no countdown delay. It accepts model and -c options, not resume or positional prompts. Prompts must be nonempty and at most 16 MiB. Unlike the UI, it requires explicit --yolo. It does not answer approval or user-input questions: those end the run with an error rather than hanging or guessing. Ctrl-C stops the run.

Stdout is JSONL containing host app-server messages and namespaced Mekugi reset and completion events. Diagnostics go to stderr. The event stream includes prompt, tool and answer content; it is session evidence, not sanitized metrics. A nonzero exit means the run or its shutdown failed. Ordinary codex exec is unchanged.

Options

Flag Default Purpose
--ansi-faint auto Dimming: auto detects mosh ancestry, on uses ANSI faint, off uses fixed muted colors
--mode mekugi Use passthrough with mekugi codex to forward traffic without Mekugi tools or plugins
--vcs-guard true Ask before remote VCS writes in the UI, even with --yolo; false disables only this guard
--post-compact-recovery true Use false to skip the post-compaction context hook
--journal-compaction off Experimental auto uses journal summaries without a provider request; slice resets only between planned slices
--duplicate-output true Use duplicate-output references in model input; --duplicate-output=false disables them; full results and evidence stay intact; no effect in passthrough
--grok-auth-file ~/.grok/auth.json Select a Grok OAuth credential store
--timeout 10m Wait for the upstream response to start
--stream-idle-timeout 4m Limit gaps between provider messages during an active response, or HTTP response bytes
--capture-output PATH Disabled Append sanitized JSONL metrics
--debug Disabled Record diagnostics, capture, metrics, forwarded instruction/tool snapshots, runtime reads, and an AX report; print a session diagnosis command on exit

mekugi --mode passthrough --vcs-guard=false codex forwards traffic only. It doesn't need Node.js, and capture still works. Interactive passthrough can't guard remote writes, so it requires --vcs-guard=false and retains Codex's configured approval and sandbox policy.

If a detached multiplexer hides your mosh connection, use mekugi --ansi-faint=off codex for readable dimmed text. The setting applies only to that invocation and does not modify terminal configuration.

Grok models

Authenticate with grok login --oauth, or set XAI_API_KEY in the router's environment; an API key takes precedence. Codex credentials are never sent to Grok.

mekugi grok -m grok-4.7
mekugi -m grok:grok-4.7

The default follows [models].default in ~/.grok/config.toml, falling back to the latest standard model, currently grok-4.7. An explicit -m or -c model=... takes precedence. Standalone mode adds the grok: prefix to this default; mekugi grok uses plain IDs. The old --grok flag is not supported.

Subagents use the same IDs as their launch mode: grok-4.5, grok-4.6, grok-4.7, or grok-4.7-build-fast, prefixed with grok: in standalone mode. Use fresh context (fork_turns="none"). Build Fast requires Grok OAuth, not an API key. Grok can't read encrypted OpenAI history, so switching an existing OpenAI conversation to Grok isn't supported. See the Grok requirements.

OpenCode Go and Zen

Set an API key here or in Mekugi settings:

OPENCODE_GO_API_KEY='your-key' mekugi -m opencode-go:glm-5.3
OPENCODE_ZEN_API_KEY='your-key' mekugi -m opencode-zen:kimi-k3

Models, reasoning controls, and prices refresh from an hourly cache. The model picker updates on the next launch. See the provider contract.

OPENCODE_API_KEY overrides both service keys from the settings file. Per-service variables override it and any file keys; an empty per-service value disables that service.

UI

Every interactive launch lays out Main, Diff, Activity, Journal, and Agents panes in one terminal without an external pane manager. Main holds the conversation and composer. Inline Markdown code uses content-detected syntax colors; unrecognized spans stay plain with an accent. Fenced code uses its language tag. Markdown tables render as aligned grids that switch to a record layout in narrow panes. Completed Mermaid flowchart fences render as terminal diagrams with labeled solid/dashed edges and & fan-in/fan-out groups. Unsupported syntax (including subgraphs), incomplete fences, and diagrams too wide for the pane remain readable source.

The empty launch view shows the Mekugi and Codex versions. Release builds show their tag, such as mekugi-v1.2.3, rather than a commit SHA. Click tool output, long-content excerpts, or edit rows to open the shared scrollable dialog without leaving your current view. Close it with Esc or its top-right close button.

  • Ctrl-B, then 1/2/3/4/5, focuses Main, Diff, Activity, Agents, or Journal. Diff, Activity and Journal share the right column. Click a pane or its bottom selector to focus it. New sessions show Journal there. A live child spawn or follow-up temporarily shows Activity; when all children finish, Journal returns unless you selected another pane. Saved pane preferences still apply on resume.
  • Drag the dividers to resize panes or the file navigator. Ctrl-B, then arrow keys, resizes the main splits (up/down in the roster adjusts its height); Ctrl-B, then [/], resizes the file navigator. Narrow terminals show the focused pane full-width.
  • Ctrl-B, then PageUp/PageDown, browses Main history. The wheel scrolls the pane under the pointer.
  • Ctrl-C in an auxiliary pane returns focus to Main.

Main's top-right header shows the session title. Use /title <title> to rename it, even before the session has started or while a task is running. The new title appears immediately and is saved with the session; a save failure restores the last saved title and shows composer feedback. Manual renaming skips automatic title generation, including after resume or fork. For a new conversation without a title, the first successful upstream request starts a separate title-generation request using GPT-6 Luna with medium reasoning. This small additional model request does not block the conversation. If Codex credentials or Luna are unavailable, automatic naming is silently skipped, without switching to another model. Saved and inherited titles are reused on resume or fork.

Terminal titles and desktop notifications follow Codex's tui.notifications settings. Inside Herdr, its working, blocked, done, and idle indicators update even with notifications off.

See the UI contract.

Composer

Use input editing, file and skill pickers, steering, and queuing: Enter steers a running turn; Tab queues input. Type ? in an empty composer for the full shortcut list. The controls and attachment behavior are described below.

Use /lock to prevent Esc or Ctrl-C from interrupting work and to disable Ctrl-C exit on an empty draft. /unlock restores those shortcuts. Draft clearing, copying, and closing pickers still work while locked; /quit remains an explicit exit when idle. A persistent Locked indicator shows the protection, which is restored with the session on resume. It does not block explicit commands or steering new input.

  • Files and directory trees attach. @! also finds ignored files; neither picker lists VCS metadata such as .git. Selected text files attach their contents when you submit or queue the prompt, and large or unreadable files produce an explicit omission notice instead of truncated content. Directories attach a sorted tree of children and grandchildren, not file contents. Trees respect ancestor and nested .gitignore files, exclude VCS metadata, and list at most 256 entries within 16 KiB. A scan limit also bounds large directories; incomplete trees have an explicit truncation marker. Queued prompts retain the submitted tree.
  • Select to mention. Drag across Main, Activity, or the saved Diff and press r to add the selection as one short mention, such as [Selected message] or [Selected diff hunk @amber1:42-45]. The selected text is sent with the prompt without filling the composer or losing its formatting.
  • Skill references attach automatically. Complete enabled $skill-name references are recognized when you finish the word or submit a pasted prompt; unknown, disabled, or ambiguous names stay plain text. With skills-mgr, managed skills attach their actual instructions automatically, with an Attached skill receipt. Click successful file or skill attachment receipts to open their submitted contents, including after resume. Unreadable or oversized contents produce an explicit omission notice. Without it, contents come from Codex-discovered skill files. Use skills-mgr to manage its skills; /skills toggles Codex-discovered skills.
  • Waiting messages combine. Steers typed while an earlier one is still sending, and queued messages, each appear as one stack and send as one message, one entry per line. Alt+Up or Shift+Left returns all locally waiting input to the composer. Already-sent steers remain pending until Codex commits them or the turn ends. While a turn is active, Esc expedites pending or locally waiting steers: it interrupts the turn, then sends only uncommitted steers in a new turn, leaving your draft unchanged. Tab-queued input stays queued when a steer is resent. If all pending steers commit before interruption completes, nothing is resent and queued input returns to the composer as in a normal interrupt. Already-committed input is never resent. Ctrl-C clears the draft first, then interrupts and restores waiting input without resending it. With no pending steers, Esc interrupts and restores input without resending, and never quits. Closing a picker, help, or selection and returning scrollback to the bottom take precedence over Esc interruption.
  • Session controls. Enter on /compact interrupts the current turn and compacts after Codex acknowledges its end, with or without instant_interrupt. Tab queues compaction until the current turn ends. After successful busy compaction, waiting input runs next; without waiting input, Mekugi sends a visible continuation message to resume the task. Idle compaction stays idle, and failure or interruption never automatically continues it. Ctrl+C cancels queued compaction and restores waiting input without interrupting Main. Cancelling while an Enter-command interruption is pending prevents compaction but cannot undo that interruption; once compaction starts, it interrupts only that compaction. /clear starts a fresh session and clears its transcript; it is available while idle and does not delete saved sessions or filesystem changes. A normal interrupt returns unsent input to the composer without automatically resending it; Esc with pending steers uses the expedited delivery above. Interrupting an uncommitted first message leaves an empty transcript.
  • Live diffs. Edits temporarily replace Main's transcript or the editing agent's Activity transcript, leaving other agents visible. Brief edits finish without opening this temporary view; their saved diffs remain available. Ctrl-B e cycles and pins files; Ctrl-B r resumes Main's live following. Completed edits stay together until the batch settles, then the transcript returns. /live toggles the view; /live on or /live off applies directly for the current session without stopping activity or capture. New launches, including resume, show it again.
  • Setting pickers. /model, /effort (also /reasoning), and /tier open a picker: Up/Down and Enter apply a choice, Esc cancels, and neither the command nor its choices enter the transcript. A value switches directly, such as /effort high or /tier priority; /tier default clears the tier. Changes also reach a running turn's next steps and never edit your config file.
  • Terminal requirements. /copy and text selection copy through OSC 52, which your terminal must allow. Pasting a clipboard image on Linux needs wl-paste (Wayland) or xclip (X11).

/btw QUESTION asks a side question about a snapshot of the conversation, even while Main is working. The answer streams in a panel above the composer, with shimmering Answering status and elapsed time. Drag across its content to copy or reference it, just as in Main. Repeat /btw QUESTION to follow up, use PgUp/PgDn to scroll, and press Esc to clear a selection or close the panel; Main keeps working and your draft stays. Closing discards the side conversation, and it can't be resumed. If the side question needs compaction, it is rejected and restored to the composer. Compact Main, close the side panel, and retry to take a fresh snapshot.

Resume

resume THREAD_ID and resume --last work as in Codex. Startup resume and /resume restore the session's saved model, reasoning effort, and service tier; explicit -m and -c flags override only the settings they name. Resuming also restores pane layout, keyboard focus, the agent roster, Activity history, and the session's retained Diff changes. Scroll positions, filters, selections, and drafts are not restored. Successfully applied settings survive a fresh launch, including priority and default selections made before the first turn. Storage failures are reported in Activity. If no saved model settings are available, a notice explains that Codex defaults and explicit flags apply instead. Main histories larger than 16 MiB cannot resume in the UI. Older child activity loads on demand. In third-party modes, noninteractive exec resume and exec fork use the mode's default model rather than the saved one; pass -m to choose another. Codex does not save an empty conversation before its first turn. If Codex rejects restoring default reasoning, waiting input returns to the composer and stays blocked until you choose /effort VALUE or restart resume.

Bare resume, or /resume inside a session, opens a picker of saved sessions for the current workspace, newest first. Type to search, Tab to show every workspace, and Enter to resume. Esc clears the search, then starts a new session at launch or closes the picker in a session; Ctrl-C quits at launch. /resume switches the UI to the chosen session and is unavailable while a task runs; /resume THREAD_ID switches directly.

Live diff pane

The live diff viewer opens at the first edit or command; read-only turns don't open it. Main-agent and subagent calls get labeled cards that stream input as it arrives. When a turn finishes, the viewer switches to the saved diff. A failed or unfinished call never becomes a saved change.

  • v switches views; ? lists diff shortcuts.
  • In the saved Diff, s shows and focuses the file/Changes navigator; press it again to hide the navigator. t toggles tree/flat paths, / filters files.
  • The navigator and diff have separate focus. Arrow keys act on the focused region. Selecting or clicking a file previews it while keeping list focus; Enter opens it and focuses the diff. Click the diff to focus it, or press Esc from an opened diff to return to the list.
  • n/p change files, [/] jump between hunks, and j/k, Space/b, and g/G scroll. Opening a file starts at its header.
  • Tab switches the navigator to Changes: a graph of changes by caller (main or the agent's name) with each change's source, such as apply_patch, sed, or python3. {/} step through changes, a shows one caller's changes at a time, and 0 shows all callers. In the tab, Enter on a caller filters to it, and Enter or h/l on a change expands or collapses its files.
  • Click an Edit to inspect its captured diff in the shared dialog. Reply, question, and journal-agent links also open dialogs, leaving pane filters and scroll positions unchanged. Completed host file-change diffs open even while other commands in the same batch are still running. Esc dismisses the dialog.
  • New saved edits refresh the content without moving your chosen file or scroll position. Streaming previews still follow live edits until you browse; r resumes preview following.

See live view details.

Journal pane

Press Ctrl-B then 5 to open Journal. Its title counts tasks by state. Open tasks come first; subtrees start expanded and collapse oldest-first when space runs short. Use j/k or arrows to select, Space to expand or collapse, d to read full details, Enter to open a row, and c to copy the selected path. Click a ▸ marker to expand it, or click a row to open it. Esc returns to Main. Blocked tasks show their reason; notes have no state label. Entries replaced by later direction stay dimmed with superseded by and the path of their replacement. Delegated journals appear under their owning task, or in an Agents group after the owned plan. Agent headings show their lifecycle separately from task states; expanded descendants use local paths without repeating the agent name. Outcomes follow the work they summarize. Press c to copy their full journal address. Press Enter on, or click, an agent to open its Activity.

The plan strip stays above the composer while work remains. Main offers a continuation countdown after an agent stops with unfinished work, including after answering a follow-up. Esc cancels. Blocked tasks and pending questions pause automatic continuation. Explicitly stopped work stays paused across later questions, forks, and resume until reactivated. Ordinary continuation keeps the current context, while planned slice boundaries follow the selected compaction mode. Headless sessions use the same policy without a countdown and require interactive continuation when a question needs an answer.

Main shows task transitions and, while Journal is hidden, notes. Work updates appear in separate cards; open a card for full evidence and older notes. Ordinary answers remain in the conversation, and an unchanged plan does not add a report card. Task timers count active work, pause while blocked or the agent is inactive, and retain their totals when work resumes.

Agents pane

The Activity pane streams child activity, messages, and replies, including while Main waits. The Agents roster below the main columns shows children with their active elapsed time, provider round trips, output tokens/sec, and cumulative edited lines as +N -N. The roster header's +N -N reports the final composed outcome across agents, so superseded edits and files created then deleted do not inflate it. It uses recorded changes, not a live Git diff; incomplete or inconsistent evidence shows ?. Main's conversation and progress stay in Main. Usage and estimated API costs appear per thread and survive resume while their records are retained, including for completed agents. Missing consumption is not zero: ≥ marks known lower bounds (including restored totals), and unavailable metrics stay blank. Older sessions without retained accounting cannot recover usage from context counts. Elapsed timers exclude idle gaps and freeze when work stops; the separate last-response age continues counting. Main's output throughput appears only beside context in its composer, not in its roster row. The last valid provider-measured rate stays visible while streaming and between requests until a newer valid terminal measurement arrives. Throughput stays blank before the first valid measurement. Visible streaming omits hidden reasoning, so it is not used to estimate total output throughput. Measured rates survive resume. See Metrics for launch-wide totals.

  • Click an agent to inspect its activity; reply links address that agent.
  • In Activity or Agents, a toggles selected-agent filtering. The hint reads a all while filtered, and a only in the shared view.
  • Scrolling pauses following; End resumes it. The mouse wheel scrolls without changing keyboard focus.
  • When the Activity title shows Older history, focus Activity and press o to load an older page for the selected child, or the first child with older history in the shared view. Esc cancels the read; o retries a failed read. Intentionally unloaded history is distinct from unavailable evidence.

Redirected sessions keep ordinary Codex input/output and inline agent activity. Inside Herdr, Mekugi advertises the invocation through Herdr's agent hint. Herdr is optional and does not control Mekugi's internal panes.

Output dialog

Click a command, program, read, error, or long-content excerpt in Main or Activity to open its full content in the shared dialog above the panes, without expanding the transcript. Read source and unified diffs use syntax colors. Untyped command output above 8 KiB stays uncolored for responsiveness; its text remains available for reading, searching, and copying. File-specific and diff highlighting retain their 256 KiB limit. Supported Bash commands and Linux /bin/sh commands backed by dash use the same command tracking. Each segment of a command list streams its own output and shows its state and measured elapsed suffix; clicking it opens that segment's tab with its retained output and exit status in the shared dialog. Supported single commands use measured command time in the same suffix, leaving output unchanged. See command tracking for limits and overhead. Older history without timing evidence shows no per-command duration. Without retained output boundaries, the dialog labels the output as combined. Errors keep a short inline preview. Click details, or focus Main or Activity and press Ctrl-B then !, to read the full error, including restored JavaScript execution failures. The keyboard shortcut opens the newest error; Left/Right reaches the other retained errors in that transcript. Host-omitted text cannot be recovered.

Click a Markdown link to an existing local file in Main, Activity, or a dialog to read its current contents. Relative paths resolve against the session workspace; absolute paths and local file:/// links also work. A :line suffix scrolls to that source line when it exists. The path row uses workspace-relative display inside the workspace and stays absolute outside it. Drag to select the path or visible content, then y, c, or Ctrl-C copies it; y without a selection copies the original file contents. Files must be UTF-8 text no larger than 8 MiB. Read failures, oversized files, and binary/non-UTF-8 files show red, copyable errors. Terminal controls are sanitized for display. Reopening reads the file again; an open dialog does not monitor changes. HTTP(S) links still copy their destinations in Main and Activity; clicking them inside a dialog still does nothing. Missing or unrecognized file links keep their prior behavior.

  • Left/Right or a click switches tabs. j/k, PgUp/PgDn, and g/G scroll; live output follows its tail until you scroll up.
  • / searches, and n/N step through matches.
  • y copies the page's output. Drag to select text, then y, c, or Ctrl-C copies the selection.
  • The top-right [×] button, Esc, q, or a click outside closes it.

See activity display.

Recoverable output and change review

Saved diffs and mchanges record recognized source edits, including edits to ignored files, and the file changes of any other command that may write, such as a Python script, found by comparing workspace snapshots taken before and after it. Agents do not need apply_patch to have their edits recorded. Inside a Git repository, ignored paths such as an ignored node_modules/ stay out of the record unless an edit names them; outside Git, bulk new files in one directory are left out. Changes made by you while a command runs are attributed to that command. LiveDiff previews remain provisional.

Wrapped-session helpers

Session helpers let the agent read less output and recover what it omitted, or review and undo recorded edits. They are available only inside a wrapped session; you can ask the agent to use them.

Command Purpose Requirements
mread Continue bounded retained output by reference Access to the router's replay directory
mrun Bound a foreground command's output and optionally keep its ending The wrapped command
mchanges Review the current thread's edits, compose captured diffs, or read/revert/reapply explicit IDs Access to the router's replay directory
mcat Read raw UTF-8 rows, with multi-file batching, ranges, and tail selection None
msymbol Look up compact definitions and file-grouped references; batch queries in one call gopls for Go; TypeScript 7 as tsc for JS, TS, and JSON; pyright-langserver for Python
inspect_file Inspect a structural outline None
mchanges --list
mchanges amber1..amber3 --summary
mchanges revert amber2
mread REF
mcat --number source.ts 10-20 40:60
inspect_file source.ts
mrun --tail -n 20 go test ./internal/router

mchanges is the recorded view of agent changes, including ordinary Git-ignored files such as FIXME.md, not a live Git diff. Dependency trees are summarized as one directory status, such as M node_modules/, without descendant listings or content. Manifest and lockfile changes remain reviewable. Directory summaries cannot be reverted or reapplied because their contents are not retained. Tests, generators, and other commands without known targets also record changes observed while they ran. These are labeled observed during command window, since another writer may have made them; unavailable evidence is reported rather than treated as no changes. Like git revert, mchanges revert merges any later edits and marks overlaps with conflict markers. The revert is recorded as a new change, so it can be undone too. See the change record, reader, and execution contract.

Metrics

Open /session in Main for the current launch's request and retry counts, provider usage, usage-evidence coverage, average output tokens/sec, measured cache rate, capture health, and transport details. Average throughput is measured output tokens divided by the sum of their provider-request seconds, including request latency and automatic transport retries, not an average of individual rates or session wall time. Local preparation, tool execution, and idle time between requests are excluded. Measured rates use provider-response receipt time, before local processing and delivery of already-read output. Unread transport buffering and backpressure still count, so these rates describe observed provider-request throughput, not provider-only generation speed. Requests without timing or authoritative token totals are excluded from both sums; measured request count and duration show the coverage. Output includes provider-counted reasoning tokens. A measured zero-output request has zero throughput; missing timing is unavailable. Exchanges shows timings, errors, and each attempt's provider-returned service tier, not the configured tier; missing evidence stays unavailable. Left/Right or Tab switches Overview, Transport, and Exchanges; Up/Down, mouse wheel, and PgUp/PgDn scroll. In Exchanges, [ selects older and ] newer observations. r refreshes immediately; the open dialog also refreshes once per second. Escape closes without interrupting a turn. Metrics include all threads in this launch, not just the currently displayed session, and do not restore historical totals after resume. There is no browser dashboard.

The same sanitized metrics remain available through the local API:

curl -sS "${MEKUGI_BASE_URL%/v1}/api/metrics"
mekugi --capture-output capture.jsonl codex

Launch metrics stay in memory unless captured with --capture-output; captures hold sanitized measurements only, with no prompts, patches, or credentials. Provider-reported usage is authoritative; local token estimates are not billing figures. Costs are API estimates, not subscription charges. See the metrics reference.

mekugi --debug codex writes a private mekugi-debug-* bundle under $XDG_STATE_HOME/mekugi/debug (default ~/.local/state/mekugi/debug). Inactive bundles are removed after 14 days; copy a bundle elsewhere to keep it. Explicit external capture/read destinations are not removed. Existing temporary bundles are left untouched. /session shows the bundle path and measured application-write bytes in Overview; final metrics include the same accounting. These bytes cover this router's managed-record and debug/capture writes, not physical disk traffic or subprocess writes. On exit, “To diagnose this session” prints an inspection command ready to share with an agent. Debug bundles include private session content and are not sanitized. Repeated instruction/tool content is stored once and referenced by later requests, while request and wire-projection evidence remain available through the inspection command. Its report includes artifact sizes and application-write metrics to help identify bulky or incomplete evidence. Older bundles remain readable and are not rewritten. Debug mode records future requests only. See debug evidence.

Configuration

Mekugi settings

Create mekugi/config.toml in your user configuration directory: $XDG_CONFIG_HOME or ~/.config on Linux, ~/Library/Application Support on macOS.

# Optional overrides, keyed by exact model ID.
[service_tiers]
"gpt-6-astra" = "fast"
"gpt-5.6-sol" = "default"

[providers.opencode_go]
api_key = "your-go-key"

[providers.opencode_zen]
api_key = "your-zen-key"

Every section is optional. Settings are read at startup and never rewritten.

  • Service tiers replace the request's tier after model selection. The values are auto, default, fast (sent as priority), priority, and flex. The provider must support the tier you choose. The composer and /status show the effective tier, including this override, rather than only Codex's requested tier. /tier shows the effective current tier. Confirmed explicit choices, including default, override configured defaults for that thread and routed model during this invocation without changing your config file. /session reports the provider-returned tier, which can differ from the requested tier.
  • API keys: these file keys are optional alternatives to the OpenCode environment variables.

Troubleshooting and integrations

  • Post-compaction recovery: After compaction, Mekugi restores a bounded snapshot of Main's journal and changes. Subagents and passthrough mode are unaffected. This needs Codex's compact SessionStart hook support (tested with CLI 0.156.1). Opt out with --post-compact-recovery=false or /hooks. If Codex asks you to review the hook, use /hooks. Custom -c hooks=... settings are left alone; to enable recovery with them, add a SessionStart handler matching ^compact$ that runs /absolute/path/to/mekugi post-compact. Hook failures don't stop the task. See guidance behavior.
  • Journal compaction (opt-in): --journal-compaction=auto uses retained task, constraint, change and failed-command evidence instead of asking the model for a summary. It includes subagents and falls back to the provider if evidence cannot be safely recovered. Recovery keeps constraints and open work inline; completed task bodies and agent history stay available through journal reads when needed, rather than filling the restored context. The default remains off pending comparative evaluation; this is not evidence of improved model success or token savings. In the UI, sliced plans show a countdown between successful turns; Esc cancels. slice and auto reset context before continuing, while off continues without resetting. An interrupted reset may require manual continuation. Resets appear once in the journal, not as duplicate commentary. Click the journal's Context reset from journal row to read the recovery message shown to the model. Older or expired messages are marked unavailable. See compaction behavior.
  • Instructions: Wrapped sessions disable Codex's /goal feature. Anything between <!-- mekugi:omit --> and <!-- /mekugi:omit --> in instruction files is omitted for the session; the files themselves are not changed. When skills-mgr is on the PATH, Mekugi turns off Codex's stock skill catalog for the session. Managed $skill selections attach their instructions in the composer; other Codex-selected skill injections remain compact name references. See guidance behavior.
  • Issue reports: start with MEKUGI_DIAGNOSE=1 to give agents a report_issue tool. Each report runs the commands in hooks.diagnose of mekugi/settings.json in your user configuration directory. Commands are templates with .Title, .Body, shellquote, and format_markdown, for example gh issue create --title {{shellquote .Title}} --body {{shellquote .Body}}. See agent issue reports.
  • Plugins: put .js or .mjs modules in mekugi/plugins in your user configuration directory. See the plugin contract.
  • Executor environment: the router and executor must see the same workspace paths and runtime directory. MEKUGI_RUNTIME_DIR overrides the default temporary directory.
  • Failures: startup errors print before Codex launches. Session failures appear as user-only commentary; undelivered notices print to stderr after exit. A router translation fault ends the turn and suggests recovery steps.

Replay storage

Replay records live in $XDG_STATE_HOME/mekugi/replay, or ~/.local/state/mekugi/replay if that variable is unset. Resuming and side conversations need no extra flag. Replay doesn't rerun old commands or restore processes. Roster usage shares this managed store; existing records need no migration. Publication remains atomic for readers, with disk flushing left to the kernel. Sudden power loss may lose recent records; unavailable retained evidence is not recovered by rerunning the original operation.

For read-only storage diagnosis, use mekugi inspect-storage; see the storage inspection reference for selectors and output limits.

Mekugi retains up to 4 GiB of managed session data and deletes it after 14 days without activity. When storage is full, it removes the least recently active inactive sessions first, and never touches running work. Your Codex chats and workspace files are never deleted. If storage is full, Mekugi reports when evidence cannot be retained. Free space and retry retaining the evidence, not the completed command or edit. Cleanup can break old recovery and review references. To reset, stop all Mekugi wrappers and move the directory aside.

Inspect a session

This reads a Codex rollout without running anything or starting a router:

mekugi inspect-session --session /path/to/rollout.jsonl
mekugi inspect-session --debug-dir /path/to/debug --field diagnostic
mekugi inspect-session --failures
mekugi inspect-sessions --exclude-model '*grok*' --class production

The default JSON holds tool names, call IDs, outcomes, and sizes, but no private text. For a reported issue with a debug bundle, use the printed --debug-dir command to see failure evidence, capture health, metrics, and AX results. Use --request-id ID --field all to drill into one request's capture and instruction evidence. Values you request with --field may include private error text, instructions, source, and command output. See session inspection and AX evidence.

Replay a session

Review a retained session through the UI without running Codex, calling providers, executing commands, or answering questions:

mekugi replay-session --session SESSION_ID
mekugi replay-session --session SESSION_ID --debug-dir /path/to/debug --speed 4

Use the full session ID, not a rollout path. Mekugi finds the session in sessions or archived_sessions under CODEX_HOME (default ~/.codex). Missing or duplicate rollouts are reported as errors.

Playback defaults to 1.0x. Streaming is simulated from retained text and timing, not a screen recording; --seed 1 makes comparisons repeatable. Referenced child rollouts are included when available. Retained journal records restore task progress, delegated hierarchies, and completion cards when timing is available. Missing records are reported. Original keystrokes, window sizes, and live diff previews are not reconstructed.

The playback bar shows position, speed, and simulated-streaming status. p pauses, +/- steps through speed presets from 0.1x to 100x, [/] seeks ten seconds, r restarts, Ctrl-B 1–5 selects Main, Diff, Activity, Agents, or Journal, and q quits. In Journal, j/k or arrows select, Space expands or collapses, d/Enter opens read-only details, and the wheel scrolls the tree. Esc/q closes details before quitting replay. Outside Journal, Space also pauses and j/k or the wheel scrolls Main. Playback stops on its final frame until you quit. Use --from 5m --until 6m to review a recorded interval; earlier state is loaded first. The current terminal size controls layout.

For offline measurements, use --headless --width 160 --height 48; stdout is a JSON timing summary. Headless playback renders the UI but cannot measure terminal backpressure. Compare runs with the same inputs, seed, speed, and dimensions; use 1.0x for representative latency. Use the profiling build to collect profiles from live sessions or replay. Session contents remain local and may appear on screen. See the replay reference.

Older installations

Finish active sessions before replacing an older installation. Retire any old service and provider configuration separately, keeping unrelated settings and authentication. Then choose a current launch mode.

Documentation

Development

Profile live sessions and replay

From a checkout with the source-build prerequisites, run make mekugi-pprof. It regenerates the existing preview assets and builds bin/mekugi-pprof with optimized code, symbols, and the pprof build tag, plus its executable sibling bin/mekugi-exec. It does not install or replace mekugi. Use the diagnostic binary with your usual launch arguments, or replay offline:

bin/mekugi-pprof codex --yolo
# Alternatively:
bin/mekugi-pprof replay-session --session SESSION_ID --headless --width 160 --height 48 --seed 1 --speed 1

Before the UI takes over, stderr prints an invocation-specific URL: mekugi-pprof: http://127.0.0.1:PORT/debug/pprof/. While that session or replay is running, copy its URL into a second terminal:

umask 077
MEKUGI_PPROF_URL='http://127.0.0.1:PORT/debug/pprof/'
go tool pprof -seconds 30 bin/mekugi-pprof "${MEKUGI_PPROF_URL}profile"
go tool pprof bin/mekugi-pprof "${MEKUGI_PPROF_URL}heap"

Replace PORT with the printed port. The index also offers allocs, goroutine, block, mutex, and execution-trace endpoints. CPU and trace collection start only on request; block sampling uses a 1 ms blocked-time rate and mutex sampling records one in ten contention events. Instrumentation can perturb performance. Profiles cover Mekugi's router, UI, and replay process; separate Codex, executor, and worker processes need their own measurements.

The listener is private IPv4 loopback, with no additional authentication. Local callers can read command-line arguments and other private process data; keep captures private. Session or replay completion ends active captures and closes the listener. The normal build starts no profiling listener, and replay creates no automatic profile files. See the profiling contract and replay comparison limits.

Build and test

The build workflow tests and packages both commands for Linux amd64/arm64 and macOS arm64 on pushes to main, pull requests, and manual runs. Pushing a v* tag also publishes the three archives and SHA256SUMS to a GitHub release, with the tag embedded as the welcome version. Rerunning a tag build replaces that release's matching assets.

Before packaging, Linux amd64 runs the fresh full offline Go suite and make lint with pinned lint tools. Other platforms run command and welcome/version checks.

To review the UI without Codex or model requests, run make preview-native-ui in a terminal. It plays a synthetic session through the real panes and renderer: streaming and long messages, journal edits, retraction and flush, agent summaries, and Main/agent communication. Scroll, resize, and click reply links to inspect them. Keys behave as in the real UI: Enter steers the playing turn or, once idle, starts a new one that echoes your prompt; Tab queues for the next turn; Ctrl-C clears the draft, then interrupts playback, then exits, as does /quit.

For offline terminal-layout regression checks, run make test-ui-snapshots. Failures leave .txt.new candidates beside the reviewed fixtures and print a diff without replacing the baseline. After reviewing an intentional change, run make update-ui-snapshots SNAPSHOT='^TestUISnapshotJournalReply$', then rerun the check. Omitting SNAPSHOT updates all matching cases. See terminal UI snapshot testing for fixture locations and coverage limits.

The full offline Go suite includes configured-plugin fixtures and requires Node.js 24+ and ripgrep on PATH, even when using built-in frontends. make lint requires golangci-lint and deadcode on PATH; it does not install them. It runs the configured Go linters and deadcode analysis including test executables. Lint findings, deadcode findings, and tool failures all fail the command.

make preview-assets
make test
make lint

Built-in frontends are native Go. Go regenerates the optional plugin shared core; Bun is needed only for the separately invoked JavaScript plugin-host and shared-core tests: bun test ./internal/router/toolplugin/tests.

While implementing, select the affected Go packages and tests, for example make test TEST_PACKAGES=./internal/router TEST_RUN='^TestShellRunnerMRun'. The default checks all packages and uses Go's test cache; add TEST_FLAGS=-count=1 for an uncached run. See focused checks.

License

MIT. See LICENSE.

About

A Codex Responses router that provides better Agent and User Experiences.

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages