eliaskc/kajji
{ "createdAt": "2025-12-30T19:10:19Z", "defaultBranch": "main", "description": "A simple terminal interface for jj", "fullName": "eliaskc/kajji", "homepage": "", "language": "TypeScript", "name": "kajji", "pushedAt": "2026-03-21T12:42:32Z", "stargazersCount": 7, "topics": [], "updatedAt": "2026-03-21T12:42:34Z", "url": "https://github.com/eliaskc/kajji"}
A simple jj terminal UI with custom diff rendering.
![normal mode]!(./assets/normal-mode.png)
Reviewing local code has never been as prominent as it is today. Coding agents are writing line upon line, and your sorry eyes are the ones that need to trudge through it.
Kajji makes this new reality less painful with polished jj navigation and manipulation alongside Shiki-powered diff rendering with syntax highlighting and word-level diffs. To allow for jj’s log to get the real estate it deserves when you’re looking at the diff, while also allowing the width required for side-by-side diff rendering, kajji has two view modes: normal and diff. Switch with ctrl+x and try it out.
![diff mode]!(./assets/diff-mode.png)
Why build this? While learning jj I found myself coming back to lazygit to do this quickly and easily - the options for jj didn’t quite scratch that lazygit itch of speed, simplicity and polish.
Kajji is my attempt to bring the UX of lazygit to jj, while also aiming for top-class diff rendering and exploring leveraging coding agents effectively. I’m building this for myself first and foremost, but I hope it can be helpful to others too.
Installation
Section titled “Installation”Requirements: jj
# recommended (standalone binary, no dependencies)curl -fsSL https://kajji.sh/install.sh | bash
# or via package managernpm install -g kajjibun install -g kajjipnpm add -g kajjiyarn global add kajji
# or run directly without installingnpx kajjibunx kajjiFrom source
Section titled “From source”Requirements: Bun
git clone https://github.com/eliaskc/kajji.gitcd kajjibun installbun devPrinciples
Section titled “Principles”- Polish & simplicity - Do less, but do it well.
- Intuitive UX - Sensible defaults, consistent patterns.
- Snappy - If it feels slow, it’s a bug.
Features
Section titled “Features”Core jj operations:
- View commit log with graph
- View diffs with syntax highlighting and word-level emphasis
- New / edit / describe / squash / abandon
- Rebase with revision picker
- Split (suspends TUI for jj’s native split)
- Undo / redo with preview
- Bookmarks (create, delete, rename, move)
- Git fetch / push
- Operation log with restore
- Conflict resolution
TUI polish:
- Vim-style navigation (j/k, ctrl+u/d)
- Mouse support (click, double-click, horizontal scroll)
- Collapsible file tree with status colors
- Help palette with fuzzy search (
?) - Focus modes for normal browsing vs diff viewing
- Line wrapping toggle (
w) and split/unified view (v) - Binary file detection
- Recent repository switcher
- Automatic update notifications
- Revset filtering and fuzzy search
- JSONC config with live reload and schema autocomplete
- Open files in editor from file view (
e/E) - Multi-select for batch operations
Run kajji in any jj repository:
kajji # current directorykajji /path/to/repo # specific directoryKajji includes a small CLI for scripting and agent workflows:
# List changes with addressable hunk IDskajji changes -r @
# Commentskajji comment list -r @kajji comment set -r @ --hunk h1 -m "note"kajji comment set -r @ --file src/App.tsx --line 12 -m "note"kajji comment delete -r @ --hunk h1kajji comment delete -r @ --file src/App.tsx --line 12kajji comment delete -r @ --file src/App.tsxkajji comment delete -r @ --all -yConfiguration
Section titled “Configuration”Kajji reads JSONC config from ~/.config/kajji/config.json (comments and trailing commas are supported).
- Open it from the command palette (
?) withopen config - Changes from
open configare reloaded when you return to kajji - Schema autocomplete is available via
$schemain the generated config
{ "$schema": "https://kajji.sh/schema.json", "ui": { "theme": "lazygit", // "lazygit" | "opencode" "showFileTree": true }, "diff": { "layout": "auto", // "auto" | "unified" | "split" "autoSwitchWidth": 120, // only used when layout is "auto" "wrap": true, "useJjFormatter": false // use jj's ui.diff-formatter output in Detail }, "whatsNewDisabled": false}Not yet wired from config (#16):
- keybind overrides
Keybindings
Section titled “Keybindings”| Key | Action |
|---|---|
j / k | Move down / up |
Tab | Cycle focus between panels |
Enter | Drill into commit / file |
Escape | Back / close modal |
ctrl+x | Toggle focus mode (normal / diff) |
ctrl+o | Open recent repository |
o / O | Open commit/PR on GitHub (prompt / direct) |
- | Toggle tree/list (Files) or jj formatter (Detail) |
w | Toggle line wrapping in diff (built-in renderer) |
v | Toggle split / unified diff (built-in renderer) |
ctrl+p | Show commands (or ?) |
q | Quit |
Operations
Section titled “Operations”| Key | Action |
|---|---|
n / N | New change / new before |
e | Edit change |
d | Describe change |
s | Squash |
a | Abandon change |
r | Rebase |
S | Split |
u / U | Undo / redo |
f | Git fetch |
F | Git fetch options |
p | Git push |
P | Git push options |
Bookmarks
Section titled “Bookmarks”| Key | Action |
|---|---|
c | Create bookmark |
d | Delete bookmark |
r | Rename bookmark |
b | Set bookmark on commit |
m | Move bookmark |
See GitHub issues for the roadmap.
Built With
Section titled “Built With”- OpenTUI + SolidJS - Modern TypeScript TUI framework
- Bun - Fast JavaScript runtime
- jj (Jujutsu) - Git-compatible VCS
Related Projects
Section titled “Related Projects”License
Section titled “License”MIT