e397da2733
- add the tui command using Bubble Tea and Lip Gloss - preselect eligible repositories and disable selection for blocked repositories - add keyboard controls for navigation, selection, refresh, sync, and cancellation - require confirmation before sync and show the branch-deletion warning - show dirty paths, block reasons, and hub output for the focused repository - add TUI model tests and set the embedded version to 0.2.0
80 lines
3.8 KiB
Markdown
80 lines
3.8 KiB
Markdown
# Stack Sync
|
|
|
|
`stack-sync` safely runs [`hub sync`](https://hub.github.com/hub-sync.1.html) across every Git repository in a workspace. It is designed for directory trees such as JezzWTF where the root may not be a repository and a parent repository may contain deliberately untracked, nested repositories.
|
|
|
|
It provides both a full-screen [Bubble Tea](https://github.com/charmbracelet/bubbletea) control deck for interactive work and a conventional CLI/JSON interface for SSH sessions and automation. Both interfaces use the same discovery and safety engine.
|
|
|
|
## Safety model
|
|
|
|
Before a repository is eligible, Stack Sync verifies that it:
|
|
|
|
- is on a branch (not a detached `HEAD`);
|
|
- has at least one remote;
|
|
- has no merge, rebase, cherry-pick, revert, or bisect in progress;
|
|
- has no modified, staged, deleted, conflicted, or untracked files.
|
|
|
|
Untracked paths that are themselves discovered nested Git repositories are excluded from the parent repository's dirty check. All other untracked files still block it.
|
|
|
|
Stack Sync never runs `git stash`, `git reset`, `git clean`, `git commit`, or any other command that saves or discards work. A repository is checked again immediately before `hub sync` to reduce the chance of a change slipping in between the plan and apply phases. Blocked repositories are skipped; use `--strict` to abort the whole run if even one is blocked.
|
|
|
|
Stack Sync intentionally preserves `hub sync` semantics. That means `hub` may delete a local branch when its upstream branch has been deleted and it considers the local branch merged. It warns instead when it finds unpushed or apparently unmerged commits. The interactive confirmation calls this out; review `hub help sync` before using `--yes` in automation.
|
|
|
|
## Build and install
|
|
|
|
Requires Go 1.24 or newer, Git, and [hub](https://hub.github.com/).
|
|
|
|
```bash
|
|
cd stack-sync
|
|
go test ./...
|
|
go build -o stack-sync .
|
|
install -Dm755 stack-sync ~/.local/bin/stack-sync
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Interactive TUI
|
|
|
|
Launch the control deck for the workspace:
|
|
|
|
```bash
|
|
stack-sync tui --root ~/Coding/jwtf
|
|
```
|
|
|
|
Every eligible repository starts selected. Move with the arrow keys or `j`/`k`, toggle the focused repository with Space, select all with `a`, clear the selection with `n`, and refresh with `r`. Press `s` or Enter to review the destructive-branch warning, then `y` to begin. Blocked repositories cannot be selected and show their first dirty paths in the detail panel. After a run, focusing a repository shows its latest `hub` output.
|
|
|
|
### CLI and automation
|
|
|
|
Scan the current workspace. This is read-only and is the default command:
|
|
|
|
```bash
|
|
stack-sync scan --root ~/Coding/jwtf
|
|
# equivalent:
|
|
stack-sync --root ~/Coding/jwtf
|
|
```
|
|
|
|
Review the same plan, confirm it, and sync every eligible repository:
|
|
|
|
```bash
|
|
stack-sync sync --root ~/Coding/jwtf
|
|
```
|
|
|
|
For automation, suppress the prompt and optionally require the entire workspace to be clean:
|
|
|
|
```bash
|
|
stack-sync sync --root ~/Coding/jwtf --yes --strict
|
|
```
|
|
|
|
Useful options:
|
|
|
|
```text
|
|
--jobs 4 maximum concurrent inspections or syncs
|
|
--timeout 5m per-repository hub sync timeout
|
|
--exclude temp skip a directory name anywhere in the tree
|
|
--exclude Org/old skip a root-relative path
|
|
--json emit structured output
|
|
```
|
|
|
|
Dependency caches, build outputs, and tool-managed directories such as `node_modules`, `target`, `.claude`, and `.codex` are skipped during discovery by default. These exclusions only affect repository discovery; they never make real changes inside a discovered repository disappear from its dirty-worktree check.
|
|
|
|
Exit codes are `0` for a successful scan or sync (planned dirty repositories may be safely skipped), `1` for an operational/sync failure, `2` for invalid or unconfirmed non-interactive use, and `3` when strict mode refuses the plan or a previously eligible repository fails its immediate pre-sync safety check.
|