A fullscreen terminal UI for jj (Jujutsu VCS), built in Go with Bubble Tea and Lip Gloss.
⚠️ This project was developed using AI assistance. It's been reviewed by a developer now and should be generally safe to use.
- Log view — scrollable commit graph with change IDs, authors, dates, bookmarks, and working copy highlighting
- Diff panel — file status summary + syntax-highlighted diff for any commit
- Bookmark management — create, delete, move, rename, set, track, untrack, and list bookmarks
- Git integration — fetch, push, and remote management from within the TUI
- AI commit messages — generate a description from a commit's diff via any OpenAI-compatible API
- Undo / redo — one-key
jj undo/jj redo - Graph rendering — native jj graph output with styled nodes (@/○/◆) and edges
brew tap 0xhckr/gojo https://github.com/0xhckr/gojo
brew install --cask gojoThis installs gojo and pulls in jj (jujutsu) as a runtime dependency
automatically. The explicit URL is needed because the cask lives in the
source repo rather than a separate homebrew- repo. See the post-install
caveat for an optional gj shorthand alias.
nix run github:0xhckr/gojo # run directly
# or, for development:
nix develop # drops you into a shell with go + jujutsu
go run .Requires Go 1.26+ and jj in $PATH.
go build -o gojo .
./gojo- Go 1.26+ (to build)
- jj (Jujutsu VCS) v0.41+ in
$PATH - A jj repository (run
gojoinside any.jjdirectory)
Gojo reads an optional TOML config file at ~/.config/gojo/gojo.toml. Values
may also be placed under a [tools.gojo] section in ~/.config/jj/config.toml
(the standalone gojo file takes precedence).
# API key for AI-generated commit messages (optional)
ai_api_key = "sk-or-..."
# Base URL of an OpenAI-compatible chat-completions endpoint
# (defaults to https://openrouter.ai/api/v1)
ai_base_url = "https://openrouter.ai/api/v1"
# Model to use
ai_model = "anthropic/claude-sonnet-4"
# Custom prompt template for AI commit messages (optional)
commit_prompt = "You are a software developer. Write a clear, concise commit message given the diff: "| Key | Action |
|---|---|
? |
Help |
q |
Quit / close panel |
ctrl+c |
Force quit |
| Key | Action |
|---|---|
↑/k, ↓/j |
Navigate commits |
G |
Jump to last commit |
Home |
Jump to first commit |
enter |
Open diff panel |
d |
jj describe (opens $EDITOR) |
D |
AI-generate commit message |
e |
jj edit (set working copy) |
n |
jj new (create change) |
a |
jj abandon (remove commit) |
b |
Bookmark mode |
g |
Git mode |
u |
jj undo |
r |
jj redo |
| Key | Action |
|---|---|
↑/k, ↓/j |
Scroll |
enter / q |
Close panel |
Press b to enter, then:
| Key | Action |
|---|---|
c <name> |
Create bookmark |
d <name> |
Delete bookmark |
f <name> |
Forget bookmark |
l |
List bookmarks |
m <name> |
Move bookmark to selected commit |
r <old> <new> |
Rename bookmark |
s <name> |
Set bookmark to selected commit |
t <name> |
Track remote bookmark |
T <name> |
Untrack remote bookmark |
tab |
Autocomplete (cycle suggestions) |
esc |
Cancel |
Press g to enter, then:
| Key | Action |
|---|---|
f |
jj git fetch |
p |
jj git push |
r |
Remote mode |
esc |
Cancel |
Press r in git mode, then:
| Key | Action |
|---|---|
a <name> <url> |
Add remote |
l |
List remotes |
r <name> |
Remove remote |
m <old> <new> |
Rename remote |
s <name> <url> |
Set remote URL |
esc |
Cancel |
main.go Entry point — starts the Bubble Tea program
internal/
jj/
jj.go jj CLI wrapper + log/status parsers
config.go config + TOML loader
ai.go AI commit-message generation (OpenAI-compatible API)
ui/
model.go Bubble Tea model: state, update, view, keybindings
render.go styled-line rendering helpers (Lip Gloss)
styles.go color palette and constants
logview.go commit list with graph
diff.go git-diff parser + chroma syntax highlighting
diffpanel.go diff viewer
helpview.go keybinding reference
go.mod Go module + dependencies
flake.nix Nix dev shell + package
Everything is pure Go — no native FFI, no Node runtime:
The TOML config parser, unified-diff parser, and AI client are implemented in-tree with the standard library.
MIT