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.
- gitstow-0.2.6/.claude/settings.json +19 -0
- gitstow-0.2.6/.github/workflows/publish.yml +65 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/BACKLOG.md +3 -1
- gitstow-0.2.6/CHANGELOG.md +112 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/CLAUDE.md +10 -4
- {gitstow-0.1.0 → gitstow-0.2.6}/CONTRIBUTING.md +12 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/PKG-INFO +36 -6
- {gitstow-0.1.0 → gitstow-0.2.6}/README.md +30 -5
- gitstow-0.2.6/demo.gif +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/demo.tape +15 -6
- {gitstow-0.1.0 → gitstow-0.2.6}/docs/building/implementation-plan.md +14 -2
- {gitstow-0.1.0 → gitstow-0.2.6}/docs/user/commands.md +131 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/docs/user/concepts.md +1 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/docs/user/getting-started.md +16 -1
- {gitstow-0.1.0 → gitstow-0.2.6}/pyproject.toml +6 -1
- gitstow-0.2.6/scripts/release.sh +137 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/__init__.py +1 -1
- gitstow-0.2.6/src/gitstow/cli/fetch.py +225 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/main.py +7 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/onboard.py +1 -1
- gitstow-0.2.6/src/gitstow/cli/serve.py +49 -0
- gitstow-0.2.6/src/gitstow/cli/update.py +146 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/git.py +31 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/repo.py +3 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/skill/SKILL.md +13 -0
- gitstow-0.2.6/src/gitstow/web/__init__.py +4 -0
- gitstow-0.2.6/src/gitstow/web/routes/__init__.py +1 -0
- gitstow-0.2.6/src/gitstow/web/routes/collection.py +245 -0
- gitstow-0.2.6/src/gitstow/web/routes/dashboard.py +246 -0
- gitstow-0.2.6/src/gitstow/web/routes/pages.py +91 -0
- gitstow-0.2.6/src/gitstow/web/routes/repos.py +489 -0
- gitstow-0.2.6/src/gitstow/web/routes/system.py +23 -0
- gitstow-0.2.6/src/gitstow/web/routes/workspaces.py +121 -0
- gitstow-0.2.6/src/gitstow/web/server.py +100 -0
- gitstow-0.2.6/src/gitstow/web/static/app.css +922 -0
- gitstow-0.2.6/src/gitstow/web/templates/_repo_drawer.html +111 -0
- gitstow-0.2.6/src/gitstow/web/templates/add_repo.html +52 -0
- gitstow-0.2.6/src/gitstow/web/templates/base.html +132 -0
- gitstow-0.2.6/src/gitstow/web/templates/dashboard.html +196 -0
- gitstow-0.2.6/src/gitstow/web/templates/partials/dashboard_rows.html +1 -0
- gitstow-0.2.6/src/gitstow/web/templates/partials/fetch_summary.html +39 -0
- gitstow-0.2.6/src/gitstow/web/templates/partials/pull_summary.html +39 -0
- gitstow-0.2.6/src/gitstow/web/templates/partials/repo_row.html +76 -0
- gitstow-0.2.6/src/gitstow/web/templates/settings.html +103 -0
- gitstow-0.2.6/src/gitstow/web/templates/workspaces.html +97 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/tests/test_cli.py +18 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/tests/test_git.py +40 -0
- gitstow-0.2.6/tests/test_serve.py +409 -0
- gitstow-0.1.0/.github/workflows/release.yml +0 -45
- gitstow-0.1.0/CHANGELOG.md +0 -27
- {gitstow-0.1.0 → gitstow-0.2.6}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/.github/workflows/ci.yml +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/.gitignore +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/CODE_OF_CONDUCT.md +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/LICENSE +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/SECURITY.md +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/docs/user/configuration.md +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/__main__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/__init__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/add.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/config_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/doctor.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/exec_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/export_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/helpers.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/list_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/manage.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/migrate.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/open_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/pull.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/remove.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/search.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/setup_ai.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/shell.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/skill_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/stats.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/status.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/tui.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/cli/workspace_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/__init__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/config.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/discovery.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/parallel.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/paths.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/core/url_parser.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/mcp/__init__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/mcp/server.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/tui/__init__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/src/gitstow/tui/app.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/tests/__init__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/tests/conftest.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/tests/test_config.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.6}/tests/test_repo.py +0 -0
- {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
|
-
- [
|
|
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 (
|
|
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.
|
|
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
|
+

|
|
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
|
-
###
|
|
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
|
|
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
|
+

|
|
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
|
-
###
|
|
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
|
|
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
|
|
18
|
+
Type "gitstow -w demo add charmbracelet/vhs charmbracelet/gum --shallow"
|
|
16
19
|
Enter
|
|
17
|
-
Sleep
|
|
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
|
|
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 (
|
|
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
|