init
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
# Claude Code Instructions for lazygitclj
|
||||
|
||||
## Clojure Development
|
||||
|
||||
- Use Clojure skills (nREPL evaluation) when editing code to verify changes compile and work correctly
|
||||
- Evaluate code in the REPL to test functions before committing changes
|
||||
- Run `bb start` to launch the application, `bb test` for unit tests
|
||||
|
||||
## Local TUI Library
|
||||
|
||||
- The TUI library is at `../clojure-tui/` (local dependency in bb.edn)
|
||||
- You have access to edit the local TUI library in conjunction with this repo
|
||||
- Use this access to debug issues, support new features, and simplify code
|
||||
- Look for opportunities to create better abstraction primitives for TUI layout
|
||||
|
||||
## Testing with VHS
|
||||
|
||||
- Use VHS to test all changes and verify behavior before finishing any task
|
||||
- Run `bb test:e2e` to run VHS tape tests
|
||||
- Run VHS tape files to capture terminal recordings and validate UI behavior
|
||||
- Do not consider a task complete until changes have been verified with VHS
|
||||
|
||||
## Understanding Expected Behavior
|
||||
|
||||
- Reference the lazygit repository and documentation to understand expected behaviors
|
||||
- Use VHS locally with lazygit to compare and verify that lazygitclj matches expected interaction patterns
|
||||
- When implementing features, check how lazygit handles the same functionality
|
||||
- See `PRD.md` for detailed lazygit behavior documentation
|
||||
|
||||
---
|
||||
|
||||
## Project Overview
|
||||
|
||||
lazygitclj is a lazygit-inspired TUI for Git written in Clojure, targeting Babashka for fast startup. It follows the Elm Architecture pattern (Model-Update-View).
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/lazygitclj/
|
||||
├── core.clj # Main TUI app: views, update logic, keybindings (883 lines)
|
||||
├── git.clj # Git operations wrapper via shell commands (478 lines)
|
||||
└── debug_tui.clj # Layout debugging utility
|
||||
test/
|
||||
├── lazygitclj/
|
||||
│ ├── core_test.clj # Model/update function tests
|
||||
│ └── git_test.clj # Git operations tests (uses temp repo fixture)
|
||||
└── run-tests.clj # Test runner
|
||||
```
|
||||
|
||||
## Build Commands
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `bb start` | Run lazygitclj TUI |
|
||||
| `bb debug` | Debug TUI layout issues |
|
||||
| `bb test` | Run unit tests |
|
||||
| `bb test:e2e` | Run VHS tape tests |
|
||||
|
||||
## Architecture: Elm Pattern
|
||||
|
||||
```clojure
|
||||
(tui/run {:init (initial-model)
|
||||
:update update-model
|
||||
:view view})
|
||||
```
|
||||
|
||||
- **Model**: Application state as a map
|
||||
- **Update**: Pure functions returning `[new-model command]` tuples
|
||||
- **View**: Pure functions rendering hiccup-style VDom
|
||||
|
||||
## Model Structure
|
||||
|
||||
```clojure
|
||||
{:panel :files ;; Current panel: :files, :branches, :commits, :stash
|
||||
:cursor 0 ;; Cursor position in current panel
|
||||
:message nil ;; Transient message display
|
||||
:input-mode nil ;; :commit, :new-branch, :rename-branch, etc.
|
||||
:input-buffer "" ;; Text input during modal entry
|
||||
:menu-mode nil ;; :stash-options, :reset-options, :help
|
||||
:commits-tab :commits ;; :commits or :reflog
|
||||
:branches-tab :local ;; :local, :remotes, or :tags
|
||||
:branch "main" ;; Current branch
|
||||
:sha "abc1234" ;; HEAD SHA
|
||||
:ahead-behind [0 0] ;; [ahead, behind] upstream
|
||||
:staged [...] ;; Staged files
|
||||
:unstaged [...] ;; Unstaged/untracked files
|
||||
:commits [...] ;; Recent commits
|
||||
:branches [...] ;; Local branches
|
||||
:remote-branches [...] ;; Remote branches
|
||||
:tags [...] ;; Tags
|
||||
:stashes [...] ;; Stash entries
|
||||
:reflog [...] ;; Reflog for undo/redo
|
||||
:diff nil} ;; Currently displayed diff
|
||||
```
|
||||
|
||||
## Key Functions in core.clj
|
||||
|
||||
| Function | Purpose |
|
||||
|----------|---------|
|
||||
| `initial-model` | Create initial application state |
|
||||
| `load-git-data` | Load all git state via git.clj |
|
||||
| `refresh` | Reload git data and update diff |
|
||||
| `update-model` | Main dispatcher for keyboard input |
|
||||
| `update-files` | Handle files panel (stage, unstage, commit) |
|
||||
| `update-commits` | Handle commits panel (checkout, cherry-pick, revert) |
|
||||
| `update-branches` | Handle branches panel (checkout, create, delete, merge) |
|
||||
| `update-stash` | Handle stash panel (apply, pop, drop) |
|
||||
| `file-items` | Combine staged/unstaged files with type metadata |
|
||||
| `current-items` | Get items for current panel |
|
||||
| `view` | Render UI based on state and dimensions |
|
||||
|
||||
## Keybindings
|
||||
|
||||
**Global**: `q` quit, `?` help, `r` refresh, `h/l` panel nav, `j/k` cursor, `z/Z` undo/redo, `p/P` pull/push, `D` reset menu
|
||||
|
||||
**Files**: `space` stage/unstage, `a` stage all, `c` commit, `d` discard, `s/S` stash
|
||||
|
||||
**Commits**: `space` checkout, `g` reset to, `C` cherry-pick, `t` revert, `r` reword, `[/]` tabs
|
||||
|
||||
**Branches**: `enter` checkout, `n` new, `d` delete, `R` rename, `M` merge, `f` fast-forward, `[/]` tabs
|
||||
|
||||
**Stash**: `space` apply, `g` pop, `d` drop, `n` branch from stash
|
||||
|
||||
## Git Operations (git.clj)
|
||||
|
||||
All git operations wrap `babashka.process/shell` and return `nil` on error.
|
||||
|
||||
**Categories**:
|
||||
- Status: `current-branch`, `head-sha`, `ahead-behind`
|
||||
- Files: `status-files`, `staged-files`, `unstaged-files`
|
||||
- Staging: `stage-file`, `unstage-file`, `stage-all`
|
||||
- Diff: `diff-file`, `diff-staged`, `show-commit`, `diff-branch`
|
||||
- Actions: `commit`, `discard-file`, `pull`, `push`
|
||||
- Stash: `stash-list`, `stash-push`, `stash-pop`, `stash-apply`, `stash-drop`
|
||||
- Reset: `reset-soft`, `reset-mixed`, `reset-hard`
|
||||
- Branches: `create-branch`, `checkout-branch`, `delete-branch`, `merge-branch`
|
||||
- Tags: `list-tags`, `create-tag`, `delete-tag`
|
||||
|
||||
## TUI Library Primitives
|
||||
|
||||
```clojure
|
||||
;; Containers
|
||||
[:row {:widths [30 :flex] :gap 1} left right]
|
||||
[:col {:heights [3 :flex :flex 4]} top mid1 mid2 bottom]
|
||||
[:box {:border :double :title "Title"} content]
|
||||
|
||||
;; Text with styling
|
||||
[:text {:fg :green :bold true} "content"]
|
||||
```
|
||||
|
||||
- `:flex` keyword items share remaining space equally
|
||||
- Borders: `:single`, `:double`, `:rounded`
|
||||
- Colors: `:red`, `:green`, `:yellow`, `:blue`, `:magenta`, `:cyan`, `:white`
|
||||
|
||||
## Responsive Layout
|
||||
|
||||
- **Narrow (< 70 cols)**: Single-column stacked layout
|
||||
- **Wide (>= 70 cols)**: Two-column (left panels 30 cols, right diff flex)
|
||||
|
||||
## File Status Format
|
||||
|
||||
Files parsed from `git status --porcelain`:
|
||||
```clojure
|
||||
{:index \M :worktree \space :path "file.txt"}
|
||||
```
|
||||
|
||||
## Diff Coloring
|
||||
|
||||
- `+` lines: green (additions)
|
||||
- `-` lines: red (deletions)
|
||||
- `@@` lines: cyan (hunk headers)
|
||||
- `diff`/`commit` lines: yellow (headers)
|
||||
|
||||
## Conventions
|
||||
|
||||
- Predicates end with `?` (e.g., `can-fast-forward?`)
|
||||
- Private functions prefixed with `-` (e.g., `-sh`, `-parse-status-line`)
|
||||
- Update functions return `[new-model command]` tuples
|
||||
- Messages are transient (cleared on next refresh)
|
||||
Reference in New Issue
Block a user