All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- A review workspace. A list on the left (the queue, the structure tree or a flat list of changed files, keys
1to3) and the code of the selected unit on the right, which follows the cursor.Kopens a symbol panel with the typed signature, the documentation comment and the reasons for the priority. The lists are cards, the sections have headers instead of boxes, andui.density(comfortableorcompact) sets how much air the rows get. - Decisions window (
4). An agent writes.klaub/decisions/<snapshot>.json, the technical decisions of the change, each told for a reader who knows nothing about it. The reader shows one decision per full screen: approve (a), reject (d) or comment (c), and send the rejected and commented ones back to the agent (f).klaub decisionsvalidates and shows the document. A document for another snapshot is not shown. New[decisions]configuration. - Flow window (
5). A form (focus, kind, detail, reach, size, start, errors, externals) builds the request for the agent; the diagram shows when the agent saves it.klaub flow prompttakes the same choices as flags. - Ask the agent (
t, inklaub wrap). Puts the file, flow or decision on screen in the agent's input as context for a question. It never pressesEnter.integration.ask_agent_confirmsmakes it ask first. Shift+←goes to the agent andShift+→to the reviewer in a wrapped session, with no prefix.
- The requests Klaub puts in the agent's input are self-contained and fit one line of at most 3800 characters; the decisions skill is not needed.
- The reader is a reader only. The Impact, Comments, Context, Tests, Follow-up and Coverage screens, and everything that wrote feedback from the reader (commenting a line, finishing a review, delivering to the agent), are gone from it. The review session, the stored reviews and the
feedback,tests,flowandreviewscommands are unchanged.klaub review --waitcan only report a draft. 3opens the file list; the code has no key of its own (Enter,TaborF4). A[keys]table that moves a removed action is rejected like any unknown id.- In
klaub wrap,Prefix+I,C,T,BandLare gone: they opened removed screens.
integration.paste_requires_confirmation: nothing read it. It is still accepted in a config file so earlier configs load.
Prefix+Qends the whole session, agent included, after ay/nconfirmation.Prefix+donly detaches and leaves the agent running.
Prefix+randPrefix+aopen the reviewer and go back to the agent likePrefix+RandPrefix+A; before, only the capital letters were bound.
- The embedded tmux no longer exits unexpectedly on Apple Silicon. With a full-screen agent (Claude Code, Codex) running, switching to the reviewer with
Ctrl+B Rended the session with[server exited unexpectedly]. The cause was jemalloc 5.4 in the macOS build of tmux 3.8; the embedded tmux now uses the system allocator on every macOS target. A Homebrew tmux throughKLAUB_TMUX_PATHwas a workaround and is no longer needed.
scripts/test-tmux-interactive.pyruns the embedded tmux on a pseudo-terminal with a full-screen program and switches windows repeatedly, failing if the server dies. Thetmux assetworkflow runs it for every release target, so a release cannot ship a tmux that crashes there.
- Portuguese and Spanish. The reader, its prompts and status messages,
klaub doctorand the other commands' diagnostics, and--helpspeak English, Portuguese (Brazil) or Spanish.ui.languagetakesauto(the default),en,ptores;autofollowsKLAUB_LANGand thenLC_ALL,LC_MESSAGESandLANG, with English as the fallback. A language set in the user or project configuration wins over the environment. JSON output, exports and the text pasted into the agent stay in English. See Languages. - Yes/no prompts of the command line accept
sandsim(Portuguese) ands,siandsí(Spanish) next toyandyes.
- Every sentence the user reads is now a typed function in
domain::i18n(tuiandcli) that takes aLocale, with its translations next to it. A missing language or a misspelt placeholder fails to compile, andtests/i18n.rschecks placeholders and spacing across languages. Mode::label,Filters::summaryand the labels in the reader take aLocale;tui::DELIVERY_OPTIONSis nowtui::delivery_options(locale), andReviewSession::finish_warningsreturns typed warnings (warnings_before_finishstill returns English text).
- Named colour themes.
ui.themeacceptscatppuccin_mocha,catppuccin_latte,dracula,gruvbox_dark,nordandrose_pine, next todark,lightandhigh_contrast.darkis the Tokyo Night palette. The palette (:) has "Switch colour theme", which cycles through them for the current session; setui.themeto keep one. The light themes assume a light terminal. ColorDepth. The colour themes are written in true colour and use the 256-colour palette when the terminal does not report 24-bit colour (COLORTERM,TERM,TERM_PROGRAM).
- A premium look for the reader. A title bar with the brand and a progress gauge, pill tabs, a status bar that shows the mode and its keys (hints that do not fit are dropped whole), rounded titled panels, scrollbars, and a details panel next to the queue. Selected rows get an accent bar and a full-width background, and priority and status are chips. The code view tints added, removed and changed lines, has a gutter and a NEW CODE / OLD CODE badge, and shows the comment under the cursor as a callout. Overlays dim the screen behind them, and empty states are centred.
high_contraststill uses no colour. domain::config::Themehas new variants, so an exhaustivematchon it outside Klaub needs new arms.
- Klaub is on crates.io.
cargo install klaub --lockedbuilds it from the registry. A build from source has no bundled session runtime, soklaub wraplooks for one onPATH(klaub reviewdoes not need it). - A logo. An ASCII mark in light and dark, a banner and a social preview image, rendered from
assets/logo.txtbyscripts/render-logo.py.
-
A README for the person who reviews. It now opens with what Klaub is for, a three-step quickstart (install Klaub, install the skills, review), a full install section (Homebrew, the install script and its variables, Cargo, release archives with checksum and provenance checks, update and uninstall), a comparison with other ways to review agent code and a FAQ. The Portuguese README is gone.
-
Klaub is a single crate. The fifteen workspace crates are modules of one
klaubpackage (domain,services,app,adapters,tui,cli), the way the layers were already drawn. The direction of the dependencies between them is no longer enforced by the compiler, sotests/architecture.rsnow reads the sources and fails when a layer names one it must not, when something other thanclinames an adapter, or whendomain,servicesorappreach for the file system, processes or the environment. Publishing to crates.io becomes one crate and one trusted publisher instead of fifteen. -
The library is now called
klaub(it wasklaub_cli), andcargo build,cargo testandcargo bench --bench latencyneed no-p. -
Crash reports name the source file relative to the package (
src/app/session.rs:10), also when Klaub was built from crates.io.
- Running tests could stall and be reported as a failure. The test runner waited for the command to exit before reading its output, so a command that wrote more than a pipe holds (about 64 KiB) blocked on its next write until the time limit. Both streams are now read while the command runs, only the last 64 KiB is kept, and a timeout or a cancel ends the whole process group instead of only the command, so a background process it started no longer outlives the run.
klaub tests list|run --review IDignored the id. The id was only checked for its shape, and the command answered for whatever the worktree looked like now. It now loads that review, refuses an id that does not exist, and refuses a review whose files have changed since, before any session is opened.--selectis also applied before the check for several test commands, so the hint to use it works.- A worktree that changed while it was being analysed went unnoticed for a few seconds. Files that did not change are read from disk after the snapshot is taken, so an agent that keeps editing could leave an impact graph that mixes two moments. The check for changes now runs as soon as the analysis finishes. The banner says that impact may mix versions, and finishing the review warns about it.
- Install with cargo. The binary package is now called
klaub, socargo install --git https://github.com/myrk-kale/klaub klaub --lockedworks. A build without the bundled tmux uses the one onPATHand says so inklaub doctor. CI packages the whole workspace on every pull request, and a Trusted Publishing workflow for crates.io is in place; the crates are not published yet. - The two skills install with the Vercel skills CLI:
npx skills add myrk-kale/klaub. CI checks that the CLI finds both.
- The
klaub-clipackage is nowklaub(the library keeps the nameklaub_cli). Use-p klaubwhere you used-p klaub-cli. - The crate keywords no longer name the implementation.
klaub skills installand its--harnessand--forceoptions. Usenpx skills add myrk-kale/klaub, which also covers agents beyond Codex and Claude Code.
- The
klaub-feedbackskill named a command that does not exist (klaub feedback show); it isklaub feedback <review-id>.
- Java. Classes, interfaces, enums, records, methods and constructors with their annotations (kept as decorators), signatures without the annotations, visibility (package-private is
Internal),throw new Xandthrows, calls with receivers, imports (classes, packages and static members),public static void main, Spring (@GetMapping,@RequestMappingwith the class prefix and verb) and JAX-RS (@GETwith@Path) routes, JUnit@Testmethods, and the same risk markers as the other languages (swallowedcatch, SQL built by concatenation orString.format, a shell started byProcessBuilderorRuntime.exec, a secret in a string literal, I/O in a loop). Imports resolve to files under any source root. Test files aresrc/test/**/*.java,*Test.java,*Tests.javaand*IT.java(tests.java_patterns). Reflection, dependency injection and code generation are not followed, so calls through them stay unresolved. Parser version 3. - Every mode-specific key is configurable.
[keys]also moves movement (down,up,scroll_left,scroll_right),select_lines,open_file,inspect_contract,pivot_impact,request_flow, the Context and Comments edit keys and the four follow-up decisions. A moved key works in the modes it belongs to and its old character stops acting there. The footer is built from the keymap, so it no longer names keys you moved. - Optional mouse (
[ui] mouse = true): the wheel scrolls, a click on a tab switches to it, a click on a row selects it, a second click opens it, a click on a code line moves the cursor. It only does what a key already does. - Hold to see the previous version (
[ui] hold_to_peek = true,B), where the terminal reports key releases (kitty keyboard protocol). Elsewhere, inside tmux included, the key says it cannot be held andvstill toggles. The protocol is dropped while a text field is open so compose andAltGrcharacters still type. - A
HarnessAdapterseam (klaub_core::harness) withGenericHarnessas the only adapter. The paste confirmation names the adapter and shows a busy warning if an adapter reports one. The paste contract is unchanged, and no Codex or Claude Code adapter ships. - Linux aarch64 and macOS Intel builds join Linux x86_64 and macOS Apple Silicon in the release, the install script and the Homebrew formula. The macOS Intel build uses the system memory allocator, because a build with jemalloc crashes in the forked child on that platform. Source downloads in the tmux build fall back to mirrors, and every source is checked against its SHA-256.
klaub doctorwarns under WSL, and when the directory is on the Windows file system.KLAUB_BENCH_REPOruns the latency harness on real repositories;docs/benchmarks.mdhas a run on flask, django, tokio and vue core.- Contract inspector (
i). The declaration of a callable is split into parameters and return type for Python, JavaScript/TypeScript, Rust, Go and Java (wherethrowsis listed with the exceptions). Decorators, the routes a symbol serves, the exceptions its body raises or throws (and the error a RustResultor a Goerrordeclares), observable effects (risk markers and I/O-looking calls) and, for a type, its public members and what kind of data type it looks like are shown as+/-lists before and after. The entrypoints that can reach the symbol are named with their certainty. A declaration it cannot read is reported as unknown. - Contracts for files without symbols. The same key opens a contract for migrations (SQL, Alembic, Django, Rails), dependency manifests (
Cargo.toml,package.json,pyproject.toml,requirements*.txt,go.mod) and settings files (JSON, TOML, YAML,.env): what was added, removed or changed. Secret values and every.envvalue are never shown. Anything it cannot read falls back to the textual diff and says so. klaub-parserecords the exceptions a body raises and the I/O-looking calls it makes (parser version 2, so cached parses are refreshed).- Configurable keys.
[keys]moves any global reader action to another single character. The table is validated as a whole (unknown action, not one printable character, reserved key, two actions on one key) and the reader refuses to open with an invalid one. The help and the palette show the configured keys. Seedocs/configuration.md, which also documents every other configuration section. - A first-review notice. The first review of a worktree with no
.klaub/explains that the folder is local data, that Klaub does not add it to.gitignoreor.git/info/exclude, never commits it, and always leaves it out of the changes it reviews. - False positives. A finding can be silenced for one review from "Why this priority" (
w): press its number, confirm, and its rule is silenced. The queue is recomputed on the same snapshot (the worktree is not read again), the choice is saved in the review and carried into the next round, and "Bring back silenced rules" in the palette undoes it. Only a rule that produced a finding in the review can be silenced. - Flow as a tree. The Flow view indents branches under the step they leave, marks a step reached twice as
↺ shown above, shows how each row was reached (calls ◐), folds and unfolds branches with←,→andSpace, and shows apath:of breadcrumbs from the first step to the selected one.Enteropens the selected step's real symbol whatever is folded. - History.
<and>walk back and forward through the units visited, as in a browser. A new move forgets what was ahead; the history holds the last 64 units. klaub review --waitstays until the reader is closed and reports how the review ended: exit 0 when finished, 3 when closed as a draft, with the review export on standard output under--format jsonand nothing else there.klaub reviews export --format sarif: a SARIF 2.1.0 log, one result per comment. The level is a hint about attention (P0error, P1warning, the restnote), not a defect classification; the exact priority travels inproperties.klaub doctoralso proves every grammar parses a sample, inspects the parse cache read-only (a damaged one is reported and left alone), says which clipboard program Copy would use, notes an SSH session and what it means for the clipboard, and counts saved crash reports. Seedocs/ssh.md.- Local crash reports. If Klaub panics it saves a short report (version, platform, subcommand name, a bounded panic message and the place in Klaub's source, with the home directory as
~) under its state directory.klaub crashes listandklaub crashes showread them. Nothing is sent anywhere. - Latency benchmarks for the project's targets:
cargo bench -p klaub-app --bench latencyandcargo bench -p klaub-tui --bench ui, with one recorded run and its caveats indocs/benchmarks.md. fixtures/with flow documents (one current, one stale, one with a missing symbol, four that must be refused) and JUnit and Coverage.py reports, each read by a test; anddocs/adding-a-language.md.
SnapshotProvider::read_project_filesreads many project files at once, and the Git adapter answers with onegit cat-file --batch. Reviewing a branch or a commit range no longer starts a process per project file.- Test association checks a file's imports once per file instead of once per test case.
onow opens the current unit in its whole file and stays there, whereSstill toggles between the symbol and the file. The contract inspector, which had takeno, is nowi.- The confirmation before preparing text in the agent shows the process running in the pane and warns when it is a shell, so the text is not pasted onto a shell prompt by surprise.
- The
Securityworkflow runs on every pull request instead of only those that touch a manifest, so its checks can be required onmain.
- A symbol that moved from one file to another made the analysis read the wrong file's symbol table. On a real project (tokio) it panicked with an out-of-bounds index; on a small one it quietly showed the contract and the old code of the wrong symbol. Each side of a symbol is now read from the file it names, and the old code of a moved symbol is shown from the file it left.
klaub-storage: atomic, advisory-locked JSON reviews (symlinked.klaub/refused), a SQLite parse cache that heals itself, confined readers for briefs, reports and flows, and layered configuration loading.klaub-app: the analysis use case (parallel, cached parsing; matching; call graph; test evidence; rules; queue) andReviewSession(comments with anchors, reviewed marks, brief, coverage, finishing, delivery to the agent only after confirmation, drift detection and refresh, next rounds with relocated comments, test panel, flow state, exports), plus a code view with change marks and syntax colours.klaub-graph: call and dependency graph with per-edge origin (resolved/heuristic), ambiguity counted instead of guessed, entrypoints from the parser and frompyproject.toml/package.json, reverse impact with entrypoint paths, scope and coverage, and module cycles.klaub-rules: explainable findings reconciled intointroduced/preexisting/removed/unknown, an itemised score and the P0–P3 queue, whereP0needs critical evidence; architecture rules (forbidden dependencies, new cycles).klaub-review: comments, anchors with relocation and stale detection, finishing into an idempotent feedback payload, human-confirmed delivery states, follow-up decisions with history, JSON and Markdown exports.klaub-context: brief import (never ticks criteria for you) and human review coverage with non-blocking warnings.klaub-tests: heuristic test association with method and confidence, JUnit and Coverage.py report import with staleness, honest evidence status, and a no-shell run request built only from configuration.klaub-flow: strict, bounded validation of agent-written flow documents (paths, terminal sequences, snapshot freshness, divergences from the index), request prompt and an indented layout for the TUI.klaub-parse: tree-sitter extraction of symbols, calls, imports, entrypoints and risk markers for Python, JavaScript, TypeScript/TSX, Rust and Go, behind theSourceParserport. Fault tolerant and depth-bounded; nested symbols never change the fingerprint of the symbol that contains them.klaub-match: temporal symbol matching with confidence and evidence (identity, similarity within a file, moves across files) that classifies each symbol as added, removed, modified, moved, renamed, signature-changed, rewritten or format-only, explains near misses it refuses to call moves, and computes the per-line diff for the reader.klaub-git: immutable, content-addressed snapshots through the Git CLI for the worktree, staged, unstaged, branch and commit-range scopes; rename detection, untracked and ignored-file handling, binary/oversized/symlink metadata, generated-file flags, a cheap drift probe, and project file listing and reading for call-graph building. Repositories are treated as untrusted: external diff drivers, textconv and fsmonitor never run, option-like revisions are rejected and symlinks cannot lead out of the worktree.klaub wrap <command>runs any interactive program in a private tmux session with anagentand areviewwindow;klaub session list|attach|kill,klaub doctor,klaub version,klaub completions.klaub-tmux: verified embedded tmux (SHA-256 checked before every execution, private0700extraction), one private server per session, pane-identity checks, and a bracketed, single-line, never-Enterpaste. Nine integration tests run against a real tmux server and assert the exact bytes the harness receives.klaub-tui: the fullscreen semantic reader (Elm-style state, input and view, drawn with Ratatui). Ten modes over the review queue, a command palette and help generated from one key table, and overlays for commenting, confirming and finishing. Every string that comes from the repository, a comment or a document is sanitised before it is drawn, and a terminal below 50×10 is told to resize instead of rendering a broken frame.klaub reviewnow opens that reader over the worktree: it wires the Git, tree-sitter and storage adapters, resumes an existing review, and insideklaub wrapcan prepare feedback in the agent's input after confirmation. On its own it can only copy or show the feedback. Running the configured tests goes through a shell-less process adapter with a time limit.--base,--scopeand--briefchoose the comparison and import a local brief.klaub reviews list|show|export,klaub feedback,klaub tests list|run,klaub flow status|context|validate|promptandklaub skills install.tests runshows the exact command and asks before it starts.flow promptonly prints text. Installing a skill refuses to replace one the user has edited unless--forceis given.- tmux session chords
Prefix+I,Prefix+C,Prefix+T,Prefix+BandPrefix+Lopen the reviewer directly on impact, comments, tests, context and flow. - Packaged skills
klaub-flowandklaub-feedback, installed on request into the Codex or Claude Code skills directory. - Render tests for the reader: queue order, before/after, comments, reviewed marks, hostile terminal sequences, a too-small terminal, finishing without ever sending Enter, the drift banner, and the contract panel.
- A contract inspector (
oin the code view) showing, for one changed symbol, the change kind, the confidence, the signature before and after, the effects named by markers the symbol already carries, and the direct callers. What the analysis cannot know is stated as unknown rather than guessed. - Search also matches comment ids, test ids and acceptance-criterion text.
mbookmarks a unit and,jumps to the next bookmark. Reopening a review returns to the unit you were on. - The execution sort order ranks a change reached from more entrypoints first.
- Fixture measurements for symbol matching, temporal classification, test association and anchor stability (
crates/klaub-app/tests/metrics.rs), plus notes on what has not been measured (docs/benchmarks.md). - Release pipeline:
scripts/build-tmux.sh(pinned tmux 3.8, libevent 2.1.13, ncurses 6.6), thetmux assetandReleaseworkflows (checksums, build-provenance attestations, changelog-based notes),scripts/install.sh. klaub-core: the I/O-free domain model (snapshots, symbols, semantic changes, findings, reviews, test evidence, flow contract), the configuration schema with line/column errors and layered merging, terminal-text sanitisation, and the ports every adapter implements.- Executable architecture rules (
crates/klaub-cli/tests/architecture.rs): dependency direction between layers and an I/O-free core are enforced in CI. - Project foundation: Cargo workspace, lint policy, continuous integration, security scanning, community files, architecture documentation and decision records.