forestui 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,41 @@
1
+ name: Publish to PyPI
2
+
3
+ permissions:
4
+ id-token: write
5
+
6
+ on:
7
+ release:
8
+ types: [published]
9
+
10
+ jobs:
11
+ release:
12
+ name: Build and Publish
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - name: Check out repository
17
+ uses: actions/checkout@v6
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v7
21
+
22
+ - name: Set up Python
23
+ run: uv python install
24
+
25
+ - name: Set version from GITHUB_REF
26
+ run: |
27
+ # GITHUB_REF is refs/tags/v1.2.3 - extract "1.2.3"
28
+ echo "GITHUB_REF: ${{ github.ref }}"
29
+ export VERSION=$(echo ${{ github.ref }} | sed -e 's,.*/\(.*\),\1,' -e 's/^v//')
30
+ echo "Setting version to $VERSION"
31
+ sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
32
+ echo "======================================"
33
+ echo "Version line in pyproject.toml:"
34
+ grep "^version" pyproject.toml
35
+ echo "======================================"
36
+
37
+ - name: Build wheels and source tarball
38
+ run: uv build
39
+
40
+ - name: Publish to PyPI
41
+ uses: pypa/gh-action-pypi-publish@v1.13.0
@@ -0,0 +1,10 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.14.11
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
@@ -0,0 +1 @@
1
+ 3.14
@@ -0,0 +1,200 @@
1
+ # CLAUDE.md - AI Development Guidelines
2
+
3
+ This file provides context for AI assistants (like Claude) working on forestui.
4
+
5
+ ## Project Overview
6
+
7
+ forestui is a terminal UI for managing Git worktrees, built with Python and Textual. It's designed to run inside tmux and provides a cohesive experience for developers managing multiple worktrees.
8
+
9
+ ## Tech Stack
10
+
11
+ - **Python 3.14+** with strict type hints (mypy strict mode)
12
+ - **Textual 7.2+** for the TUI framework
13
+ - **Pydantic 2.12+** for data models and validation
14
+ - **Click 8.1+** for CLI parsing
15
+ - **uv** for package management
16
+
17
+ ## Project Structure
18
+
19
+ ```
20
+ forestui/
21
+ ├── forestui/
22
+ │ ├── __init__.py # Package init, version
23
+ │ ├── __main__.py # Module entry point
24
+ │ ├── app.py # Main Textual application
25
+ │ ├── cli.py # Click CLI with --self-update
26
+ │ ├── models.py # Pydantic data models
27
+ │ ├── state.py # Application state management
28
+ │ ├── theme.py # CSS styling
29
+ │ ├── components/
30
+ │ │ ├── modals.py # Modal dialogs (settings, add repo, etc.)
31
+ │ │ ├── sidebar.py # Repository/worktree sidebar
32
+ │ │ ├── repository_detail.py
33
+ │ │ └── worktree_detail.py
34
+ │ └── services/
35
+ │ ├── settings.py # User preferences + runtime forest path
36
+ │ ├── git.py # Async git operations
37
+ │ ├── claude_session.py # Claude Code session tracking
38
+ │ └── tmux.py # tmux window management
39
+ ├── pyproject.toml # Project config, dependencies
40
+ ├── Makefile # Development commands
41
+ ├── install.sh # Installation script
42
+ └── README.md
43
+ ```
44
+
45
+ ## Development Commands
46
+
47
+ ```bash
48
+ make lint # Run ruff linter
49
+ make typecheck # Run mypy type checker
50
+ make check # Run both lint and typecheck
51
+ make format # Format code with ruff
52
+ make dev # Install dev dependencies
53
+ make run # Run the app
54
+ make clean # Clean build artifacts
55
+ ```
56
+
57
+ Always run `make check` before committing changes.
58
+
59
+ ## Code Conventions
60
+
61
+ ### Type Hints
62
+ - All functions must have type hints (mypy strict mode)
63
+ - Use `from __future__ import annotations` for forward references
64
+ - Prefer `X | None` over `Optional[X]`
65
+
66
+ ### Imports
67
+ - Use absolute imports: `from forestui.services.git import GitService`
68
+ - Imports are auto-sorted by ruff (isort rules)
69
+
70
+ ### Textual Patterns
71
+ - Components emit `Message` classes for parent communication
72
+ - Use `@work` decorator for async operations that update UI
73
+ - CSS is defined in `theme.py` as `APP_CSS`
74
+
75
+ ### Async Operations & Reactive UI
76
+
77
+ **IMPORTANT:** Never block the UI with slow operations. The app must start instantly.
78
+
79
+ For any operation that may take time (CLI calls, network requests, file I/O):
80
+ 1. Render UI immediately with a loading state ("Loading...", "Checking...")
81
+ 2. Dispatch work to a background task using `@work` decorator
82
+ 3. When the task completes, update the UI reactively
83
+
84
+ Example pattern:
85
+ ```python
86
+ # In compose(), show loading state:
87
+ yield Label("Loading...", id="my-loading")
88
+
89
+ # In on_mount() or elsewhere, dispatch background work:
90
+ self._fetch_data()
91
+
92
+ @work
93
+ async def _fetch_data(self) -> None:
94
+ data = await slow_operation()
95
+ # Update UI when ready
96
+ self.query_one("#my-loading").update(f"Result: {data}")
97
+ ```
98
+
99
+ This applies to:
100
+ - External CLI integrations (gh, git, etc.)
101
+ - Network requests
102
+ - File system operations that may be slow
103
+ - Any operation that could fail or hang
104
+
105
+ The UI should always remain responsive. Users should never see the app freeze.
106
+
107
+ ### Services
108
+ - Services are singletons accessed via `get_*_service()` functions
109
+ - State is persisted automatically via `_save_state()` methods
110
+
111
+ ## Key Design Decisions
112
+
113
+ ### tmux Requirement
114
+ forestui requires tmux and will auto-exec into a tmux session if not already inside one. This enables:
115
+ - TUI editors opening in tmux windows
116
+ - Session persistence
117
+ - Fast switching between editor/app/claude windows
118
+
119
+ ### Multi-Forest Support
120
+ The forest directory is a CLI argument, not a setting:
121
+ ```bash
122
+ forestui ~/forest # default
123
+ forestui ~/work # different forest
124
+ ```
125
+
126
+ Each forest has its own `.forestui-config.json` state file.
127
+
128
+ ### Coexistence with forest (macOS)
129
+ - forestui uses `.forestui-config.json`
130
+ - forest uses `.forest-config.json`
131
+ - Both can share the same `~/forest` directory safely
132
+
133
+ ## Common Tasks
134
+
135
+ ### Adding a New Service
136
+ 1. Create `forestui/services/myservice.py`
137
+ 2. Implement singleton pattern with `get_myservice()` function
138
+ 3. Export from `forestui/services/__init__.py`
139
+
140
+ ### Adding a New Component
141
+ 1. Create `forestui/components/mycomponent.py`
142
+ 2. Define `Message` classes for events
143
+ 3. Handle messages in `app.py` with `on_mycomponent_*` methods
144
+
145
+ ### Adding a New CLI Option
146
+ 1. Add to `@click.option` in `forestui/cli.py`
147
+ 2. Handle in the `main()` function
148
+
149
+ ### Modifying Settings
150
+ 1. Update `Settings` model in `models.py`
151
+ 2. Update `SettingsModal` in `components/modals.py`
152
+ 3. Settings are auto-persisted to `~/.config/forestui/settings.json`
153
+
154
+ ## Testing
155
+
156
+ Currently no test suite. When adding tests:
157
+ - Use pytest
158
+ - Place tests in `tests/` directory
159
+ - Add pytest to dev dependencies
160
+
161
+ ## Versioning
162
+
163
+ Version is defined in **both** `forestui/__init__.py` and `pyproject.toml`:
164
+ ```python
165
+ __version__ = "0.1.0"
166
+ ```
167
+
168
+ **IMPORTANT:** The `main` branch represents the release. Every feature, fix, or change merged to `main` **must** include a version bump in both files:
169
+ - **Patch** (0.0.X): Bug fixes, dead code removal, minor cleanup
170
+ - **Minor** (0.X.0): New features, enhancements
171
+ - **Major** (X.0.0): Breaking changes
172
+
173
+ This is required for `--self-update` to work correctly - it compares the local version against the remote to detect updates. If you forget to bump the version, users won't see the update.
174
+
175
+ ### Workflow: Test Before Commit
176
+
177
+ **Do NOT bump the version, commit, or push until the user has tested and approved the changes.**
178
+
179
+ Every commit to `main` with a bumped version is an actual release that will propagate to all users via `--self-update`. The workflow should be:
180
+
181
+ 1. Make code changes
182
+ 2. Run `make check` to verify lint/typecheck pass (do this BEFORE bumping version - if linter reformats code, you don't want to bump twice)
183
+ 3. **Ask the user to test the changes** before proceeding
184
+ 4. Bump version in both `forestui/__init__.py` and `pyproject.toml`
185
+ 5. Commit and push
186
+
187
+ This keeps a human in the loop for quality control before releasing.
188
+
189
+ ## Git Commits
190
+
191
+ - Do NOT include `Co-Authored-By` attribution
192
+ - Do NOT include "Generated with Claude Code" footer
193
+ - Write clear, concise commit messages
194
+
195
+ ## References
196
+
197
+ - [forest (macOS)](https://github.com/ricwo/forest) - Original inspiration
198
+ - [Textual Documentation](https://textual.textualize.io/)
199
+ - [Pydantic Documentation](https://docs.pydantic.dev/)
200
+ - [Click Documentation](https://click.palletsprojects.com/)
@@ -0,0 +1,46 @@
1
+ .PHONY: lint typecheck check format install dev clean
2
+
3
+ # Run ruff linter
4
+ lint:
5
+ uv run ruff check forestui/
6
+
7
+ # Run mypy type checker
8
+ typecheck:
9
+ uv run mypy forestui/
10
+
11
+ # Run all checks (lint + typecheck)
12
+ check: lint typecheck
13
+
14
+ # Format code with ruff
15
+ format:
16
+ uv run ruff format forestui/
17
+ uv run ruff check --fix forestui/
18
+
19
+ # Install the package locally
20
+ install:
21
+ uv pip install -e .
22
+
23
+ # Install with dev dependencies
24
+ dev:
25
+ uv sync --group dev
26
+
27
+ # Clean build artifacts
28
+ clean:
29
+ rm -rf build/ dist/ *.egg-info/ .mypy_cache/ .ruff_cache/
30
+ find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
31
+
32
+ # Run the app
33
+ run:
34
+ uv run forestui
35
+
36
+ # Show help
37
+ help:
38
+ @echo "Available targets:"
39
+ @echo " make lint - Run ruff linter"
40
+ @echo " make typecheck - Run mypy type checker"
41
+ @echo " make check - Run all checks (lint + typecheck)"
42
+ @echo " make format - Format code with ruff"
43
+ @echo " make install - Install package locally"
44
+ @echo " make dev - Install with dev dependencies"
45
+ @echo " make clean - Clean build artifacts"
46
+ @echo " make run - Run the app"
@@ -0,0 +1,152 @@
1
+ Metadata-Version: 2.4
2
+ Name: forestui
3
+ Version: 0.9.0
4
+ Summary: A Terminal UI for managing Git worktrees
5
+ Author: cadu
6
+ Keywords: git,terminal,textual,tui,worktree
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Environment :: Console
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Classifier: Topic :: Software Development :: Version Control :: Git
14
+ Requires-Python: >=3.14
15
+ Requires-Dist: click>=8.1.0
16
+ Requires-Dist: humanize>=4.9.0
17
+ Requires-Dist: libtmux>=0.37.0
18
+ Requires-Dist: pydantic>=2.12.5
19
+ Requires-Dist: textual>=7.2.0
20
+ Description-Content-Type: text/markdown
21
+
22
+ # forestui
23
+
24
+ > A terminal UI for managing Git worktrees, inspired by [forest](https://github.com/ricwo/forest) for macOS by [@ricwo](https://github.com/ricwo).
25
+
26
+ forestui brings the power of Git worktree management to the terminal with a beautiful TUI interface built on [Textual](https://textual.textualize.io/), featuring deep integration with [Claude Code](https://claude.ai/code).
27
+
28
+ ![forestui screenshot](doc/screenshot_small.png)
29
+
30
+ ## Features
31
+
32
+ - **Repository Management**: Add and track multiple Git repositories
33
+ - **Worktree Operations**: Create, rename, archive, and delete worktrees
34
+ - **TUI Editor Integration**: Opens TUI editors (vim, nvim, helix, etc.) in tmux windows
35
+ - **Claude Code Integration**: Track and resume Claude Code sessions per worktree
36
+ - **Multi-Forest Support**: Manage multiple forest directories via CLI argument
37
+ - **tmux Native**: Runs inside tmux for a cohesive terminal experience
38
+
39
+ ## Requirements
40
+
41
+ - Python 3.14+
42
+ - tmux
43
+ - uv (for installation)
44
+
45
+ ## Installing
46
+
47
+ ```bash
48
+ curl -fsSL https://raw.githubusercontent.com/flipbit03/forestui/main/install.sh | bash
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ ```bash
54
+ # Start with default forest directory (~/forest)
55
+ forestui
56
+
57
+ # Start with a custom forest directory
58
+ forestui ~/my-projects
59
+
60
+ # Update to latest version
61
+ forestui --self-update
62
+
63
+ # Show help
64
+ forestui --help
65
+ ```
66
+
67
+ ### Keyboard Shortcuts
68
+
69
+ | Key | Action |
70
+ |-----|--------|
71
+ | `a` | Add repository |
72
+ | `w` | Add worktree |
73
+ | `e` | Open in editor |
74
+ | `t` | Open in terminal |
75
+ | `o` | Open in file manager |
76
+ | `n` | Start Claude session |
77
+ | `y` | Start Claude session (YOLO mode) |
78
+ | `h` | Toggle archive |
79
+ | `d` | Delete |
80
+ | `s` | Settings |
81
+ | `r` | Refresh |
82
+ | `?` | Show help |
83
+ | `q` | Quit |
84
+
85
+ ### TUI Editor Integration
86
+
87
+ When your default editor is a TUI editor (vim, nvim, helix, nano, etc.), forestui opens it in a new tmux window named `edit:<worktree>`. This keeps your editing session organized alongside forestui and any Claude sessions.
88
+
89
+ Supported TUI editors: `vim`, `nvim`, `vi`, `emacs`, `nano`, `helix`, `hx`, `micro`, `kakoune`, `kak`
90
+
91
+ ### Multi-Forest Support
92
+
93
+ forestui stores its state (`.forestui-config.json`) in the forest directory itself, allowing you to manage multiple independent forests:
94
+
95
+ ```bash
96
+ forestui ~/work # Uses ~/work/.forestui-config.json
97
+ forestui ~/personal # Uses ~/personal/.forestui-config.json
98
+ ```
99
+
100
+ User preferences (editor, theme, branch prefix) are stored globally in `~/.config/forestui/settings.json`.
101
+
102
+ ## Configuration
103
+
104
+ Settings are stored in `~/.config/forestui/settings.json`:
105
+
106
+ ```json
107
+ {
108
+ "default_editor": "nvim",
109
+ "branch_prefix": "feat/",
110
+ "theme": "system"
111
+ }
112
+ ```
113
+
114
+ Press `s` in the app to open the settings modal.
115
+
116
+ ## Development
117
+
118
+ ```bash
119
+ # Clone and enter the repo
120
+ git clone https://github.com/flipbit03/forestui.git
121
+ cd forestui
122
+
123
+ # Install dev dependencies
124
+ make dev
125
+
126
+ # Run checks
127
+ make check
128
+
129
+ # Format code
130
+ make format
131
+
132
+ # Run the app
133
+ make run
134
+ ```
135
+
136
+ See [CLAUDE.md](CLAUDE.md) for AI-assisted development guidelines.
137
+
138
+ ## Compatibility with forest (macOS)
139
+
140
+ forestui is designed to coexist with [forest](https://github.com/ricwo/forest) for macOS:
141
+
142
+ - Both apps can share the same `~/forest` directory for worktrees
143
+ - Each app maintains its own state file:
144
+ - forest: `.forest-config.json` (stored in `~/.config/forest/`)
145
+ - forestui: `.forestui-config.json` (stored in the forest folder itself)
146
+ - Worktrees created by either app work seamlessly with both
147
+
148
+ **Key difference:** forestui stores its state inside the forest folder (`~/forest/.forestui-config.json`) rather than in a global config directory. This design enables multi-forest support - you can run `forestui ~/work` and `forestui ~/personal` with completely independent state for each.
149
+
150
+ ## License
151
+
152
+ MIT
@@ -0,0 +1,131 @@
1
+ # forestui
2
+
3
+ > A terminal UI for managing Git worktrees, inspired by [forest](https://github.com/ricwo/forest) for macOS by [@ricwo](https://github.com/ricwo).
4
+
5
+ forestui brings the power of Git worktree management to the terminal with a beautiful TUI interface built on [Textual](https://textual.textualize.io/), featuring deep integration with [Claude Code](https://claude.ai/code).
6
+
7
+ ![forestui screenshot](doc/screenshot_small.png)
8
+
9
+ ## Features
10
+
11
+ - **Repository Management**: Add and track multiple Git repositories
12
+ - **Worktree Operations**: Create, rename, archive, and delete worktrees
13
+ - **TUI Editor Integration**: Opens TUI editors (vim, nvim, helix, etc.) in tmux windows
14
+ - **Claude Code Integration**: Track and resume Claude Code sessions per worktree
15
+ - **Multi-Forest Support**: Manage multiple forest directories via CLI argument
16
+ - **tmux Native**: Runs inside tmux for a cohesive terminal experience
17
+
18
+ ## Requirements
19
+
20
+ - Python 3.14+
21
+ - tmux
22
+ - uv (for installation)
23
+
24
+ ## Installing
25
+
26
+ ```bash
27
+ curl -fsSL https://raw.githubusercontent.com/flipbit03/forestui/main/install.sh | bash
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```bash
33
+ # Start with default forest directory (~/forest)
34
+ forestui
35
+
36
+ # Start with a custom forest directory
37
+ forestui ~/my-projects
38
+
39
+ # Update to latest version
40
+ forestui --self-update
41
+
42
+ # Show help
43
+ forestui --help
44
+ ```
45
+
46
+ ### Keyboard Shortcuts
47
+
48
+ | Key | Action |
49
+ |-----|--------|
50
+ | `a` | Add repository |
51
+ | `w` | Add worktree |
52
+ | `e` | Open in editor |
53
+ | `t` | Open in terminal |
54
+ | `o` | Open in file manager |
55
+ | `n` | Start Claude session |
56
+ | `y` | Start Claude session (YOLO mode) |
57
+ | `h` | Toggle archive |
58
+ | `d` | Delete |
59
+ | `s` | Settings |
60
+ | `r` | Refresh |
61
+ | `?` | Show help |
62
+ | `q` | Quit |
63
+
64
+ ### TUI Editor Integration
65
+
66
+ When your default editor is a TUI editor (vim, nvim, helix, nano, etc.), forestui opens it in a new tmux window named `edit:<worktree>`. This keeps your editing session organized alongside forestui and any Claude sessions.
67
+
68
+ Supported TUI editors: `vim`, `nvim`, `vi`, `emacs`, `nano`, `helix`, `hx`, `micro`, `kakoune`, `kak`
69
+
70
+ ### Multi-Forest Support
71
+
72
+ forestui stores its state (`.forestui-config.json`) in the forest directory itself, allowing you to manage multiple independent forests:
73
+
74
+ ```bash
75
+ forestui ~/work # Uses ~/work/.forestui-config.json
76
+ forestui ~/personal # Uses ~/personal/.forestui-config.json
77
+ ```
78
+
79
+ User preferences (editor, theme, branch prefix) are stored globally in `~/.config/forestui/settings.json`.
80
+
81
+ ## Configuration
82
+
83
+ Settings are stored in `~/.config/forestui/settings.json`:
84
+
85
+ ```json
86
+ {
87
+ "default_editor": "nvim",
88
+ "branch_prefix": "feat/",
89
+ "theme": "system"
90
+ }
91
+ ```
92
+
93
+ Press `s` in the app to open the settings modal.
94
+
95
+ ## Development
96
+
97
+ ```bash
98
+ # Clone and enter the repo
99
+ git clone https://github.com/flipbit03/forestui.git
100
+ cd forestui
101
+
102
+ # Install dev dependencies
103
+ make dev
104
+
105
+ # Run checks
106
+ make check
107
+
108
+ # Format code
109
+ make format
110
+
111
+ # Run the app
112
+ make run
113
+ ```
114
+
115
+ See [CLAUDE.md](CLAUDE.md) for AI-assisted development guidelines.
116
+
117
+ ## Compatibility with forest (macOS)
118
+
119
+ forestui is designed to coexist with [forest](https://github.com/ricwo/forest) for macOS:
120
+
121
+ - Both apps can share the same `~/forest` directory for worktrees
122
+ - Each app maintains its own state file:
123
+ - forest: `.forest-config.json` (stored in `~/.config/forest/`)
124
+ - forestui: `.forestui-config.json` (stored in the forest folder itself)
125
+ - Worktrees created by either app work seamlessly with both
126
+
127
+ **Key difference:** forestui stores its state inside the forest folder (`~/forest/.forestui-config.json`) rather than in a global config directory. This design enables multi-forest support - you can run `forestui ~/work` and `forestui ~/personal` with completely independent state for each.
128
+
129
+ ## License
130
+
131
+ MIT
Binary file
@@ -0,0 +1,3 @@
1
+ """forestui - A Terminal UI for managing Git worktrees."""
2
+
3
+ __version__ = "0.9.0"
@@ -0,0 +1,6 @@
1
+ """Entry point for forestui."""
2
+
3
+ from forestui.app import main
4
+
5
+ if __name__ == "__main__":
6
+ main()