gitstow 0.1.0__tar.gz → 0.2.8__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.8/.claude/settings.json +19 -0
- gitstow-0.2.8/.github/workflows/publish.yml +84 -0
- gitstow-0.2.8/AGENTS.md +150 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/BACKLOG.md +3 -1
- gitstow-0.2.8/CHANGELOG.md +141 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/CLAUDE.md +19 -4
- {gitstow-0.1.0 → gitstow-0.2.8}/CONTRIBUTING.md +12 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/PKG-INFO +36 -6
- {gitstow-0.1.0 → gitstow-0.2.8}/README.md +30 -5
- gitstow-0.2.8/demo.gif +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/demo.tape +15 -6
- gitstow-0.2.8/docs/building/audit-2026-07-06.md +149 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/docs/building/implementation-plan.md +14 -2
- gitstow-0.2.8/docs/building/plans/2026-07-06-wave-1-correctness-safety.md +1301 -0
- gitstow-0.2.8/docs/building/plans/2026-07-06-wave-2-status-model.md +1097 -0
- gitstow-0.2.8/docs/building/plans/2026-07-06-wave-3-structure-polish.md +1690 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/docs/user/commands.md +131 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/docs/user/concepts.md +1 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/docs/user/getting-started.md +16 -1
- {gitstow-0.1.0 → gitstow-0.2.8}/pyproject.toml +6 -1
- gitstow-0.2.8/scripts/release.sh +137 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/__init__.py +1 -1
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/config_cmd.py +39 -38
- gitstow-0.2.8/src/gitstow/cli/fetch.py +225 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/main.py +7 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/manage.py +38 -33
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/onboard.py +16 -7
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/pull.py +12 -11
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/remove.py +11 -0
- gitstow-0.2.8/src/gitstow/cli/serve.py +49 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/setup_ai.py +4 -4
- gitstow-0.2.8/src/gitstow/cli/update.py +146 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/workspace_cmd.py +15 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/core/git.py +40 -1
- gitstow-0.2.8/src/gitstow/core/locking.py +63 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/core/repo.py +53 -34
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/core/url_parser.py +33 -10
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/skill/SKILL.md +13 -0
- gitstow-0.2.8/src/gitstow/web/__init__.py +4 -0
- gitstow-0.2.8/src/gitstow/web/routes/__init__.py +1 -0
- gitstow-0.2.8/src/gitstow/web/routes/collection.py +245 -0
- gitstow-0.2.8/src/gitstow/web/routes/dashboard.py +246 -0
- gitstow-0.2.8/src/gitstow/web/routes/pages.py +91 -0
- gitstow-0.2.8/src/gitstow/web/routes/repos.py +489 -0
- gitstow-0.2.8/src/gitstow/web/routes/system.py +23 -0
- gitstow-0.2.8/src/gitstow/web/routes/workspaces.py +121 -0
- gitstow-0.2.8/src/gitstow/web/server.py +129 -0
- gitstow-0.2.8/src/gitstow/web/static/app.css +922 -0
- gitstow-0.2.8/src/gitstow/web/templates/_repo_drawer.html +111 -0
- gitstow-0.2.8/src/gitstow/web/templates/add_repo.html +52 -0
- gitstow-0.2.8/src/gitstow/web/templates/base.html +132 -0
- gitstow-0.2.8/src/gitstow/web/templates/dashboard.html +196 -0
- gitstow-0.2.8/src/gitstow/web/templates/partials/dashboard_rows.html +1 -0
- gitstow-0.2.8/src/gitstow/web/templates/partials/fetch_summary.html +39 -0
- gitstow-0.2.8/src/gitstow/web/templates/partials/pull_summary.html +39 -0
- gitstow-0.2.8/src/gitstow/web/templates/partials/repo_row.html +76 -0
- gitstow-0.2.8/src/gitstow/web/templates/settings.html +103 -0
- gitstow-0.2.8/src/gitstow/web/templates/workspaces.html +97 -0
- gitstow-0.2.8/tests/test_cli.py +266 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/tests/test_config.py +63 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/tests/test_git.py +54 -0
- gitstow-0.2.8/tests/test_locking.py +64 -0
- gitstow-0.2.8/tests/test_onboard.py +122 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/tests/test_repo.py +2 -2
- gitstow-0.2.8/tests/test_serve.py +435 -0
- gitstow-0.2.8/tests/test_setup_ai.py +49 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/tests/test_url_parser.py +35 -0
- gitstow-0.1.0/.github/workflows/release.yml +0 -45
- gitstow-0.1.0/CHANGELOG.md +0 -27
- gitstow-0.1.0/tests/test_cli.py +0 -62
- {gitstow-0.1.0 → gitstow-0.2.8}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/.github/workflows/ci.yml +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/.gitignore +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/CODE_OF_CONDUCT.md +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/LICENSE +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/SECURITY.md +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/docs/user/configuration.md +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/__main__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/__init__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/add.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/doctor.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/exec_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/export_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/helpers.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/list_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/migrate.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/open_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/search.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/shell.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/skill_cmd.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/stats.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/status.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/cli/tui.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/core/__init__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/core/config.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/core/discovery.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/core/parallel.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/core/paths.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/mcp/__init__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/mcp/server.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/tui/__init__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/src/gitstow/tui/app.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/tests/__init__.py +0 -0
- {gitstow-0.1.0 → gitstow-0.2.8}/tests/conftest.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,84 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
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
|
+
|
|
26
|
+
publish:
|
|
27
|
+
needs: test
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
environment: pypi
|
|
30
|
+
permissions:
|
|
31
|
+
contents: read
|
|
32
|
+
id-token: write
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- uses: actions/setup-python@v5
|
|
37
|
+
with:
|
|
38
|
+
python-version: "3.12"
|
|
39
|
+
|
|
40
|
+
- name: Install build tools
|
|
41
|
+
run: pip install build
|
|
42
|
+
|
|
43
|
+
- name: Build package
|
|
44
|
+
run: python -m build
|
|
45
|
+
|
|
46
|
+
- name: Verify version matches tag
|
|
47
|
+
run: |
|
|
48
|
+
python - <<'PY'
|
|
49
|
+
import os
|
|
50
|
+
import pathlib
|
|
51
|
+
import re
|
|
52
|
+
import sys
|
|
53
|
+
import tomllib
|
|
54
|
+
|
|
55
|
+
tag_version = os.environ["GITHUB_REF"].removeprefix("refs/tags/v")
|
|
56
|
+
|
|
57
|
+
with open("pyproject.toml", "rb") as f:
|
|
58
|
+
package_version = tomllib.load(f)["project"]["version"]
|
|
59
|
+
|
|
60
|
+
init_text = pathlib.Path("src/gitstow/__init__.py").read_text()
|
|
61
|
+
match = re.search(r'__version__ = "([^"]+)"', init_text)
|
|
62
|
+
init_version = match.group(1) if match else None
|
|
63
|
+
|
|
64
|
+
errors = []
|
|
65
|
+
if tag_version != package_version:
|
|
66
|
+
errors.append(
|
|
67
|
+
f"Tag v{tag_version} does not match package version {package_version}"
|
|
68
|
+
)
|
|
69
|
+
if init_version != package_version:
|
|
70
|
+
errors.append(
|
|
71
|
+
f"src/gitstow/__init__.py version {init_version} "
|
|
72
|
+
f"does not match package version {package_version}"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if errors:
|
|
76
|
+
for error in errors:
|
|
77
|
+
print(f"::error::{error}")
|
|
78
|
+
sys.exit(1)
|
|
79
|
+
|
|
80
|
+
print(f"Publishing gitstow v{package_version}")
|
|
81
|
+
PY
|
|
82
|
+
|
|
83
|
+
- name: Publish to PyPI
|
|
84
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
gitstow-0.2.8/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.
|
|
@@ -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,141 @@
|
|
|
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.8] - 2026-07-12
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **Pasted GitHub browse URLs now resolve correctly.** URLs like `/tree/...`, `/blob/...`, `/pull/...` now resolve to the repo root instead of being misparsed.
|
|
12
|
+
- **`config migrate-root`** now actually updates workspace paths, and honors the global `-w/--workspace` flag.
|
|
13
|
+
- **`repo freeze/unfreeze/tag/untag`** now honor `-w/--workspace` and report cross-workspace ambiguity clearly instead of guessing.
|
|
14
|
+
- **`pull --json` and `fetch --json`** always emit pure JSON on stdout — no more banners or progress lines interleaved with the payload.
|
|
15
|
+
- **Pull summary** keeps per-workspace identity for same-named frozen repos in different workspaces.
|
|
16
|
+
- **Bulk git operations** no longer hang on credential prompts and are now locale-independent.
|
|
17
|
+
- **`remove --delete`** refuses to delete paths that resolve outside the workspace root.
|
|
18
|
+
- **Workspace labels** are now validated (lowercase alphanumeric, dash, underscore only).
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **Atomic, cross-process-locked writes** to `repos.yaml`, safe for concurrent CLI and web UI use.
|
|
23
|
+
- **Test gate before PyPI publish** — releases now require a passing test suite.
|
|
24
|
+
|
|
25
|
+
### Security
|
|
26
|
+
|
|
27
|
+
- **Web dashboard CSRF protection.** POST routes now reject cross-origin and DNS-rebinding requests on the localhost UI.
|
|
28
|
+
|
|
29
|
+
## [0.2.7] - 2026-05-28
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- **`gitstow onboard`** now uses Beaupy's `default_is_yes` confirmation parameter, fixing first-run setup crashes on confirmation prompts.
|
|
34
|
+
- **AI integration setup** now renders MCP warning text with balanced Rich markup during onboarding and `gitstow setup-ai`.
|
|
35
|
+
|
|
36
|
+
## [0.2.5] - 2026-04-19
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- **`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.
|
|
41
|
+
- **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.
|
|
42
|
+
- **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.
|
|
43
|
+
- **`last_fetched` timestamp** tracked per repo in `repos.yaml`. Stamped on successful fetch operations. Backward-compatible — existing repos default to empty.
|
|
44
|
+
- Updated help dialog and tooltips to reference Fetch all instead of "fetch manually."
|
|
45
|
+
|
|
46
|
+
## [0.2.4] - 2026-04-19
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- **Renamed `gitstow serve` → `gitstow ui`** — more intuitive command name for the browser dashboard. `gitstow serve` remains as a hidden alias for backwards compatibility.
|
|
51
|
+
- **Removed `WEB_GUI_PLAN.md`** — shipped planning artifact retired; git history preserves it.
|
|
52
|
+
|
|
53
|
+
## [0.2.3] - 2026-04-18
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- **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.
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
|
|
61
|
+
- **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.
|
|
62
|
+
- **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).
|
|
63
|
+
|
|
64
|
+
## [0.2.2] - 2026-04-18
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
|
|
68
|
+
- **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.
|
|
69
|
+
- **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.
|
|
70
|
+
- **"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.
|
|
71
|
+
- Matching `docs/user/commands.md` "Reading the dashboard" subsection under `gitstow ui` so the legend exists in prose too, not only in the UI.
|
|
72
|
+
|
|
73
|
+
### Changed
|
|
74
|
+
|
|
75
|
+
- `_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.
|
|
76
|
+
|
|
77
|
+
## [0.2.1] - 2026-04-17
|
|
78
|
+
|
|
79
|
+
### Added
|
|
80
|
+
|
|
81
|
+
- **`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.
|
|
82
|
+
- Smoke tests for `serve` and `update` command help.
|
|
83
|
+
|
|
84
|
+
### Fixed
|
|
85
|
+
|
|
86
|
+
- **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.
|
|
87
|
+
|
|
88
|
+
## [0.2.0] - 2026-04-17
|
|
89
|
+
|
|
90
|
+
### Added
|
|
91
|
+
|
|
92
|
+
- **`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.
|
|
93
|
+
- **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.
|
|
94
|
+
- **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.
|
|
95
|
+
- **Add repo** — form with URL parser, workspace selector, and optional tags; merges workspace auto-tags on clone.
|
|
96
|
+
- **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).
|
|
97
|
+
- **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.
|
|
98
|
+
- **Workspaces** — list, add (label + path + layout + auto-tags), remove (files untouched), **Scan** (discovers untracked repos on disk and catalogs them with auto-tags merged).
|
|
99
|
+
- **Collection export / import** — under Settings; downloads YAML (canonical round-trip), JSON, or plain URL list; upload accepts any of the three.
|
|
100
|
+
- **Auto-refresh** — dashboard tbody reloads every 30s via HTMX `hx-trigger="every 30s"` without touching hero, metrics, or action bar.
|
|
101
|
+
- **Shutdown** — footer button POSTs `/shutdown`, which flips `uvicorn.Server.should_exit` (Ctrl+C also works).
|
|
102
|
+
- **New core dependencies** (shipped, not behind an extra): `fastapi>=0.110`, `uvicorn>=0.27`, `jinja2>=3.1`, `python-multipart>=0.0.9`.
|
|
103
|
+
- **30 FastAPI TestClient smoke tests** covering every route + mutation path. Monkeypatches isolate config/repo files to tmp; git calls are mocked (never shells out).
|
|
104
|
+
|
|
105
|
+
### Changed
|
|
106
|
+
|
|
107
|
+
- Command count 29 → 30 (`serve` added).
|
|
108
|
+
- `CLAUDE.md` architecture tree expanded to document the new `web/` module.
|
|
109
|
+
|
|
110
|
+
### Security
|
|
111
|
+
|
|
112
|
+
- `gitstow ui` binds `127.0.0.1` only. There is no `--host` flag — arbitrary git execution must not be LAN-reachable.
|
|
113
|
+
- All mutations are POST; `/shutdown` is POST so stray links can't terminate the server.
|
|
114
|
+
- Registry + disk delete resolves the repo path and verifies it lives under the workspace root before `rmtree`.
|
|
115
|
+
|
|
116
|
+
### Deferred
|
|
117
|
+
|
|
118
|
+
- 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.
|
|
119
|
+
- Web GUI is intentionally single-user + localhost-only. Auth, multi-user, HTTPS, remote access, and daemonization are explicitly out of scope for v0.2.
|
|
120
|
+
|
|
121
|
+
## [0.1.0] - 2026-04-10
|
|
122
|
+
|
|
123
|
+
Initial release.
|
|
124
|
+
|
|
125
|
+
### Added
|
|
126
|
+
|
|
127
|
+
- **Core commands:** `add`, `pull`, `list`, `status`, `remove`, `migrate`
|
|
128
|
+
- **Workspace system:** Multiple workspaces with structured (`owner/repo`) and flat (`repo`) layouts
|
|
129
|
+
- **Workspace commands:** `workspace list`, `workspace add`, `workspace remove`, `workspace scan`
|
|
130
|
+
- **Repo management:** `repo freeze`, `repo unfreeze`, `repo tag`, `repo untag`, `repo tags`, `repo info`
|
|
131
|
+
- **Bulk operations:** Parallel pull/status with configurable concurrency (default 6)
|
|
132
|
+
- **Power commands:** `exec` (run commands across repos), `search` (grep across repos via ripgrep), `open` (editor/browser/finder), `stats`
|
|
133
|
+
- **Collection sharing:** `collection export` (YAML/JSON/URLs) and `collection import`
|
|
134
|
+
- **Shell integration:** `shell pick` (fzf picker), `shell init` (aliases), `shell setup`
|
|
135
|
+
- **Interactive TUI:** `tui` command with Textual-based dashboard (filter, pull, freeze toggle)
|
|
136
|
+
- **URL parsing:** GitHub, GitLab, Bitbucket, Codeberg, Azure DevOps, custom hosts; HTTPS, SSH, and shorthand formats
|
|
137
|
+
- **AI integration:** Claude Code skill (auto-installed via `onboard` or `install-skill`) and optional MCP server
|
|
138
|
+
- **Setup:** `onboard` wizard, `doctor` health check, `config show/set`
|
|
139
|
+
- **Output modes:** `--json` and `--quiet` flags on all main commands
|
|
140
|
+
- **Global workspace filter:** `-w/--workspace` flag on all commands
|
|
141
|
+
- **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
|
|
|
@@ -113,6 +119,15 @@ pip install -e ".[tui]" # For TUI development
|
|
|
113
119
|
- Repo.global_key (`workspace:key`) for unique identification across workspaces
|
|
114
120
|
- Legacy format auto-migration (flat repos.yaml → nested, root_path → workspaces)
|
|
115
121
|
|
|
122
|
+
## Product & Implementation Standards
|
|
123
|
+
|
|
124
|
+
- 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.
|
|
125
|
+
- Do not recommend quick fixes, temporary patches, or narrow workarounds unless the user explicitly asks for a shortcut.
|
|
126
|
+
- Keep CLI, TUI, web dashboard, JSON output, docs, and tests semantically aligned when changing user-facing status behavior.
|
|
127
|
+
- 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.
|
|
128
|
+
- Keep local working-tree state separate from remote relationship state. For example: local changes, clean, ahead, behind, diverged, frozen, missing.
|
|
129
|
+
- 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.
|
|
130
|
+
|
|
116
131
|
## AI Integration
|
|
117
132
|
|
|
118
133
|
**Primary: Claude Code skill** (`src/gitstow/skill/SKILL.md`)
|
|
@@ -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.8
|
|
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
|