Document the workflow for delegating tasks to Codex via tmux-cli instead of using the Codex MCP server for long-running commands.
5.1 KiB
CLAUDE.md
Project Summary
This project is porting the NATS server from Go to .NET 10 C#. The Go source (~130K LOC across 109 non-test files, 85 test files) is at golang/nats-server/. The porting process is tracked via an SQLite database (porting.db) and managed by two tools: a Go AST analyzer and a .NET PortTracker CLI.
Folder Layout
natsnet/
├── golang/nats-server/ # Go source (reference)
├── dotnet/ # .NET ported version
│ ├── src/
│ │ ├── ZB.MOM.NatsNet.Server/ # Main server library
│ │ └── ZB.MOM.NatsNet.Server.Host/ # Host/entry point
│ └── tests/
│ ├── ZB.MOM.NatsNet.Server.Tests/ # Unit tests
│ └── ZB.MOM.NatsNet.Server.IntegrationTests/ # Integration tests
├── tools/
│ ├── go-analyzer/ # Go AST analyzer (Phases 1-2)
│ └── NatsNet.PortTracker/ # .NET CLI tool (all phases)
├── docs/plans/phases/ # Phase instruction guides
├── reports/ # Generated porting reports
├── porting.db # SQLite tracking database
├── porting-schema.sql # Database schema
└── documentation_rules.md # Documentation conventions
Tools
Go AST Analyzer
CGO_ENABLED=1 go build -o go-analyzer . && ./go-analyzer --source golang/nats-server --db porting.db --schema porting-schema.sql
.NET PortTracker CLI
dotnet run --project tools/NatsNet.PortTracker -- <command> --db porting.db
Phase Instructions
- Phase 1: Go Codebase Decomposition -
docs/plans/phases/phase-1-decomposition.md - Phase 2: Verification of Captured Items -
docs/plans/phases/phase-2-verification.md - Phase 3: Library Mapping -
docs/plans/phases/phase-3-library-mapping.md - Phase 4: .NET Solution Design -
docs/plans/phases/phase-4-dotnet-design.md - Phase 5: Mapping Verification -
docs/plans/phases/phase-5-mapping-verification.md - Phase 6: Initial Porting -
docs/plans/phases/phase-6-porting.md - Phase 7: Porting Verification -
docs/plans/phases/phase-7-porting-verification.md
.NET Standards
All .NET code must follow the rules in docs/standards/dotnet-standards.md. Key points:
- .NET 10, C# latest
- Testing: xUnit 3, Shouldly, NSubstitute — do NOT use FluentAssertions or Moq
- Logging:
Microsoft.Extensions.Loggingwith Serilog provider; useLogContext.PushPropertyfor contextual enrichment - Naming: PascalCase for all public members;
ZB.MOM.NatsNet.Server.[Module]namespace hierarchy
Using Codex via tmux-cli
Use tmux-cli to launch and interact with OpenAI Codex (ccc alias) in a separate tmux pane. This lets you delegate tasks to Codex without blocking your current session.
Do NOT use the Codex MCP server (mcp__codex__codex) for long-running commands. Use tmux-cli + ccc instead — it runs in a separate pane, won't time out, and lets you capture output when ready.
The ccc alias
ccc runs codex --dangerously-bypass-approvals-and-sandbox (with Node/nvm auto-setup). Use it for tasks you want Codex to handle autonomously.
Workflow
Always launch a shell pane first — if a command errors without a shell, the pane closes and output is lost:
# 1. Launch a shell (returns pane ID, e.g. "2")
tmux-cli launch "zsh"
# 2. Send a codex command to that pane
tmux-cli send 'ccc "your prompt here"' --pane=2
# 3. Wait for codex to finish (no output for N seconds = idle)
tmux-cli wait_idle --pane=2 --idle-time=10.0
# 4. Capture the output
tmux-cli capture --pane=2
# 5. Clean up when done
tmux-cli kill --pane=2
Key tmux-cli commands
| Command | Purpose |
|---|---|
tmux-cli launch "zsh" |
Start a shell pane (do this FIRST) |
tmux-cli send "cmd" --pane=N |
Send text + Enter to pane N |
tmux-cli send "text" --pane=N --enter=False |
Send text without pressing Enter |
tmux-cli send "text" --pane=N --delay-enter=0.5 |
Custom delay before Enter (default 1.5s) |
tmux-cli wait_idle --pane=N --idle-time=3.0 |
Wait until pane has no output for N seconds |
tmux-cli capture --pane=N |
Capture current pane output |
tmux-cli list_panes |
List all panes (JSON with IDs and status) |
tmux-cli kill --pane=N |
Kill a pane (cannot kill your own) |
tmux-cli interrupt --pane=N |
Send Ctrl+C to a pane |
tmux-cli escape --pane=N |
Send Escape to a pane |
Pane identifiers
- Just the pane number:
2(current window) - Full format:
session:window.pane(e.g.myapp:1.2)
Tips
- Use
wait_idleinstead of polling with repeatedcapturecalls - Save the pane ID returned by
launchfor subsequent commands - Use
captureto check state before sending input - For long-running Codex tasks, increase
--idle-time(e.g.--idle-time=15.0)
Reports
reports/current.mdalways has the latest porting status.reports/report_{commit_id}.mdsnapshots are generated on each commit via pre-commit hook.- Run
./reports/generate-report.shmanually to regenerate.