gitstow 0.2.6__tar.gz → 0.3.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.
- {gitstow-0.2.6 → gitstow-0.3.0}/.github/workflows/ci.yml +5 -1
- {gitstow-0.2.6 → gitstow-0.3.0}/.github/workflows/publish.yml +19 -0
- gitstow-0.3.0/AGENTS.md +150 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/BACKLOG.md +2 -2
- {gitstow-0.2.6 → gitstow-0.3.0}/CHANGELOG.md +60 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/CLAUDE.md +27 -17
- {gitstow-0.2.6 → gitstow-0.3.0}/PKG-INFO +20 -18
- {gitstow-0.2.6 → gitstow-0.3.0}/README.md +8 -10
- gitstow-0.3.0/docs/building/audit-2026-07-06.md +149 -0
- gitstow-0.3.0/docs/building/plans/2026-07-06-wave-1-correctness-safety.md +1301 -0
- gitstow-0.3.0/docs/building/plans/2026-07-06-wave-2-status-model.md +1097 -0
- gitstow-0.3.0/docs/building/plans/2026-07-06-wave-3-structure-polish.md +1690 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/docs/user/commands.md +38 -31
- {gitstow-0.2.6 → gitstow-0.3.0}/docs/user/getting-started.md +5 -1
- {gitstow-0.2.6 → gitstow-0.3.0}/pyproject.toml +13 -9
- {gitstow-0.2.6 → gitstow-0.3.0}/scripts/release.sh +6 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/__init__.py +1 -1
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/add.py +100 -34
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/config_cmd.py +44 -41
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/doctor.py +17 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/exec_cmd.py +4 -1
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/export_cmd.py +75 -21
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/fetch.py +33 -70
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/helpers.py +22 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/list_cmd.py +4 -1
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/main.py +0 -2
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/manage.py +42 -34
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/onboard.py +17 -7
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/open_cmd.py +25 -11
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/pull.py +55 -82
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/remove.py +11 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/search.py +43 -30
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/serve.py +3 -2
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/setup_ai.py +4 -4
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/status.py +43 -30
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/workspace_cmd.py +24 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/core/config.py +3 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/core/discovery.py +11 -7
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/core/git.py +31 -6
- gitstow-0.3.0/src/gitstow/core/locking.py +63 -0
- gitstow-0.3.0/src/gitstow/core/operations.py +98 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/core/repo.py +81 -34
- gitstow-0.3.0/src/gitstow/core/status_model.py +119 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/core/url_parser.py +33 -10
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/mcp/server.py +85 -43
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/skill/SKILL.md +5 -3
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/routes/collection.py +5 -1
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/routes/dashboard.py +57 -28
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/routes/pages.py +10 -1
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/routes/repos.py +53 -26
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/server.py +30 -1
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/templates/_repo_drawer.html +1 -9
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/templates/dashboard.html +7 -7
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/templates/partials/pull_summary.html +11 -0
- gitstow-0.3.0/tests/test_cli.py +885 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/tests/test_config.py +72 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/tests/test_git.py +36 -0
- gitstow-0.3.0/tests/test_locking.py +64 -0
- gitstow-0.3.0/tests/test_mcp.py +138 -0
- gitstow-0.3.0/tests/test_onboard.py +122 -0
- gitstow-0.3.0/tests/test_operations.py +67 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/tests/test_repo.py +53 -2
- {gitstow-0.2.6 → gitstow-0.3.0}/tests/test_serve.py +189 -1
- gitstow-0.3.0/tests/test_setup_ai.py +49 -0
- gitstow-0.3.0/tests/test_status_model.py +83 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/tests/test_url_parser.py +35 -0
- gitstow-0.2.6/src/gitstow/cli/tui.py +0 -27
- gitstow-0.2.6/src/gitstow/tui/__init__.py +0 -1
- gitstow-0.2.6/src/gitstow/tui/app.py +0 -384
- gitstow-0.2.6/tests/test_cli.py +0 -80
- {gitstow-0.2.6 → gitstow-0.3.0}/.claude/settings.json +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/.gitignore +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/CODE_OF_CONDUCT.md +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/CONTRIBUTING.md +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/LICENSE +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/SECURITY.md +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/demo.gif +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/demo.tape +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/docs/building/implementation-plan.md +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/docs/user/concepts.md +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/docs/user/configuration.md +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/__main__.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/__init__.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/migrate.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/shell.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/skill_cmd.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/stats.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/cli/update.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/core/__init__.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/core/parallel.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/core/paths.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/mcp/__init__.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/__init__.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/routes/__init__.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/routes/system.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/routes/workspaces.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/static/app.css +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/templates/add_repo.html +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/templates/base.html +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/templates/partials/dashboard_rows.html +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/templates/partials/fetch_summary.html +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/templates/partials/repo_row.html +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/templates/settings.html +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/src/gitstow/web/templates/workspaces.html +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/tests/__init__.py +0 -0
- {gitstow-0.2.6 → gitstow-0.3.0}/tests/conftest.py +0 -0
|
@@ -8,10 +8,14 @@ on:
|
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
test:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
11
|
strategy:
|
|
13
12
|
matrix:
|
|
13
|
+
os: [ubuntu-latest]
|
|
14
14
|
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
include:
|
|
16
|
+
- os: macos-latest
|
|
17
|
+
python-version: "3.12"
|
|
18
|
+
runs-on: ${{ matrix.os }}
|
|
15
19
|
|
|
16
20
|
steps:
|
|
17
21
|
- uses: actions/checkout@v4
|
|
@@ -5,7 +5,26 @@ on:
|
|
|
5
5
|
tags: ["v*"]
|
|
6
6
|
|
|
7
7
|
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
|
|
13
|
+
- uses: actions/setup-python@v5
|
|
14
|
+
with:
|
|
15
|
+
python-version: "3.12"
|
|
16
|
+
|
|
17
|
+
- name: Install dependencies
|
|
18
|
+
run: pip install -e ".[dev]"
|
|
19
|
+
|
|
20
|
+
- name: Lint
|
|
21
|
+
run: ruff check src/
|
|
22
|
+
|
|
23
|
+
- name: Test
|
|
24
|
+
run: pytest --tb=short
|
|
25
|
+
|
|
8
26
|
publish:
|
|
27
|
+
needs: test
|
|
9
28
|
runs-on: ubuntu-latest
|
|
10
29
|
environment: pypi
|
|
11
30
|
permissions:
|
gitstow-0.3.0/AGENTS.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# gitstow - AI Developer Guide
|
|
2
|
+
|
|
3
|
+
## What is this?
|
|
4
|
+
|
|
5
|
+
A CLI tool that manages collections of git repositories across multiple workspaces. Think "package manager for repos" - whether they're open-source projects you learn from or active projects you work on.
|
|
6
|
+
|
|
7
|
+
## Operating Contract
|
|
8
|
+
|
|
9
|
+
- Prefer proper long-term solutions over shortcut patches. If a feature is incomplete in one surface, build the feature into that surface instead of papering over it with wording, partial conditionals, or one-off display logic.
|
|
10
|
+
- Do not recommend quick fixes, temporary patches, or narrow workarounds unless the user explicitly asks for a shortcut.
|
|
11
|
+
- Read the relevant existing code before proposing or editing. Let the current architecture decide where the change belongs.
|
|
12
|
+
- Keep changes scoped to the requested behavior. Avoid unrelated refactors, formatting churn, or drive-by cleanups.
|
|
13
|
+
- Do not revert user changes or generated local state unless the user explicitly asks.
|
|
14
|
+
|
|
15
|
+
## Product Standards
|
|
16
|
+
|
|
17
|
+
- Keep CLI, TUI, web dashboard, JSON output, docs, and tests semantically aligned when changing user-facing status behavior.
|
|
18
|
+
- For repo state presentation, avoid using "dirty" as a broad user-facing bucket for every local change. Present it as local/uncommitted changes with the composition visible: modified, staged, and untracked counts.
|
|
19
|
+
- Keep local working-tree state separate from remote relationship state. For example: local changes, clean, ahead, behind, diverged, frozen, missing.
|
|
20
|
+
- When improving the web dashboard, implement the actual missing dashboard feature and shared classification/model behavior instead of copying a CLI-only assumption into the template.
|
|
21
|
+
|
|
22
|
+
## Key Concept: Workspaces
|
|
23
|
+
|
|
24
|
+
Repos are organized into **workspaces** - directories with a label and layout mode:
|
|
25
|
+
- **structured** layout: `workspace/owner/repo/` (open-source collections)
|
|
26
|
+
- **flat** layout: `workspace/repo/` (active projects, no owner subdirectory)
|
|
27
|
+
|
|
28
|
+
Each workspace can have auto-tags applied to all repos it discovers.
|
|
29
|
+
|
|
30
|
+
## Architecture
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
src/gitstow/
|
|
34
|
+
├── cli/ # Typer commands (thin — delegates to core)
|
|
35
|
+
│ ├── main.py # App entry, command registration, global --workspace flag
|
|
36
|
+
│ ├── helpers.py # Shared workspace resolution, repo lookup, iteration
|
|
37
|
+
│ ├── add.py, pull.py, list_cmd.py, status.py, remove.py # Core commands
|
|
38
|
+
│ ├── workspace_cmd.py # workspace list/add/remove/scan subcommands
|
|
39
|
+
│ ├── manage.py # freeze/unfreeze/tag/untag/info subcommands
|
|
40
|
+
│ ├── exec_cmd.py, search.py, open_cmd.py, stats.py # Power commands
|
|
41
|
+
│ ├── export_cmd.py # export/import collection
|
|
42
|
+
│ ├── shell.py # Shell integration (fzf, aliases)
|
|
43
|
+
│ ├── tui.py # TUI launcher
|
|
44
|
+
│ ├── serve.py # Web dashboard launcher
|
|
45
|
+
│ ├── migrate.py, config_cmd.py, onboard.py, doctor.py, skill_cmd.py
|
|
46
|
+
│ └── __init__.py
|
|
47
|
+
├── core/ # Business logic (git ops, URL parsing, state)
|
|
48
|
+
│ ├── paths.py # Path constants, central repos.yaml resolution
|
|
49
|
+
│ ├── config.py # Workspace + Settings dataclasses, load/save
|
|
50
|
+
│ ├── repo.py # Repo dataclass + RepoStore (nested YAML CRUD)
|
|
51
|
+
│ ├── url_parser.py # URL → (host, owner, repo) extraction
|
|
52
|
+
│ ├── git.py # All git subprocess calls
|
|
53
|
+
│ ├── discovery.py # Walk directory tree (structured + flat), reconcile
|
|
54
|
+
│ ├── parallel.py # Async execution with semaphore
|
|
55
|
+
│ └── __init__.py
|
|
56
|
+
├── tui/ # Textual interactive dashboard
|
|
57
|
+
│ ├── app.py # Main TUI application
|
|
58
|
+
│ └── __init__.py
|
|
59
|
+
├── web/ # FastAPI browser dashboard (gitstow ui)
|
|
60
|
+
│ ├── server.py # FastAPI app, uvicorn runner, app.state.server stash
|
|
61
|
+
│ ├── static/app.css # Dark theme, Bricolage Grotesque + JetBrains Mono
|
|
62
|
+
│ ├── templates/ # Jinja2 — base.html + page templates + partials/
|
|
63
|
+
│ └── routes/ # dashboard.py, repos.py, workspaces.py, collection.py, pages.py, system.py
|
|
64
|
+
└── skill/ # Codex skill (SKILL.md)
|
|
65
|
+
└── SKILL.md
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Key rules:**
|
|
69
|
+
1. CLI never touches git directly - it calls `core/git.py`
|
|
70
|
+
2. `core/repo.py` (RepoStore) is the only module that reads/writes `repos.yaml`
|
|
71
|
+
3. `core/config.py` defines Workspace dataclass - all workspace logic flows from here
|
|
72
|
+
4. `cli/helpers.py` provides `resolve_workspaces()`, `resolve_repo()`, `iter_repos_with_workspace()`
|
|
73
|
+
|
|
74
|
+
## Key Files
|
|
75
|
+
|
|
76
|
+
- `core/config.py` - Workspace + Settings dataclasses. `get_workspaces()` with legacy migration shim.
|
|
77
|
+
- `core/repo.py` - Repo with workspace field, RepoStore with nested YAML format, legacy auto-migration.
|
|
78
|
+
- `core/discovery.py` - `discover_repos(root, layout)` supports structured and flat layouts.
|
|
79
|
+
- `core/url_parser.py` - URL parsing (the hardest part). Test changes here thoroughly.
|
|
80
|
+
- `core/git.py` - All git subprocess calls. Uses `git status --porcelain=v2 --branch` for single-call efficiency.
|
|
81
|
+
- `core/parallel.py` - Async execution with semaphore (max 6 concurrent).
|
|
82
|
+
- `cli/helpers.py` - Shared workspace resolution used by all CLI commands.
|
|
83
|
+
- `cli/workspace_cmd.py` - workspace list/add/remove/scan subcommands.
|
|
84
|
+
- `cli/main.py` - Typer app, global `-w/--workspace` option, command registration.
|
|
85
|
+
- `tui/app.py` - Textual dashboard with DataTable, filter, pull, freeze toggle.
|
|
86
|
+
|
|
87
|
+
## Data Files
|
|
88
|
+
|
|
89
|
+
- `~/.gitstow/config.yaml` - Settings (workspaces list, default host, SSH pref).
|
|
90
|
+
- `~/.gitstow/repos.yaml` - Repo metadata nested by workspace label. Central location.
|
|
91
|
+
|
|
92
|
+
### repos.yaml format
|
|
93
|
+
```yaml
|
|
94
|
+
oss:
|
|
95
|
+
anthropic/Codex:
|
|
96
|
+
remote_url: https://github.com/anthropic/Codex.git
|
|
97
|
+
tags: [ai]
|
|
98
|
+
active:
|
|
99
|
+
gitstow:
|
|
100
|
+
remote_url: https://github.com/rishmadaan/gitstow.git
|
|
101
|
+
tags: [active]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## All Commands (32)
|
|
105
|
+
|
|
106
|
+
**Core:** `add`, `pull`, `fetch`, `list`, `status`, `remove`, `migrate`
|
|
107
|
+
**Workspace:** `workspace list`, `workspace add`, `workspace remove`, `workspace scan`
|
|
108
|
+
**Repo management:** `repo freeze`, `repo unfreeze`, `repo tag`, `repo untag`, `repo tags`, `repo info`
|
|
109
|
+
**Power:** `exec`, `search`, `open`, `stats`
|
|
110
|
+
**Sharing:** `collection export`, `collection import`
|
|
111
|
+
**Shell:** `shell pick`, `shell init`, `shell completions`, `shell setup`, `tui`, `ui`
|
|
112
|
+
**Setup:** `onboard`, `config show/set/path/migrate-root`, `doctor`, `install-skill`, `setup-ai`, `update`
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
cd ~/labs/projects/gitstow
|
|
118
|
+
pip install -e ".[dev]"
|
|
119
|
+
pytest # 44 tests
|
|
120
|
+
ruff check src/
|
|
121
|
+
pip install -e ".[tui]" # For TUI development
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Patterns
|
|
125
|
+
|
|
126
|
+
- `--json -j` and `--quiet -q` on all main commands
|
|
127
|
+
- Global `-w/--workspace` flag filters all commands to a single workspace
|
|
128
|
+
- `cli/helpers.py` for workspace resolution (don't repeat in each command)
|
|
129
|
+
- Rich console for stdout, err_console for stderr
|
|
130
|
+
- Typer with `rich_markup_mode="rich"`, `typer.Context` for global options
|
|
131
|
+
- YAML for persistence (not JSON, not SQLite)
|
|
132
|
+
- asyncio with semaphore for parallel git ops
|
|
133
|
+
- `git status --porcelain=v2 --branch` for single-call status (vs gita's 4-5 calls)
|
|
134
|
+
- Repo.global_key (`workspace:key`) for unique identification across workspaces
|
|
135
|
+
- Legacy format auto-migration (flat repos.yaml -> nested, root_path -> workspaces)
|
|
136
|
+
|
|
137
|
+
## AI Integration
|
|
138
|
+
|
|
139
|
+
**Primary: Codex skill** (`src/gitstow/skill/SKILL.md`)
|
|
140
|
+
- Installed to `~/.Codex/skills/gitstow/` via `gitstow install-skill` or `gitstow onboard`
|
|
141
|
+
- Auto-updates on version bumps (checks `.version` marker on every CLI invocation)
|
|
142
|
+
- Zero context cost when inactive - only loaded when task matches the skill description
|
|
143
|
+
- Codex runs gitstow CLI commands via Bash - full access to all commands
|
|
144
|
+
|
|
145
|
+
**Optional: MCP server** (`src/gitstow/mcp/server.py`)
|
|
146
|
+
- For non-Codex AI tools (Codex Desktop, Cursor, Windsurf)
|
|
147
|
+
- Install: `pip install gitstow[mcp]`, entry point: `gitstow-mcp`
|
|
148
|
+
- 13 tools + 3 resources, wraps same `core/` modules as CLI
|
|
149
|
+
- **Tradeoff:** MCP tools are always loaded into context (costs tokens even when idle).
|
|
150
|
+
The skill has no such cost. Only use MCP for dedicated repo-management setups.
|
|
@@ -9,9 +9,9 @@ Post-v0.1.0 improvements tracked here. See [GitHub Issues](https://github.com/ri
|
|
|
9
9
|
- [x] **Network retry/resume for batch operations** (#3) — `--retry N` flag on add and pull; cleans up partial clones before retry
|
|
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
|
-
- [x] **Publish to PyPI** (#6) — Release workflow created (`.github/workflows/
|
|
12
|
+
- [x] **Publish to PyPI** (#6) — Release workflow created (`.github/workflows/publish.yml`); publish on GitHub release
|
|
13
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
|
-
- [
|
|
14
|
+
- [x] **Fix TUI breakage** — Resolved by retirement: the Textual TUI was removed in v0.3.0; `gitstow ui` (web dashboard) is the visual surface going forward.
|
|
15
15
|
|
|
16
16
|
## Documentation
|
|
17
17
|
|
|
@@ -4,6 +4,66 @@ All notable changes to gitstow will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [0.3.0] - 2026-07-12
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Composition-aware status everywhere.** `gitstow status` now shows a Local Changes column (modified/staged/untracked counts) and a separate Remote column (in-sync/ahead/behind/diverged). The web dashboard rows, repo drawer, and help legend all use the same shared classifier — a repo with only staged or untracked files can no longer display as "clean". JSON output gains additive `local` and `remote` keys (all existing keys preserved).
|
|
12
|
+
- **`gitstow fetch_repos` MCP tool** and a `last_fetched` timestamp in all JSON outputs — MCP clients can now see fetch state, matching the CLI and web dashboard.
|
|
13
|
+
- **Untracked-repo hints on `list` and `status`.** Repos found on disk but not in the registry are now surfaced with a hint pointing at `workspace scan`, instead of being silently invisible.
|
|
14
|
+
- **`doctor` detects orphaned workspaces**, and `workspace remove` now warns when repos would be left pointing at a removed workspace.
|
|
15
|
+
- **`clone_timeout` setting** (`gitstow config set clone_timeout <seconds>`) — clone operations on very large repos no longer fail on a hardcoded 300s limit.
|
|
16
|
+
- **macOS added to the CI test matrix**, matching the packaging classifiers.
|
|
17
|
+
- **CHANGELOG gate in the release script** — `scripts/release.sh` now refuses to cut a release without a corresponding changelog entry.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **`add` clones multiple repos in parallel** and now detects remote mismatches and duplicate URLs before cloning, instead of silently registering whatever is already on disk.
|
|
22
|
+
- **`search` now runs across repos in parallel**, matching `exec`.
|
|
23
|
+
- **Pull, fetch, and the MCP server share one operations layer.** The MCP server now follows the same bulk-pull rule as the CLI and web dashboard (modified/staged skip, diverged skip, untracked-only pulls).
|
|
24
|
+
- **`open` prefers `$VISUAL`/`$EDITOR`** over guessing an editor, and runs terminal editors in the foreground so they actually get a usable TTY.
|
|
25
|
+
- **Disk sizing (`stats`, `repo info`) now shells out to `du`** instead of walking every file in Python — much faster on large repos.
|
|
26
|
+
- **`collection import` honors each entry's recorded workspace** instead of dumping everything into one workspace, and now fails loudly (with a printed error) on newer file versions instead of exiting silently.
|
|
27
|
+
- **The web dashboard's dependencies (FastAPI, uvicorn, Jinja2) moved to the optional `[ui]` extra.** Existing installs keep working; fresh CLI-only installs are ~15 packages lighter. Install with `pip install "gitstow[ui]"` to keep the dashboard.
|
|
28
|
+
- **Bulk pull rule unified and refined (behavior change).** CLI `pull` and the dashboard's Pull-all now follow one rule: repos with modified or staged files are skipped (with the composition shown), diverged repos are skipped (fast-forward pull cannot succeed), and repos with only untracked files ARE pulled — previously the CLI skipped them forever while the web pulled everything.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **`search`, `exec`, and `status` `--json` now emit pure JSON on an empty filter match** — previously they printed a "no repos match" banner and no payload at all, even with `--json` set.
|
|
33
|
+
|
|
34
|
+
### Removed
|
|
35
|
+
|
|
36
|
+
- **The Textual TUI (`gitstow tui`).** The web dashboard (`gitstow ui`) replaced it as the visual surface in v0.2.0; the TUI had been broken and parked since. Git history preserves it.
|
|
37
|
+
|
|
38
|
+
## [0.2.8] - 2026-07-12
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- **Pasted GitHub browse URLs now resolve correctly.** URLs like `/tree/...`, `/blob/...`, `/pull/...` now resolve to the repo root instead of being misparsed.
|
|
43
|
+
- **`config migrate-root`** now actually updates workspace paths, and honors the global `-w/--workspace` flag.
|
|
44
|
+
- **`repo freeze/unfreeze/tag/untag`** now honor `-w/--workspace` and report cross-workspace ambiguity clearly instead of guessing.
|
|
45
|
+
- **`pull --json` and `fetch --json`** always emit pure JSON on stdout — no more banners or progress lines interleaved with the payload.
|
|
46
|
+
- **Pull summary** keeps per-workspace identity for same-named frozen repos in different workspaces.
|
|
47
|
+
- **Bulk git operations** no longer hang on credential prompts and are now locale-independent.
|
|
48
|
+
- **`remove --delete`** refuses to delete paths that resolve outside the workspace root.
|
|
49
|
+
- **Workspace labels** are now validated (lowercase alphanumeric, dash, underscore only).
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
- **Atomic, cross-process-locked writes** to `repos.yaml`, safe for concurrent CLI and web UI use.
|
|
54
|
+
- **Test gate before PyPI publish** — releases now require a passing test suite.
|
|
55
|
+
|
|
56
|
+
### Security
|
|
57
|
+
|
|
58
|
+
- **Web dashboard CSRF protection.** POST routes now reject cross-origin and DNS-rebinding requests on the localhost UI.
|
|
59
|
+
|
|
60
|
+
## [0.2.7] - 2026-05-28
|
|
61
|
+
|
|
62
|
+
### Fixed
|
|
63
|
+
|
|
64
|
+
- **`gitstow onboard`** now uses Beaupy's `default_is_yes` confirmation parameter, fixing first-run setup crashes on confirmation prompts.
|
|
65
|
+
- **AI integration setup** now renders MCP warning text with balanced Rich markup during onboarding and `gitstow setup-ai`.
|
|
66
|
+
|
|
7
67
|
## [0.2.5] - 2026-04-19
|
|
8
68
|
|
|
9
69
|
### Added
|
|
@@ -25,21 +25,20 @@ src/gitstow/
|
|
|
25
25
|
│ ├── exec_cmd.py, search.py, open_cmd.py, stats.py # Power commands
|
|
26
26
|
│ ├── export_cmd.py # export/import collection
|
|
27
27
|
│ ├── shell.py # Shell integration (fzf, aliases)
|
|
28
|
-
│ ├── tui.py # TUI launcher
|
|
29
28
|
│ ├── serve.py # Web dashboard launcher
|
|
30
29
|
│ ├── migrate.py, config_cmd.py, onboard.py, doctor.py, skill_cmd.py
|
|
31
30
|
│ └── __init__.py
|
|
32
31
|
├── core/ # Business logic (git ops, URL parsing, state)
|
|
33
|
-
│ ├── paths.py
|
|
34
|
-
│ ├── config.py
|
|
35
|
-
│ ├── repo.py
|
|
36
|
-
│ ├── url_parser.py
|
|
37
|
-
│ ├── git.py
|
|
38
|
-
│ ├── discovery.py
|
|
39
|
-
│ ├── parallel.py
|
|
40
|
-
│
|
|
41
|
-
├──
|
|
42
|
-
│ ├──
|
|
32
|
+
│ ├── paths.py # Path constants, central repos.yaml resolution
|
|
33
|
+
│ ├── config.py # Workspace + Settings dataclasses, load/save
|
|
34
|
+
│ ├── repo.py # Repo dataclass + RepoStore (nested YAML CRUD)
|
|
35
|
+
│ ├── url_parser.py # URL → (host, owner, repo) extraction
|
|
36
|
+
│ ├── git.py # All git subprocess calls
|
|
37
|
+
│ ├── discovery.py # Walk directory tree (structured + flat), reconcile
|
|
38
|
+
│ ├── parallel.py # Async execution with semaphore
|
|
39
|
+
│ ├── status_model.py # Shared repo-state classifier — local composition vs remote relationship
|
|
40
|
+
│ ├── operations.py # Shared filter + bulk-runner layer (pull/fetch/MCP)
|
|
41
|
+
│ ├── locking.py # Cross-process file lock guarding repos.yaml writes
|
|
43
42
|
│ └── __init__.py
|
|
44
43
|
├── web/ # FastAPI browser dashboard (gitstow ui)
|
|
45
44
|
│ ├── server.py # FastAPI app, uvicorn runner, app.state.server stash
|
|
@@ -64,15 +63,18 @@ src/gitstow/
|
|
|
64
63
|
- `core/url_parser.py` — URL parsing (the hardest part). Test changes here thoroughly.
|
|
65
64
|
- `core/git.py` — All git subprocess calls. Uses `git status --porcelain=v2 --branch` for single-call efficiency.
|
|
66
65
|
- `core/parallel.py` — Async execution with semaphore (max 6 concurrent).
|
|
66
|
+
- `core/status_model.py` — `RepoState` — the single source of truth for local (modified/staged/untracked) vs remote (in-sync/ahead/behind/diverged) classification, consumed by CLI, web, and JSON.
|
|
67
|
+
- `core/operations.py` — Shared `filter_repo_pairs()` + bulk-runner used by `pull`, `fetch`, and the MCP server so surfaces can't drift.
|
|
68
|
+
- `core/locking.py` — `file_lock()` cross-process advisory lock guarding `repos.yaml` against concurrent CLI/web writes.
|
|
67
69
|
- `cli/helpers.py` — Shared workspace resolution used by all CLI commands.
|
|
68
70
|
- `cli/workspace_cmd.py` — workspace list/add/remove/scan subcommands.
|
|
69
71
|
- `cli/main.py` — Typer app, global `-w/--workspace` option, command registration.
|
|
70
|
-
- `tui/app.py` — Textual dashboard with DataTable, filter, pull, freeze toggle.
|
|
71
72
|
|
|
72
73
|
## Data Files
|
|
73
74
|
|
|
74
75
|
- `~/.gitstow/config.yaml` — Settings (workspaces list, default host, SSH pref).
|
|
75
76
|
- `~/.gitstow/repos.yaml` — Repo metadata nested by workspace label. Central location.
|
|
77
|
+
- `~/.gitstow/repos.lock` — Cross-process advisory lock file (`core/locking.py`) held during `repos.yaml` writes. Not user-facing data; safe to ignore/delete if orphaned.
|
|
76
78
|
|
|
77
79
|
### repos.yaml format
|
|
78
80
|
```yaml
|
|
@@ -86,14 +88,14 @@ active:
|
|
|
86
88
|
tags: [active]
|
|
87
89
|
```
|
|
88
90
|
|
|
89
|
-
## All Commands (
|
|
91
|
+
## All Commands (37)
|
|
90
92
|
|
|
91
93
|
**Core:** `add`, `pull`, `fetch`, `list`, `status`, `remove`, `migrate`
|
|
92
94
|
**Workspace:** `workspace list`, `workspace add`, `workspace remove`, `workspace scan`
|
|
93
95
|
**Repo management:** `repo freeze`, `repo unfreeze`, `repo tag`, `repo untag`, `repo tags`, `repo info`
|
|
94
96
|
**Power:** `exec`, `search`, `open`, `stats`
|
|
95
97
|
**Sharing:** `collection export`, `collection import`
|
|
96
|
-
**Shell:** `shell pick`, `shell init`, `shell completions`, `shell setup`, `
|
|
98
|
+
**Shell:** `shell pick`, `shell init`, `shell completions`, `shell setup`, `ui`
|
|
97
99
|
**Setup:** `onboard`, `config show/set/path/migrate-root`, `doctor`, `install-skill`, `setup-ai`, `update`
|
|
98
100
|
|
|
99
101
|
## Development
|
|
@@ -101,9 +103,8 @@ active:
|
|
|
101
103
|
```bash
|
|
102
104
|
cd ~/labs/projects/gitstow
|
|
103
105
|
pip install -e ".[dev]"
|
|
104
|
-
pytest #
|
|
106
|
+
pytest # full suite — keep green
|
|
105
107
|
ruff check src/
|
|
106
|
-
pip install -e ".[tui]" # For TUI development
|
|
107
108
|
```
|
|
108
109
|
|
|
109
110
|
## Patterns
|
|
@@ -119,6 +120,15 @@ pip install -e ".[tui]" # For TUI development
|
|
|
119
120
|
- Repo.global_key (`workspace:key`) for unique identification across workspaces
|
|
120
121
|
- Legacy format auto-migration (flat repos.yaml → nested, root_path → workspaces)
|
|
121
122
|
|
|
123
|
+
## Product & Implementation Standards
|
|
124
|
+
|
|
125
|
+
- Prefer proper long-term solutions over shortcut patches. If a feature is incomplete in one surface, build the feature into that surface instead of papering over it with wording, partial conditionals, or one-off display logic.
|
|
126
|
+
- Do not recommend quick fixes, temporary patches, or narrow workarounds unless the user explicitly asks for a shortcut.
|
|
127
|
+
- Keep CLI, web dashboard, JSON output, docs, and tests semantically aligned when changing user-facing status behavior.
|
|
128
|
+
- For repo state presentation, avoid using "dirty" as a broad user-facing bucket for every local change. Present it as local/uncommitted changes with the composition visible: modified, staged, and untracked counts.
|
|
129
|
+
- Keep local working-tree state separate from remote relationship state. For example: local changes, clean, ahead, behind, diverged, frozen, missing.
|
|
130
|
+
- When improving the web dashboard, implement the actual missing dashboard feature and shared classification/model behavior instead of copying a CLI-only assumption into the template.
|
|
131
|
+
|
|
122
132
|
## AI Integration
|
|
123
133
|
|
|
124
134
|
**Primary: Claude Code skill** (`src/gitstow/skill/SKILL.md`)
|
|
@@ -130,6 +140,6 @@ pip install -e ".[tui]" # For TUI development
|
|
|
130
140
|
**Optional: MCP server** (`src/gitstow/mcp/server.py`)
|
|
131
141
|
- For non-Claude-Code AI tools (Claude Desktop, Cursor, Windsurf)
|
|
132
142
|
- Install: `pip install gitstow[mcp]`, entry point: `gitstow-mcp`
|
|
133
|
-
-
|
|
143
|
+
- 14 tools + 3 resources, wraps same `core/` modules as CLI
|
|
134
144
|
- **Tradeoff:** MCP tools are always loaded into context (costs tokens even when idle).
|
|
135
145
|
The skill has no such cost. Only use MCP for dedicated repo-management setups.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitstow
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
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,21 +26,25 @@ 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
|
|
32
29
|
Requires-Dist: pyyaml>=6.0
|
|
33
30
|
Requires-Dist: rich>=13.0
|
|
34
|
-
Requires-Dist: typer
|
|
35
|
-
Requires-Dist: uvicorn>=0.27
|
|
31
|
+
Requires-Dist: typer>=0.9
|
|
36
32
|
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: fastapi>=0.110; extra == 'dev'
|
|
37
34
|
Requires-Dist: httpx>=0.27; extra == 'dev'
|
|
35
|
+
Requires-Dist: jinja2>=3.1; extra == 'dev'
|
|
36
|
+
Requires-Dist: mcp>=1.0; extra == 'dev'
|
|
38
37
|
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: python-multipart>=0.0.9; extra == 'dev'
|
|
39
39
|
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
40
|
+
Requires-Dist: uvicorn>=0.27; extra == 'dev'
|
|
40
41
|
Provides-Extra: mcp
|
|
41
42
|
Requires-Dist: mcp>=1.0; extra == 'mcp'
|
|
42
|
-
Provides-Extra:
|
|
43
|
-
Requires-Dist:
|
|
43
|
+
Provides-Extra: ui
|
|
44
|
+
Requires-Dist: fastapi>=0.110; extra == 'ui'
|
|
45
|
+
Requires-Dist: jinja2>=3.1; extra == 'ui'
|
|
46
|
+
Requires-Dist: python-multipart>=0.0.9; extra == 'ui'
|
|
47
|
+
Requires-Dist: uvicorn>=0.27; extra == 'ui'
|
|
44
48
|
Description-Content-Type: text/markdown
|
|
45
49
|
|
|
46
50
|
# gitstow
|
|
@@ -62,8 +66,8 @@ Existing tools solve parts of this:
|
|
|
62
66
|
## Quick Start
|
|
63
67
|
|
|
64
68
|
```bash
|
|
65
|
-
pipx install gitstow # recommended
|
|
66
|
-
# or: pip install gitstow
|
|
69
|
+
pipx install "gitstow[ui]" # recommended — CLI + browser dashboard
|
|
70
|
+
# or: pip install gitstow # CLI only; add [ui] for the dashboard
|
|
67
71
|
|
|
68
72
|
# First-run setup (optional — works without it)
|
|
69
73
|
gitstow onboard
|
|
@@ -99,6 +103,8 @@ gitstow workspace scan active
|
|
|
99
103
|
```bash
|
|
100
104
|
gitstow add anthropic/claude-code facebook/react torvalds/linux
|
|
101
105
|
```
|
|
106
|
+
Multiple URLs clone concurrently (bounded by `parallel_limit`, default 6) — a mismatched remote on an existing path errors instead of silently registering, and duplicate URLs in the same invocation are deduped.
|
|
107
|
+
|
|
102
108
|
Creates (in a structured workspace):
|
|
103
109
|
```
|
|
104
110
|
~/oss/
|
|
@@ -117,8 +123,9 @@ gitstow -w oss pull # Only update oss workspace
|
|
|
117
123
|
gitstow pull --tag ai # Only repos tagged 'ai'
|
|
118
124
|
gitstow pull --exclude-tag stale # Everything except stale repos
|
|
119
125
|
gitstow status # Git status dashboard
|
|
120
|
-
gitstow -w active status --dirty #
|
|
126
|
+
gitstow -w active status --dirty # Repos with local changes in active workspace
|
|
121
127
|
```
|
|
128
|
+
`status` shows local changes as a composition (e.g. "2 modified · 1 staged · 3 untracked") rather than a single "dirty" bucket, and keeps the remote relationship (ahead/behind/diverged) in its own column.
|
|
122
129
|
|
|
123
130
|
### Freeze & Tags
|
|
124
131
|
```bash
|
|
@@ -182,17 +189,13 @@ gsp # gitstow pull shorthand
|
|
|
182
189
|
|
|
183
190
|
### Browser Dashboard
|
|
184
191
|
```bash
|
|
185
|
-
gitstow
|
|
192
|
+
pip install "gitstow[ui]" # if you installed CLI-only
|
|
193
|
+
gitstow ui # opens http://127.0.0.1:7853 in your browser
|
|
186
194
|
gitstow ui --port 8080
|
|
187
195
|
gitstow ui --no-browser
|
|
188
196
|
```
|
|
189
197
|
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
198
|
|
|
191
|
-
### Interactive Dashboard (TUI)
|
|
192
|
-
```bash
|
|
193
|
-
gitstow tui # Keyboard-driven terminal dashboard (SSH-friendly)
|
|
194
|
-
```
|
|
195
|
-
|
|
196
199
|
### JSON Output
|
|
197
200
|
Every command supports `--json` for scripting and AI consumption:
|
|
198
201
|
```bash
|
|
@@ -237,7 +240,6 @@ gitstow status --json
|
|
|
237
240
|
| `gitstow shell init` | Print shell functions to source in rc file |
|
|
238
241
|
| `gitstow shell pick` | fzf-powered repo picker |
|
|
239
242
|
| `gitstow shell completions` | Tab completion for repo names, workspaces, tags |
|
|
240
|
-
| `gitstow tui` | Interactive terminal dashboard |
|
|
241
243
|
| `gitstow fetch` | Fetch all remotes — update ahead/behind counts without merging |
|
|
242
244
|
| `gitstow ui` | Launch local browser dashboard (http://127.0.0.1:7853) |
|
|
243
245
|
| `gitstow update` | Upgrade gitstow itself from PyPI (detects pipx / pip / editable) |
|
|
@@ -17,8 +17,8 @@ Existing tools solve parts of this:
|
|
|
17
17
|
## Quick Start
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
pipx install gitstow # recommended
|
|
21
|
-
# or: pip install gitstow
|
|
20
|
+
pipx install "gitstow[ui]" # recommended — CLI + browser dashboard
|
|
21
|
+
# or: pip install gitstow # CLI only; add [ui] for the dashboard
|
|
22
22
|
|
|
23
23
|
# First-run setup (optional — works without it)
|
|
24
24
|
gitstow onboard
|
|
@@ -54,6 +54,8 @@ gitstow workspace scan active
|
|
|
54
54
|
```bash
|
|
55
55
|
gitstow add anthropic/claude-code facebook/react torvalds/linux
|
|
56
56
|
```
|
|
57
|
+
Multiple URLs clone concurrently (bounded by `parallel_limit`, default 6) — a mismatched remote on an existing path errors instead of silently registering, and duplicate URLs in the same invocation are deduped.
|
|
58
|
+
|
|
57
59
|
Creates (in a structured workspace):
|
|
58
60
|
```
|
|
59
61
|
~/oss/
|
|
@@ -72,8 +74,9 @@ gitstow -w oss pull # Only update oss workspace
|
|
|
72
74
|
gitstow pull --tag ai # Only repos tagged 'ai'
|
|
73
75
|
gitstow pull --exclude-tag stale # Everything except stale repos
|
|
74
76
|
gitstow status # Git status dashboard
|
|
75
|
-
gitstow -w active status --dirty #
|
|
77
|
+
gitstow -w active status --dirty # Repos with local changes in active workspace
|
|
76
78
|
```
|
|
79
|
+
`status` shows local changes as a composition (e.g. "2 modified · 1 staged · 3 untracked") rather than a single "dirty" bucket, and keeps the remote relationship (ahead/behind/diverged) in its own column.
|
|
77
80
|
|
|
78
81
|
### Freeze & Tags
|
|
79
82
|
```bash
|
|
@@ -137,17 +140,13 @@ gsp # gitstow pull shorthand
|
|
|
137
140
|
|
|
138
141
|
### Browser Dashboard
|
|
139
142
|
```bash
|
|
140
|
-
gitstow
|
|
143
|
+
pip install "gitstow[ui]" # if you installed CLI-only
|
|
144
|
+
gitstow ui # opens http://127.0.0.1:7853 in your browser
|
|
141
145
|
gitstow ui --port 8080
|
|
142
146
|
gitstow ui --no-browser
|
|
143
147
|
```
|
|
144
148
|
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
149
|
|
|
146
|
-
### Interactive Dashboard (TUI)
|
|
147
|
-
```bash
|
|
148
|
-
gitstow tui # Keyboard-driven terminal dashboard (SSH-friendly)
|
|
149
|
-
```
|
|
150
|
-
|
|
151
150
|
### JSON Output
|
|
152
151
|
Every command supports `--json` for scripting and AI consumption:
|
|
153
152
|
```bash
|
|
@@ -192,7 +191,6 @@ gitstow status --json
|
|
|
192
191
|
| `gitstow shell init` | Print shell functions to source in rc file |
|
|
193
192
|
| `gitstow shell pick` | fzf-powered repo picker |
|
|
194
193
|
| `gitstow shell completions` | Tab completion for repo names, workspaces, tags |
|
|
195
|
-
| `gitstow tui` | Interactive terminal dashboard |
|
|
196
194
|
| `gitstow fetch` | Fetch all remotes — update ahead/behind counts without merging |
|
|
197
195
|
| `gitstow ui` | Launch local browser dashboard (http://127.0.0.1:7853) |
|
|
198
196
|
| `gitstow update` | Upgrade gitstow itself from PyPI (detects pipx / pip / editable) |
|