gitstow 0.1.0__tar.gz → 0.2.6__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.
Files changed (96) hide show
  1. gitstow-0.2.6/.claude/settings.json +19 -0
  2. gitstow-0.2.6/.github/workflows/publish.yml +65 -0
  3. {gitstow-0.1.0 → gitstow-0.2.6}/BACKLOG.md +3 -1
  4. gitstow-0.2.6/CHANGELOG.md +112 -0
  5. {gitstow-0.1.0 → gitstow-0.2.6}/CLAUDE.md +10 -4
  6. {gitstow-0.1.0 → gitstow-0.2.6}/CONTRIBUTING.md +12 -0
  7. {gitstow-0.1.0 → gitstow-0.2.6}/PKG-INFO +36 -6
  8. {gitstow-0.1.0 → gitstow-0.2.6}/README.md +30 -5
  9. gitstow-0.2.6/demo.gif +0 -0
  10. {gitstow-0.1.0 → gitstow-0.2.6}/demo.tape +15 -6
  11. {gitstow-0.1.0 → gitstow-0.2.6}/docs/building/implementation-plan.md +14 -2
  12. {gitstow-0.1.0 → gitstow-0.2.6}/docs/user/commands.md +131 -0
  13. {gitstow-0.1.0 → gitstow-0.2.6}/docs/user/concepts.md +1 -0
  14. {gitstow-0.1.0 → gitstow-0.2.6}/docs/user/getting-started.md +16 -1
  15. {gitstow-0.1.0 → gitstow-0.2.6}/pyproject.toml +6 -1
  16. gitstow-0.2.6/scripts/release.sh +137 -0
  17. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/__init__.py +1 -1
  18. gitstow-0.2.6/src/gitstow/cli/fetch.py +225 -0
  19. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/main.py +7 -0
  20. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/onboard.py +1 -1
  21. gitstow-0.2.6/src/gitstow/cli/serve.py +49 -0
  22. gitstow-0.2.6/src/gitstow/cli/update.py +146 -0
  23. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/git.py +31 -0
  24. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/repo.py +3 -0
  25. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/skill/SKILL.md +13 -0
  26. gitstow-0.2.6/src/gitstow/web/__init__.py +4 -0
  27. gitstow-0.2.6/src/gitstow/web/routes/__init__.py +1 -0
  28. gitstow-0.2.6/src/gitstow/web/routes/collection.py +245 -0
  29. gitstow-0.2.6/src/gitstow/web/routes/dashboard.py +246 -0
  30. gitstow-0.2.6/src/gitstow/web/routes/pages.py +91 -0
  31. gitstow-0.2.6/src/gitstow/web/routes/repos.py +489 -0
  32. gitstow-0.2.6/src/gitstow/web/routes/system.py +23 -0
  33. gitstow-0.2.6/src/gitstow/web/routes/workspaces.py +121 -0
  34. gitstow-0.2.6/src/gitstow/web/server.py +100 -0
  35. gitstow-0.2.6/src/gitstow/web/static/app.css +922 -0
  36. gitstow-0.2.6/src/gitstow/web/templates/_repo_drawer.html +111 -0
  37. gitstow-0.2.6/src/gitstow/web/templates/add_repo.html +52 -0
  38. gitstow-0.2.6/src/gitstow/web/templates/base.html +132 -0
  39. gitstow-0.2.6/src/gitstow/web/templates/dashboard.html +196 -0
  40. gitstow-0.2.6/src/gitstow/web/templates/partials/dashboard_rows.html +1 -0
  41. gitstow-0.2.6/src/gitstow/web/templates/partials/fetch_summary.html +39 -0
  42. gitstow-0.2.6/src/gitstow/web/templates/partials/pull_summary.html +39 -0
  43. gitstow-0.2.6/src/gitstow/web/templates/partials/repo_row.html +76 -0
  44. gitstow-0.2.6/src/gitstow/web/templates/settings.html +103 -0
  45. gitstow-0.2.6/src/gitstow/web/templates/workspaces.html +97 -0
  46. {gitstow-0.1.0 → gitstow-0.2.6}/tests/test_cli.py +18 -0
  47. {gitstow-0.1.0 → gitstow-0.2.6}/tests/test_git.py +40 -0
  48. gitstow-0.2.6/tests/test_serve.py +409 -0
  49. gitstow-0.1.0/.github/workflows/release.yml +0 -45
  50. gitstow-0.1.0/CHANGELOG.md +0 -27
  51. {gitstow-0.1.0 → gitstow-0.2.6}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  52. {gitstow-0.1.0 → gitstow-0.2.6}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  53. {gitstow-0.1.0 → gitstow-0.2.6}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  54. {gitstow-0.1.0 → gitstow-0.2.6}/.github/workflows/ci.yml +0 -0
  55. {gitstow-0.1.0 → gitstow-0.2.6}/.gitignore +0 -0
  56. {gitstow-0.1.0 → gitstow-0.2.6}/CODE_OF_CONDUCT.md +0 -0
  57. {gitstow-0.1.0 → gitstow-0.2.6}/LICENSE +0 -0
  58. {gitstow-0.1.0 → gitstow-0.2.6}/SECURITY.md +0 -0
  59. {gitstow-0.1.0 → gitstow-0.2.6}/docs/user/configuration.md +0 -0
  60. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/__main__.py +0 -0
  61. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/__init__.py +0 -0
  62. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/add.py +0 -0
  63. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/config_cmd.py +0 -0
  64. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/doctor.py +0 -0
  65. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/exec_cmd.py +0 -0
  66. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/export_cmd.py +0 -0
  67. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/helpers.py +0 -0
  68. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/list_cmd.py +0 -0
  69. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/manage.py +0 -0
  70. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/migrate.py +0 -0
  71. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/open_cmd.py +0 -0
  72. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/pull.py +0 -0
  73. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/remove.py +0 -0
  74. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/search.py +0 -0
  75. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/setup_ai.py +0 -0
  76. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/shell.py +0 -0
  77. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/skill_cmd.py +0 -0
  78. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/stats.py +0 -0
  79. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/status.py +0 -0
  80. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/tui.py +0 -0
  81. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/workspace_cmd.py +0 -0
  82. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/__init__.py +0 -0
  83. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/config.py +0 -0
  84. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/discovery.py +0 -0
  85. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/parallel.py +0 -0
  86. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/paths.py +0 -0
  87. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/url_parser.py +0 -0
  88. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/mcp/__init__.py +0 -0
  89. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/mcp/server.py +0 -0
  90. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/tui/__init__.py +0 -0
  91. {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/tui/app.py +0 -0
  92. {gitstow-0.1.0 → gitstow-0.2.6}/tests/__init__.py +0 -0
  93. {gitstow-0.1.0 → gitstow-0.2.6}/tests/conftest.py +0 -0
  94. {gitstow-0.1.0 → gitstow-0.2.6}/tests/test_config.py +0 -0
  95. {gitstow-0.1.0 → gitstow-0.2.6}/tests/test_repo.py +0 -0
  96. {gitstow-0.1.0 → gitstow-0.2.6}/tests/test_url_parser.py +0 -0
@@ -0,0 +1,19 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(python -m pytest tests/test_serve.py -v)",
5
+ "Bash(python -c \"from gitstow.cli.main import app; from typer.testing import CliRunner; r = CliRunner\\(\\); print\\(r.invoke\\(app, ['ui', '--help']\\).output\\)\")",
6
+ "Bash(python3 -m pytest tests/test_serve.py -v)",
7
+ "Bash(python3 -c \"from gitstow.cli.main import app; from typer.testing import CliRunner; r = CliRunner\\(\\); print\\(r.invoke\\(app, ['ui', '--help']\\).output\\)\")",
8
+ "Bash(python3 -c \"from gitstow.cli.main import app; from typer.testing import CliRunner; r = CliRunner\\(\\); print\\(r.invoke\\(app, ['serve', '--help']\\).output\\)\")",
9
+ "Bash(python3 -m pytest -v)",
10
+ "Bash(git commit -m ':*)",
11
+ "Bash(python3 -m pytest tests/test_git.py tests/test_serve.py -v)",
12
+ "Bash(python3 -c \"from gitstow.cli.main import app; from typer.testing import CliRunner; r = CliRunner\\(\\); print\\(r.invoke\\(app, ['fetch', '--help']\\).output\\)\")",
13
+ "Bash(git tag:*)",
14
+ "Bash(python3 -c \"import gitstow; print\\(gitstow.__version__\\)\")",
15
+ "Bash(pip3 show:*)",
16
+ "Bash(python3 -m pytest tests/test_serve.py::TestFetch -v)"
17
+ ]
18
+ }
19
+ }
@@ -0,0 +1,65 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ environment: pypi
11
+ permissions:
12
+ contents: read
13
+ id-token: write
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.12"
20
+
21
+ - name: Install build tools
22
+ run: pip install build
23
+
24
+ - name: Build package
25
+ run: python -m build
26
+
27
+ - name: Verify version matches tag
28
+ run: |
29
+ python - <<'PY'
30
+ import os
31
+ import pathlib
32
+ import re
33
+ import sys
34
+ import tomllib
35
+
36
+ tag_version = os.environ["GITHUB_REF"].removeprefix("refs/tags/v")
37
+
38
+ with open("pyproject.toml", "rb") as f:
39
+ package_version = tomllib.load(f)["project"]["version"]
40
+
41
+ init_text = pathlib.Path("src/gitstow/__init__.py").read_text()
42
+ match = re.search(r'__version__ = "([^"]+)"', init_text)
43
+ init_version = match.group(1) if match else None
44
+
45
+ errors = []
46
+ if tag_version != package_version:
47
+ errors.append(
48
+ f"Tag v{tag_version} does not match package version {package_version}"
49
+ )
50
+ if init_version != package_version:
51
+ errors.append(
52
+ f"src/gitstow/__init__.py version {init_version} "
53
+ f"does not match package version {package_version}"
54
+ )
55
+
56
+ if errors:
57
+ for error in errors:
58
+ print(f"::error::{error}")
59
+ sys.exit(1)
60
+
61
+ print(f"Publishing gitstow v{package_version}")
62
+ PY
63
+
64
+ - name: Publish to PyPI
65
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -10,7 +10,9 @@ Post-v0.1.0 improvements tracked here. See [GitHub Issues](https://github.com/ri
10
10
  - [x] **Export format versioning and checksums** (#4) — Added `version: 1` to YAML/JSON exports; validates on import; backward-compatible with unversioned files
11
11
  - [x] **Progress indication during long clones** (#5) — `git clone --progress`; pull shows live counter `[5/47]`
12
12
  - [x] **Publish to PyPI** (#6) — Release workflow created (`.github/workflows/release.yml`); publish on GitHub release
13
+ - [x] **Web dashboard (`gitstow ui`)** — Dark local browser UI wrapping core/ for daily repo management. FastAPI + Jinja2 + HTMX, dark + ember accent aesthetic. See [CHANGELOG.md](CHANGELOG.md) v0.2.0.
14
+ - [ ] **Fix TUI breakage** — Multiple issues across the Textual TUI; currently unusable in daily flow. Keep around for SSH/remote use case but triage and repair when time allows.
13
15
 
14
16
  ## Documentation
15
17
 
16
- - [ ] **Record demo GIF for README** (#7) — VHS tape script created (`demo.tape`); run `vhs demo.tape` to record
18
+ - [x] **Record demo GIF for README** (#7) — Recorded with VHS, embedded in README
@@ -0,0 +1,112 @@
1
+ # Changelog
2
+
3
+ All notable changes to gitstow will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [0.2.5] - 2026-04-19
8
+
9
+ ### Added
10
+
11
+ - **`gitstow fetch`** — new CLI command to fetch all remotes without merging. Updates ahead/behind counts. Includes frozen repos (fetch is non-destructive). Supports `--tag`, `--exclude-tag`, `--owner`, `--retry`, `--json`, `--quiet` flags.
12
+ - **Web dashboard — Fetch all button.** New `btn-outline` button in the action bar between Refresh and Add repo. Fetches all remotes in parallel (including frozen repos), then shows a summary panel. No confirmation needed — fetch is non-destructive.
13
+ - **Web dashboard — single-repo Fetch.** New "Fetch" action in each row's three-dot menu. Updates that row's ahead/behind counts in place via HTMX.
14
+ - **`last_fetched` timestamp** tracked per repo in `repos.yaml`. Stamped on successful fetch operations. Backward-compatible — existing repos default to empty.
15
+ - Updated help dialog and tooltips to reference Fetch all instead of "fetch manually."
16
+
17
+ ## [0.2.4] - 2026-04-19
18
+
19
+ ### Changed
20
+
21
+ - **Renamed `gitstow serve` → `gitstow ui`** — more intuitive command name for the browser dashboard. `gitstow serve` remains as a hidden alias for backwards compatibility.
22
+ - **Removed `WEB_GUI_PLAN.md`** — shipped planning artifact retired; git history preserves it.
23
+
24
+ ## [0.2.3] - 2026-04-18
25
+
26
+ ### Fixed
27
+
28
+ - **Web dashboard — "Open folder" now actually opens the folder.** The row-menu and drawer buttons were previously no-ops; they now POST to a new `/repos/{ws}/{key}/open-folder` route which shells out to the platform opener (`open` on macOS, `xdg-open` on Linux, `explorer` on Windows). The server binds to `127.0.0.1` only, so no exposure beyond localhost.
29
+
30
+ ### Added
31
+
32
+ - **Web dashboard — Copy URL / Copy path / Copy local path actions.** The `⋯` row menu and the repo drawer each expose three clipboard actions: Copy URL (remote clone URL), Copy path (repo key like `owner/repo`), Copy local path (absolute filesystem path). Implemented client-side with `navigator.clipboard` and a textarea fallback for non-secure contexts.
33
+ - **Toast notifications.** A new bottom-center toast surfaces success/failure for Open folder and the copy actions (reads an optional `data-toast` attr on any `hx-post` button and an error message from the JSON response body on failure).
34
+
35
+ ## [0.2.2] - 2026-04-18
36
+
37
+ ### Added
38
+
39
+ - **Dashboard tooltips everywhere.** Every interactive element now has a `title=` explaining what it does or what its state means — status pills (with the recommended next step), delta badges, workspace chips, tags, last-pull, Pull button (text varies by repo state), the `⋯` menu and each of its items, action-bar buttons, column headers, the nav links, the live dot, the Shutdown button, the lock icon. Hover over anything.
40
+ - **Pull button now shows the commit count when behind.** `↓ Pull 5` instead of just `Pull` — the action's payload is visible at a glance without hover.
41
+ - **"Reading the dashboard" help dialog.** New `?` button in the hero opens a native `<dialog>` modal with: statuses + what each means + what to do, the Pull button color convention, what Remote Δ reflects (last fetch, not live remote), what auto-refresh actually does (local state only; does NOT run `git fetch`), and a reference for every action. Click the backdrop or press Esc to close.
42
+ - Matching `docs/user/commands.md` "Reading the dashboard" subsection under `gitstow ui` so the legend exists in prose too, not only in the UI.
43
+
44
+ ### Changed
45
+
46
+ - `_classify` and `_delta` helpers in `web/routes/dashboard.py` now also return tooltip strings; `_pull_tooltip` maps (variant × status) to the exact explanation shown on each Pull button. Partial template `partials/repo_row.html` threads these through consistently so HTMX row swaps after pull keep the tooltips accurate.
47
+
48
+ ## [0.2.1] - 2026-04-17
49
+
50
+ ### Added
51
+
52
+ - **`gitstow update`** — self-upgrade from PyPI. Detects the install method (pipx, pip, or editable) and runs the matching upgrade command. Use `--check` / `-c` to query PyPI without installing — shows newer-version-available or up-to-date. Editable installs get a friendly note pointing at `git pull` instead of trying to pip-upgrade.
53
+ - Smoke tests for `serve` and `update` command help.
54
+
55
+ ### Fixed
56
+
57
+ - **CI**: added `httpx` to `[dev]` extras. `fastapi.testclient.TestClient` re-exports Starlette's version, which imports `httpx` at module load. Fresh CI installs were failing at test collection; local envs passed because `httpx` was already present from other packages.
58
+
59
+ ## [0.2.0] - 2026-04-17
60
+
61
+ ### Added
62
+
63
+ - **`gitstow ui`** — a persistent local browser dashboard for daily repo management. Launches a FastAPI + Jinja2 + HTMX server at `http://127.0.0.1:7853` and auto-opens your default browser. Dark theme (Bricolage Grotesque display, JetBrains Mono data) with ember-orange primary accent and signal-blue secondary.
64
+ - **Dashboard** — ledger view of every tracked repo: colored-dot status (clean / dirty / conflict / behind / ahead / frozen), workspace chip, branch, remote delta, tags, last-pull time. Hero metrics strip summarizes counts. Hover reveals an accent indicator line on the row's left edge.
65
+ - **Pull** — single-repo pull with HTMX row swap in place; **Pull all** runs every non-frozen repo in parallel via the existing `core.parallel` semaphore and renders a summary panel (`N ok · N failed · N skipped`) with per-repo failure details.
66
+ - **Add repo** — form with URL parser, workspace selector, and optional tags; merges workspace auto-tags on clone.
67
+ - **Remove** — registry-only from the row's ⋯ menu (HTMX row-delete); registry + disk from the repo drawer (defensive path check; refuses to rmtree outside the workspace root).
68
+ - **Freeze / tag toggles** — row-menu freeze with HTMX label flip; drawer freeze checkbox posts on change; drawer tag editor replaces the list from a comma-separated input.
69
+ - **Workspaces** — list, add (label + path + layout + auto-tags), remove (files untouched), **Scan** (discovers untracked repos on disk and catalogs them with auto-tags merged).
70
+ - **Collection export / import** — under Settings; downloads YAML (canonical round-trip), JSON, or plain URL list; upload accepts any of the three.
71
+ - **Auto-refresh** — dashboard tbody reloads every 30s via HTMX `hx-trigger="every 30s"` without touching hero, metrics, or action bar.
72
+ - **Shutdown** — footer button POSTs `/shutdown`, which flips `uvicorn.Server.should_exit` (Ctrl+C also works).
73
+ - **New core dependencies** (shipped, not behind an extra): `fastapi>=0.110`, `uvicorn>=0.27`, `jinja2>=3.1`, `python-multipart>=0.0.9`.
74
+ - **30 FastAPI TestClient smoke tests** covering every route + mutation path. Monkeypatches isolate config/repo files to tmp; git calls are mocked (never shells out).
75
+
76
+ ### Changed
77
+
78
+ - Command count 29 → 30 (`serve` added).
79
+ - `CLAUDE.md` architecture tree expanded to document the new `web/` module.
80
+
81
+ ### Security
82
+
83
+ - `gitstow ui` binds `127.0.0.1` only. There is no `--host` flag — arbitrary git execution must not be LAN-reachable.
84
+ - All mutations are POST; `/shutdown` is POST so stray links can't terminate the server.
85
+ - Registry + disk delete resolves the repo path and verifies it lives under the workspace root before `rmtree`.
86
+
87
+ ### Deferred
88
+
89
+ - The Textual TUI has multiple breakages and is parked in [BACKLOG.md](BACKLOG.md); `gitstow ui` is the primary visual dashboard now. TUI remains for the eventual SSH / remote use case.
90
+ - Web GUI is intentionally single-user + localhost-only. Auth, multi-user, HTTPS, remote access, and daemonization are explicitly out of scope for v0.2.
91
+
92
+ ## [0.1.0] - 2026-04-10
93
+
94
+ Initial release.
95
+
96
+ ### Added
97
+
98
+ - **Core commands:** `add`, `pull`, `list`, `status`, `remove`, `migrate`
99
+ - **Workspace system:** Multiple workspaces with structured (`owner/repo`) and flat (`repo`) layouts
100
+ - **Workspace commands:** `workspace list`, `workspace add`, `workspace remove`, `workspace scan`
101
+ - **Repo management:** `repo freeze`, `repo unfreeze`, `repo tag`, `repo untag`, `repo tags`, `repo info`
102
+ - **Bulk operations:** Parallel pull/status with configurable concurrency (default 6)
103
+ - **Power commands:** `exec` (run commands across repos), `search` (grep across repos via ripgrep), `open` (editor/browser/finder), `stats`
104
+ - **Collection sharing:** `collection export` (YAML/JSON/URLs) and `collection import`
105
+ - **Shell integration:** `shell pick` (fzf picker), `shell init` (aliases), `shell setup`
106
+ - **Interactive TUI:** `tui` command with Textual-based dashboard (filter, pull, freeze toggle)
107
+ - **URL parsing:** GitHub, GitLab, Bitbucket, Codeberg, Azure DevOps, custom hosts; HTTPS, SSH, and shorthand formats
108
+ - **AI integration:** Claude Code skill (auto-installed via `onboard` or `install-skill`) and optional MCP server
109
+ - **Setup:** `onboard` wizard, `doctor` health check, `config show/set`
110
+ - **Output modes:** `--json` and `--quiet` flags on all main commands
111
+ - **Global workspace filter:** `-w/--workspace` flag on all commands
112
+ - **Error isolation:** One failing repo never blocks operations on others
@@ -26,6 +26,7 @@ src/gitstow/
26
26
  │ ├── export_cmd.py # export/import collection
27
27
  │ ├── shell.py # Shell integration (fzf, aliases)
28
28
  │ ├── tui.py # TUI launcher
29
+ │ ├── serve.py # Web dashboard launcher
29
30
  │ ├── migrate.py, config_cmd.py, onboard.py, doctor.py, skill_cmd.py
30
31
  │ └── __init__.py
31
32
  ├── core/ # Business logic (git ops, URL parsing, state)
@@ -40,6 +41,11 @@ src/gitstow/
40
41
  ├── tui/ # Textual interactive dashboard
41
42
  │ ├── app.py # Main TUI application
42
43
  │ └── __init__.py
44
+ ├── web/ # FastAPI browser dashboard (gitstow ui)
45
+ │ ├── server.py # FastAPI app, uvicorn runner, app.state.server stash
46
+ │ ├── static/app.css # Dark theme, Bricolage Grotesque + JetBrains Mono
47
+ │ ├── templates/ # Jinja2 — base.html + page templates + partials/
48
+ │ └── routes/ # dashboard.py, repos.py, workspaces.py, collection.py, pages.py, system.py
43
49
  └── skill/ # Claude Code skill (SKILL.md)
44
50
  └── SKILL.md
45
51
  ```
@@ -80,15 +86,15 @@ active:
80
86
  tags: [active]
81
87
  ```
82
88
 
83
- ## All Commands (26)
89
+ ## All Commands (32)
84
90
 
85
- **Core:** `add`, `pull`, `list`, `status`, `remove`, `migrate`
91
+ **Core:** `add`, `pull`, `fetch`, `list`, `status`, `remove`, `migrate`
86
92
  **Workspace:** `workspace list`, `workspace add`, `workspace remove`, `workspace scan`
87
93
  **Repo management:** `repo freeze`, `repo unfreeze`, `repo tag`, `repo untag`, `repo tags`, `repo info`
88
94
  **Power:** `exec`, `search`, `open`, `stats`
89
95
  **Sharing:** `collection export`, `collection import`
90
- **Shell:** `shell pick`, `shell init`, `shell setup`, `tui`
91
- **Setup:** `onboard`, `config show/set/path/migrate-root`, `doctor`, `install-skill`
96
+ **Shell:** `shell pick`, `shell init`, `shell completions`, `shell setup`, `tui`, `ui`
97
+ **Setup:** `onboard`, `config show/set/path/migrate-root`, `doctor`, `install-skill`, `setup-ai`, `update`
92
98
 
93
99
  ## Development
94
100
 
@@ -40,6 +40,7 @@ The codebase has a strict layered architecture:
40
40
  cli/ → Thin command layer (Typer). Delegates to core/.
41
41
  core/ → Business logic. Git ops, config, repo store, URL parsing.
42
42
  tui/ → Textual interactive dashboard.
43
+ web/ → FastAPI + Jinja2 + HTMX browser dashboard (`gitstow ui`).
43
44
  skill/ → Claude Code skill (SKILL.md).
44
45
  mcp/ → MCP server for non-Claude-Code AI tools.
45
46
  ```
@@ -67,6 +68,17 @@ See `CLAUDE.md` for a detailed architecture guide.
67
68
  - The Claude Code skill auto-updates when the version changes (checked on every CLI invocation)
68
69
  - Follow [Semantic Versioning](https://semver.org/): breaking.feature.fix
69
70
 
71
+ Release from a `main` branch with no tracked changes:
72
+
73
+ ```bash
74
+ bash scripts/release.sh 0.2.6 "short release note"
75
+ ```
76
+
77
+ The release script updates both version files, commits the bump, creates `vX.Y.Z`,
78
+ and pushes the commit plus tag. The `Publish to PyPI` workflow runs on pushed `v*`
79
+ tags and verifies the tag, `pyproject.toml`, and `src/gitstow/__init__.py` versions
80
+ match before publishing.
81
+
70
82
  ## What to Work On
71
83
 
72
84
  - Check [open issues](https://github.com/rishmadaan/gitstow/issues) for things to pick up
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitstow
3
- Version: 0.1.0
3
+ Version: 0.2.6
4
4
  Summary: A git repository library manager — clone, organize, and maintain collections of repos you learn from
5
5
  Project-URL: Homepage, https://github.com/rishmadaan/gitstow
6
6
  Project-URL: Repository, https://github.com/rishmadaan/gitstow
@@ -26,10 +26,15 @@ Classifier: Programming Language :: Python :: 3.13
26
26
  Classifier: Topic :: Software Development :: Version Control :: Git
27
27
  Requires-Python: >=3.10
28
28
  Requires-Dist: beaupy>=3.0
29
+ Requires-Dist: fastapi>=0.110
30
+ Requires-Dist: jinja2>=3.1
31
+ Requires-Dist: python-multipart>=0.0.9
29
32
  Requires-Dist: pyyaml>=6.0
30
33
  Requires-Dist: rich>=13.0
31
34
  Requires-Dist: typer[all]>=0.9
35
+ Requires-Dist: uvicorn>=0.27
32
36
  Provides-Extra: dev
37
+ Requires-Dist: httpx>=0.27; extra == 'dev'
33
38
  Requires-Dist: pytest>=8.0; extra == 'dev'
34
39
  Requires-Dist: ruff>=0.4; extra == 'dev'
35
40
  Provides-Extra: mcp
@@ -42,6 +47,8 @@ Description-Content-Type: text/markdown
42
47
 
43
48
  A git repository library manager — clone, organize, and maintain collections of repos you learn from.
44
49
 
50
+ ![gitstow demo](demo.gif)
51
+
45
52
  ## Why?
46
53
 
47
54
  AI-assisted development has created a new relationship with open source. Developers increasingly maintain local clones of repositories they study and reference, not just repos they contribute to. `gitstow` manages this collection as a first-class concern.
@@ -70,11 +77,10 @@ gitstow pull
70
77
 
71
78
  # See your collection
72
79
  gitstow list
73
-
74
- # Check git status across all repos
75
- gitstow status
76
80
  ```
77
81
 
82
+ Prefer a GUI? Run `gitstow ui` — a local dark-themed browser dashboard opens automatically. Dirty state, branch deltas, Pull / Pull-all, add / remove / freeze / tag, workspace CRUD, collection export/import — all in one tab you leave open. See [Browser Dashboard](#browser-dashboard).
83
+
78
84
  ## Features
79
85
 
80
86
  ### Workspaces
@@ -174,9 +180,17 @@ gse # Open repo in editor (fzf picker)
174
180
  gsp # gitstow pull shorthand
175
181
  ```
176
182
 
177
- ### Interactive Dashboard
183
+ ### Browser Dashboard
184
+ ```bash
185
+ gitstow ui # opens http://127.0.0.1:7853 in your browser
186
+ gitstow ui --port 8080
187
+ gitstow ui --no-browser
188
+ ```
189
+ Persistent local web dashboard for daily repo management — a tab you leave open. Shows dirty state across your library, pulls single repos or all-of-them with a parallel summary panel, adds/removes repos, edits tags, freezes stale ones. Auto-refreshes row status every 30 seconds. Binds `127.0.0.1` only (arbitrary git execution must not be LAN-reachable). Click **Shutdown** in the footer — or Ctrl+C — to stop.
190
+
191
+ ### Interactive Dashboard (TUI)
178
192
  ```bash
179
- gitstow tui # Keyboard-driven dashboard with filter, pull, freeze
193
+ gitstow tui # Keyboard-driven terminal dashboard (SSH-friendly)
180
194
  ```
181
195
 
182
196
  ### JSON Output
@@ -220,14 +234,21 @@ gitstow status --json
220
234
  | `gitstow collection import <file>` | Import a collection from file |
221
235
  | **Shell** | |
222
236
  | `gitstow shell setup` | Show shell integration instructions |
237
+ | `gitstow shell init` | Print shell functions to source in rc file |
223
238
  | `gitstow shell pick` | fzf-powered repo picker |
239
+ | `gitstow shell completions` | Tab completion for repo names, workspaces, tags |
224
240
  | `gitstow tui` | Interactive terminal dashboard |
241
+ | `gitstow fetch` | Fetch all remotes — update ahead/behind counts without merging |
242
+ | `gitstow ui` | Launch local browser dashboard (http://127.0.0.1:7853) |
243
+ | `gitstow update` | Upgrade gitstow itself from PyPI (detects pipx / pip / editable) |
244
+ | `gitstow update --check` | Check PyPI for a newer version without installing |
225
245
  | **Config** | |
226
246
  | `gitstow config show` | Show current config and workspaces |
227
247
  | `gitstow config set <key> <value>` | Change a setting |
228
248
  | `gitstow onboard` | First-run setup wizard |
229
249
  | `gitstow doctor` | Health check |
230
250
  | `gitstow install-skill` | Install Claude Code skill |
251
+ | `gitstow setup-ai` | Auto-detect AI tools and configure integration |
231
252
 
232
253
  All commands accept `-w <label>` to filter to a specific workspace.
233
254
 
@@ -299,6 +320,15 @@ pytest
299
320
  ruff check src/
300
321
  ```
301
322
 
323
+ Release from a `main` branch with no tracked changes:
324
+
325
+ ```bash
326
+ bash scripts/release.sh 0.2.6 "short release note"
327
+ ```
328
+
329
+ The script bumps `pyproject.toml` and `src/gitstow/__init__.py`, commits the bump,
330
+ creates `vX.Y.Z`, and pushes the commit plus tag. Pushing the tag publishes to PyPI.
331
+
302
332
  See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide.
303
333
 
304
334
  ## License
@@ -2,6 +2,8 @@
2
2
 
3
3
  A git repository library manager — clone, organize, and maintain collections of repos you learn from.
4
4
 
5
+ ![gitstow demo](demo.gif)
6
+
5
7
  ## Why?
6
8
 
7
9
  AI-assisted development has created a new relationship with open source. Developers increasingly maintain local clones of repositories they study and reference, not just repos they contribute to. `gitstow` manages this collection as a first-class concern.
@@ -30,11 +32,10 @@ gitstow pull
30
32
 
31
33
  # See your collection
32
34
  gitstow list
33
-
34
- # Check git status across all repos
35
- gitstow status
36
35
  ```
37
36
 
37
+ Prefer a GUI? Run `gitstow ui` — a local dark-themed browser dashboard opens automatically. Dirty state, branch deltas, Pull / Pull-all, add / remove / freeze / tag, workspace CRUD, collection export/import — all in one tab you leave open. See [Browser Dashboard](#browser-dashboard).
38
+
38
39
  ## Features
39
40
 
40
41
  ### Workspaces
@@ -134,9 +135,17 @@ gse # Open repo in editor (fzf picker)
134
135
  gsp # gitstow pull shorthand
135
136
  ```
136
137
 
137
- ### Interactive Dashboard
138
+ ### Browser Dashboard
139
+ ```bash
140
+ gitstow ui # opens http://127.0.0.1:7853 in your browser
141
+ gitstow ui --port 8080
142
+ gitstow ui --no-browser
143
+ ```
144
+ Persistent local web dashboard for daily repo management — a tab you leave open. Shows dirty state across your library, pulls single repos or all-of-them with a parallel summary panel, adds/removes repos, edits tags, freezes stale ones. Auto-refreshes row status every 30 seconds. Binds `127.0.0.1` only (arbitrary git execution must not be LAN-reachable). Click **Shutdown** in the footer — or Ctrl+C — to stop.
145
+
146
+ ### Interactive Dashboard (TUI)
138
147
  ```bash
139
- gitstow tui # Keyboard-driven dashboard with filter, pull, freeze
148
+ gitstow tui # Keyboard-driven terminal dashboard (SSH-friendly)
140
149
  ```
141
150
 
142
151
  ### JSON Output
@@ -180,14 +189,21 @@ gitstow status --json
180
189
  | `gitstow collection import <file>` | Import a collection from file |
181
190
  | **Shell** | |
182
191
  | `gitstow shell setup` | Show shell integration instructions |
192
+ | `gitstow shell init` | Print shell functions to source in rc file |
183
193
  | `gitstow shell pick` | fzf-powered repo picker |
194
+ | `gitstow shell completions` | Tab completion for repo names, workspaces, tags |
184
195
  | `gitstow tui` | Interactive terminal dashboard |
196
+ | `gitstow fetch` | Fetch all remotes — update ahead/behind counts without merging |
197
+ | `gitstow ui` | Launch local browser dashboard (http://127.0.0.1:7853) |
198
+ | `gitstow update` | Upgrade gitstow itself from PyPI (detects pipx / pip / editable) |
199
+ | `gitstow update --check` | Check PyPI for a newer version without installing |
185
200
  | **Config** | |
186
201
  | `gitstow config show` | Show current config and workspaces |
187
202
  | `gitstow config set <key> <value>` | Change a setting |
188
203
  | `gitstow onboard` | First-run setup wizard |
189
204
  | `gitstow doctor` | Health check |
190
205
  | `gitstow install-skill` | Install Claude Code skill |
206
+ | `gitstow setup-ai` | Auto-detect AI tools and configure integration |
191
207
 
192
208
  All commands accept `-w <label>` to filter to a specific workspace.
193
209
 
@@ -259,6 +275,15 @@ pytest
259
275
  ruff check src/
260
276
  ```
261
277
 
278
+ Release from a `main` branch with no tracked changes:
279
+
280
+ ```bash
281
+ bash scripts/release.sh 0.2.6 "short release note"
282
+ ```
283
+
284
+ The script bumps `pyproject.toml` and `src/gitstow/__init__.py`, commits the bump,
285
+ creates `vX.Y.Z`, and pushes the commit plus tag. Pushing the tag publishes to PyPI.
286
+
262
287
  See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide.
263
288
 
264
289
  ## License
gitstow-0.2.6/demo.gif ADDED
Binary file
@@ -1,5 +1,8 @@
1
1
  # gitstow demo — record with: vhs demo.tape
2
2
  # Install vhs: brew install charmbracelet/tap/vhs
3
+ #
4
+ # NOTE: This clones real repos. Run in a temp workspace or clean up after.
5
+ # Before recording, ensure gitstow is configured with a test workspace.
3
6
 
4
7
  Output demo.gif
5
8
 
@@ -12,32 +15,38 @@ Type "# Add repos with gitstow"
12
15
  Enter
13
16
  Sleep 500ms
14
17
 
15
- Type "gitstow add anthropic/claude-code facebook/react"
18
+ Type "gitstow -w demo add charmbracelet/vhs charmbracelet/gum --shallow"
16
19
  Enter
17
- Sleep 3s
20
+ Sleep 12s
18
21
 
22
+ Type ""
23
+ Enter
19
24
  Type "# See your collection"
20
25
  Enter
21
26
  Sleep 500ms
22
27
 
23
- Type "gitstow list"
28
+ Type "gitstow -w demo list"
24
29
  Enter
25
30
  Sleep 2s
26
31
 
32
+ Type ""
33
+ Enter
27
34
  Type "# Git status across all repos"
28
35
  Enter
29
36
  Sleep 500ms
30
37
 
31
- Type "gitstow status"
38
+ Type "gitstow -w demo status"
32
39
  Enter
33
40
  Sleep 2s
34
41
 
42
+ Type ""
43
+ Enter
35
44
  Type "# Update everything"
36
45
  Enter
37
46
  Sleep 500ms
38
47
 
39
- Type "gitstow pull"
48
+ Type "gitstow -w demo pull"
40
49
  Enter
41
- Sleep 3s
50
+ Sleep 4s
42
51
 
43
52
  Sleep 1s
@@ -628,11 +628,11 @@ dev = [
628
628
  12. **Skill** — SKILL.md + install-skill command
629
629
  13. **README** — user-facing documentation
630
630
 
631
- ### Stage 2 — Polish & Power (future)
631
+ ### Stage 2 — Polish & Power (shipped in v0.1.0)
632
632
 
633
633
  | Component | Description |
634
634
  |-----------|-------------|
635
- | TUI | Interactive dashboard via Textual (`gitstow tui`) |
635
+ | TUI | Interactive dashboard via Textual (`gitstow tui`) — broken, parked in BACKLOG |
636
636
  | MCP server | Expose tools to any AI tool via Model Context Protocol |
637
637
  | `search` | Grep across all repos |
638
638
  | `open` | Open repo in editor/browser/Finder |
@@ -642,6 +642,18 @@ dev = [
642
642
  | Shell integration | fzf helpers, shell completions, cd shortcut |
643
643
  | GitHub Actions | Automated PyPI publishing on tag |
644
644
 
645
+ ### Stage 3 — Browser GUI (shipped in v0.2.0 / v0.2.1)
646
+
647
+ | Component | Description |
648
+ |-----------|-------------|
649
+ | `gitstow ui` | Persistent localhost browser dashboard (FastAPI + Jinja2 + HTMX, dark theme). Core feature, not an extra. `src/gitstow/web/` |
650
+ | Read-only dashboard | Status ledger with auto-refresh every 30s via HTMX; repo detail drawer |
651
+ | Mutations | Add / pull single / pull all (parallel) / remove / delete / freeze / tag — HTMX row swaps, no SPA toolchain |
652
+ | Workspace CRUD + Scan | Add/remove workspaces, scan-and-catalog from the UI |
653
+ | Collection I/O | Export YAML/JSON/URLs, import uploads — under Settings |
654
+ | Shutdown | Footer button POSTs `/shutdown` → flips `uvicorn.Server.should_exit` |
655
+ | `gitstow update` (v0.2.1) | Self-upgrade command — detects pipx/pip/editable and runs the right upgrade; `--check` queries PyPI without installing |
656
+
645
657
  ---
646
658
 
647
659
  ## Patterns Adopted