tukuai
v0.1.0
Published
Tuku CLI launcher that installs native binaries and runs Tuku from your terminal.
Maintainers
Readme
Tuku
Tuku is a local-first orchestration brain for coding work.
Current Manual-Test Scope
This repository currently supports a runnable local flow for:
task.starttask.messagetask.shell.snapshottask.runtask.statustask.inspecttask.checkpointtask.continuetask.handoff.createtask.handoff.accepttask.handoff.launchtukutuku chattuku shell --task <TASK_ID>
Tuku remains the canonical response owner:
- worker output is captured as evidence
- Tuku emits the final canonical user-facing response
Prerequisites
- macOS (current focus)
- Go toolchain installed and on
PATH codexexecutable installed and onPATHfor the live PTY shell path- Optional override:
TUKU_SHELL_CODEX_BIN=/absolute/path/to/codex - Optional args:
TUKU_SHELL_CODEX_ARGS="..."
- Optional override:
claudeexecutable installed and onPATHfor real handoff launch tests- Optional override:
TUKU_CLAUDE_BIN=/absolute/path/to/claude - Optional args:
TUKU_CLAUDE_ARGS="--your --flags" - Optional timeout:
TUKU_CLAUDE_TIMEOUT_SEC=90
- Optional override:
Build
cd /Users/kagaya/Desktop/Tuku
go build ./cmd/tuku ./cmd/tukudSimple Global Install (npm)
If you want a CodeMaster-style install where users run one command and then type tuku, this repo now includes an npm launcher package.
Install:
npm install -g tukuaiThen run:
tukuHow it works:
- the npm
tukucommand is a thin Node launcher - on install/first run it downloads native
tukuandtukudbinaries into~/.tukuai/bin - if release binaries are unavailable, it falls back to building binaries from bundled Go source automatically (requires
goon PATH) - then it executes native
tukuand ensurestukudis on PATH for daemon bootstrap
Release asset naming convention expected by the launcher:
tuku-tuku-darwin-arm64tuku-tukud-darwin-arm64tuku-tuku-darwin-amd64tuku-tukud-darwin-amd64tuku-tuku-linux-arm64tuku-tukud-linux-arm64tuku-tuku-linux-amd64tuku-tukud-linux-amd64
These assets should be uploaded to GitHub Releases at tag v<version> in the repo configured by releaseRepo (default: kagaya/Tuku in package.json).
Optional environment overrides:
TUKU_RELEASE_REPO=owner/repo(override release source repo)TUKU_ASSET_PREFIX=tuku(override asset name prefix)TUKU_CLI_VERSION=0.1.0(force specific release version)TUKU_INSTALL_ROOT=/custom/path(override install root)
Start Local Daemon
Run in one terminal:
cd /Users/kagaya/Desktop/Tuku
go run ./cmd/tukudThis manual daemon path remains useful for debugging and development. The primary tuku / tuku chat entry now tries to start the local daemon automatically when it is not already running.
Default local paths:
- SQLite DB:
~/Library/Application Support/Tuku/tuku.db - Unix socket:
~/Library/Application Support/Tuku/run/tukud.sock
CLI Help
cd /Users/kagaya/Desktop/Tuku
go run ./cmd/tuku helpPrimary Entry
The main entry surface now resolves the current git repo automatically:
- it tries the local daemon first and starts it automatically in the common "not running yet" case
- it finds the current repo root from
cwd - it reuses the most recent matching task for that repo, preferring an
ACTIVEtask - if no matching task exists, it creates a new task with a minimal continuation goal
- if that repo-backed task is newly created and a local scratch session exists for the same directory, Tuku surfaces those local notes in the initial shell as adoptable intake context without importing them automatically
- those surfaced local notes can be staged into a shell-local draft, edited locally inside the shell, and only become canonical after an explicit send
- it then opens the existing full-screen shell flow
- if no git repo is detected, it opens a simple local scratch and intake prompt without inventing repo-backed continuity
- local scratch notes entered there are persisted only on this machine and reopen when you return to the same non-repo directory
Run it with:
cd /Users/kagaya/Desktop/Tuku
go run ./cmd/tuku
go run ./cmd/tuku chatOptional worker preference:
go run ./cmd/tuku --worker auto
go run ./cmd/tuku --worker codex
go run ./cmd/tuku --worker claude
go run ./cmd/tuku chat --worker auto
go run ./cmd/tuku chat --worker codex
go run ./cmd/tuku chat --worker claudeIf the current directory is not inside a git repository, Tuku now opens a deliberate local scratch and intake prompt and says so directly instead of inventing task continuity. That no-repo mode is intentionally simpler than the repo-backed shell: normal terminal input, obvious /help, /list, and /quit commands, and one-line local scratch note capture. Scratch notes from that mode are stored locally under ~/Library/Application Support/Tuku/scratch/ and are not part of daemon-backed task state. When you later create the first repo-backed task in the same directory, Tuku can surface those notes as local intake context, stage them into a shell-local draft, edit that draft locally inside the shell, and then explicitly adopt them only when you send that draft through task.message. If the daemon cannot be started automatically for the repo-backed path, Tuku returns a direct local-daemon startup error instead of pretending the shell can continue.
Terminal Shell
Tuku now includes a worker-native terminal shell:
- the center pane stays worker-first
- Tuku chrome only adds continuity, handoff, and proof context around it
- the default shell now opens with calmer secondary chrome: the worker pane stays dominant and inspector/activity can be toggled in as needed
- current shell can host either a real Codex PTY session or a real Claude PTY session
- the live host now tracks explicit shell-local lifecycle state: starting, live, exited, failed, fallback, transcript-only
- the worker pane now labels live sessions as live input and transcript modes as read-only so fallback state is obvious at a glance
- each shell run gets a shell-local session id and compact in-memory session journal
- the daemon now owns a narrow durable shell-session registry with compact metadata only
- shell-session reads now classify sessions as attachable, active-unattachable, stale, or ended
- live PTY-backed shells now report a durable worker-session id and narrow attach capability metadata for future reattach groundwork
- major shell lifecycle milestones are bridged into persisted proof: host started, host exited, transcript fallback activated
- terminal resize is propagated into the live worker pane when the PTY host is active
- if PTY startup fails or the live worker exits, the shell falls back to the persisted transcript view and keeps the shell usable
- if you open the shell again later, the new shell session surfaces both the latest persisted shell outcome and any other known shell sessions for the task, including stale-session uncertainty
Run it with:
go run ./cmd/tuku shell --task <TASK_ID>Optional worker preference:
go run ./cmd/tuku shell --task <TASK_ID> --worker auto
go run ./cmd/tuku shell --task <TASK_ID> --worker codex
go run ./cmd/tuku shell --task <TASK_ID> --worker claudeInspect daemon-known shell sessions for a task:
go run ./cmd/tuku shell-sessions --task <TASK_ID>The output includes worker_session_id, attach_capability, and session_class with attachable, active_unattachable, stale, or ended.
Key controls:
- when the worker pane is live and focused:
- normal typing goes to the worker session
- use
Ctrl-Gthen the next key for shell commands
- shell commands:
qquititoggle inspectorptoggle activity striprrefresh statestoggle compact status overlayhtoggle helpastage a shell-local draft from surfaced local scratcheedit the staged shell-local draft in the worker panemsend the current draft through Tukuxclear the staged shell-local draft- while editing the staged draft:
- normal typing edits the shell-local draft instead of the worker session
Ctrl-Gthenssaves the edited draft and exits edit modeCtrl-Gthenccancels edit mode and restores the last saved draft
tabcycle focus
Optional shell host environment:
TUKU_SHELL_CODEX_BIN=/absolute/path/to/codexTUKU_SHELL_CODEX_ARGS="..."to append extra Codex argsTUKU_SHELL_CLAUDE_BIN=/absolute/path/to/claudeTUKU_SHELL_CLAUDE_ARGS="..."to append extra Claude args- shell Claude host also falls back to
TUKU_CLAUDE_BINandTUKU_CLAUDE_ARGSif the shell-specific vars are not set
Manual Smoke Test (End-to-End)
Run these in a second terminal while daemon is running.
- Start a task:
go run ./cmd/tuku start --goal "Implement manual smoke path" --repo /Users/kagaya/Desktop/TukuCopy task_id from output.
- Send message (intent + brief generation):
go run ./cmd/tuku message --task <TASK_ID> --text "Start implementation and prepare handoff packet."- Exercise run lifecycle in safe local mode (
noop):
go run ./cmd/tuku run --task <TASK_ID> --mode noop --action startCopy run_id, then complete:
go run ./cmd/tuku run --task <TASK_ID> --action complete --run-id <RUN_ID>- Create checkpoint:
go run ./cmd/tuku checkpoint --task <TASK_ID>- Continue assessment:
go run ./cmd/tuku continue --task <TASK_ID>- Create handoff packet (Claude target):
go run ./cmd/tuku handoff-create --task <TASK_ID> --target claude --mode resume --reason "manual smoke handoff"Copy handoff_id from output.
- Accept handoff (optional but useful for audit trail):
go run ./cmd/tuku handoff-accept --task <TASK_ID> --handoff <HANDOFF_ID> --by claude --note "manual acceptance"- Launch handoff:
go run ./cmd/tuku handoff-launch --task <TASK_ID> --handoff <HANDOFF_ID>- Inspect full state:
go run ./cmd/tuku inspect --task <TASK_ID>- Open the full-screen shell:
go run ./cmd/tuku shell --task <TASK_ID>- Read status summary:
go run ./cmd/tuku status --task <TASK_ID>- Optional: inspect proof ledger directly from SQLite:
sqlite3 "$HOME/Library/Application Support/Tuku/tuku.db" \
"SELECT sequence_no,type,run_id,substr(payload_json,1,140) FROM proof_events WHERE task_id='<TASK_ID>' ORDER BY sequence_no DESC LIMIT 20;"Expected Smoke Signals
handoff-launchresponse is canonical and explicitly avoids claiming downstream completion.tuku shellopens a full-screen interface with:- top status bar
- worker-first pane that attempts the selected live worker PTY session first
- toggleable right inspector
- toggleable activity/proof strip
- shell chrome shows a session id for the current shell run
- if a prior shell ended or fell back, the next shell run surfaces that prior persisted outcome in secondary chrome
- if another attachable shell session is already known for the same task, the shell surfaces that in calm secondary chrome instead of pretending this session is alone
- if another active but non-attachable shell session is known, the shell says so without implying reconnect support
- if the daemon only knows a stale shell session, the shell says so as uncertain liveness rather than presenting it as active
- if PTY startup fails, the footer shows fallback context and the center pane falls back to transcript mode
inspectincludes:- latest intent/brief/run/checkpoint
handoff-createresponse includes the durable handoff packet.handoff-launchresponse includes the launch payload and canonical launch outcome.- proof ledger includes handoff launch and acknowledgment events.
Current Milestone Limitations
- The shell is terminal-native, not a separate dashboard app.
- Live worker PTY support currently covers Codex and Claude only.
- The PTY host is pragmatic, not a full terminal emulator.
- ANSI/control-sequence handling is intentionally lightweight.
- Claude PTY support shares the same shell chrome and lifecycle model, but no reattach or reconnect path exists yet.
- Shell session registry metadata now survives daemon restarts via SQLite-backed durable storage.
- Stale-session classification is threshold-based only; there is no background reconciler yet.
- Only major shell lifecycle milestones are persisted into proof; raw PTY output and shell input are not.
- No background reconciliation services.
- No multi-agent orchestration.
- No full Claude session lifecycle tracking after launch invocation.
- Launch success means launch invocation completed, not downstream coding completion.
