Close out the plan with the remaining polish items and a full README.
Shell completions (cmd/gitflow):
- New `completion [bash|zsh|fish|powershell]` command backed by cobra's
generators, wired into the root command
Desktop notifications (internal/notify):
- Send() dispatches to notify-send (Linux) with an osascript fallback
(macOS); Windows is a documented no-op for now; missing notifiers are
silent, never errors
- watch --notify sends a notification listing repositories whose state
changed since the previous frame
Color themes (internal/presenter):
- ThemeMode (dark/light) with ParseTheme; light uses bright ANSI variants
(90-97) that stay legible on light backgrounds; threaded through the
table, compact, and suggestions renderers; new --theme flag validated
and dumped by config
Custom rules (internal/rules):
- Rule{name, field (ahead|behind|stash|changes), op (==,!=,<,<=,>,>=),
value, label} with upfront validation in both Validate and Eval
- Config gains a `rules:` section (yaml/env only, no flag), validated at
load; matches render as a "FLAGS (custom rules)" section via a new
presenter.Flags renderer, shown in scan and watch frames
Docs:
- readme.md fully rewritten: features, install, usage, examples, flag
table, status classes, configuration reference, AI agent behavior and
--ai-execute guardrails, development layout, CI, and future work
- implementation.md gains an Implementation Progress section recording
every phase branch and the deviations from the original plan
Multi-platform:
- Verified cross-compilation for windows/amd64 and darwin/arm64; the
notify package is split behind build tags
Testing:
- rules: validation, operator semantics, Eval ordering, invalid-rule
errors
- presenter: ParseTheme, light-theme bright codes (and absence of
dark-theme codes), Flags rendering (empty = silent, matches render)
- config: rules loading from file, invalid-rule rejection, bad theme and
bad provider rejection
- notify: no-op behaviour when no notifier is installed (skipped when one
is, to avoid firing real notifications)
Verified: go build, go vet, go test -race (10 packages), gofmt clean,
windows/darwin cross-compile, completion generation, rules + light theme
smoke test, watch --notify graceful shutdown (exit 0, no orphans).
11 KiB
Git Flow — Detailed Development Plan
Overview
Git Flow is a Go CLI tool that discovers Git repositories under a user-specified parent directory, periodically scans their status, and presents findings with AI-driven suggestions for next actions (e.g., "commit pending changes", "push branch X", "pull latest from main").
Phase 0: Project Scaffolding & Tooling
| Task | Details | Deliverable |
|---|---|---|
| Module init | go mod init github.com/<user>/gitflow |
go.mod |
| Directory layout | Flat-to-modular structure appropriate for a CLI (see layout below) | Dir tree |
| Tooling | Add golangci-lint config, Makefile, .gitignore |
Dev tooling |
| CI skeleton | GitHub Actions: lint + test on push | .github/workflows/ci.yml |
Recommended Directory Layout
gitflow/
├── cmd/gitflow/ # main entry point
├── internal/
│ ├── scanner/ # repo discovery + git status scanning
│ ├── presenter/ # output formatting (table, JSON, TUI)
│ ├── scheduler/ # periodic scan loop
│ ├── ai/ # AI agent integration
│ ├── config/ # CLI flags, env vars, config file parsing
│ └── git/ # thin wrappers around git commands
├── pkg/ # shared types (RepoInfo, Status, etc.)
├── go.mod / go.sum
├── Makefile
├── .golangci.yml
└── readme.md
Phase 1: Core — Repo Discovery & Status Scanning
This is the foundational layer. Everything else depends on it.
1.1 Define the Domain Types (pkg/types.go or internal/scanner/types.go)
type RepoStatus int
const (
StatusUnknown RepoStatus = iota
StatusClean
StatusModified
StatusAhead
StatusBehind
StatusDiverged
StatusDetached
StatusBare
StatusError
)
type RepoInfo struct {
Path string
RemoteURL string
Branch string
Status RepoStatus
ModifiedFiles []string
StagedFiles []string
UntrackedFiles []string
AheadBy int
BehindBy int
StashCount int
LastFetch time.Time
Error string
}
type ScanResult struct {
ScannedAt time.Time
ParentDir string
Repos []RepoInfo
TotalCount int
ErrorCount int
}
1.2 Repo Discovery (internal/scanner/discover.go)
- Walk the directory tree starting from the parent directory
- Detect
.gitdirectories (including bare repos, submodules, worktrees) - Respect
.gitignore-style exclusion patterns via a--excludeflag - Respect depth limits via a
--depth/--max-depthflag - Use
filepath.WalkDirfor efficient traversal (noos.FileInfoallocations)
Pattern: Single-responsibility — the discoverer only finds repos; status scanning is a separate step.
1.3 Status Scanner (internal/scanner/status.go)
- For each discovered repo, run
gitporcelain commands:git status --porcelain -bfor branch, ahead/behind, modified/staged/untrackedgit remote -vfor remote URLgit stash listfor stash count
- Parse output into
RepoInfo - Resilience patterns from Go skill:
- Timeout each
gitcommand (e.g., 10s viacontext.WithTimeout) - Handle repos with errors gracefully — mark as
StatusError, don't crash - Run scans concurrently with a bounded worker pool (
errgroup+ semaphore)
- Timeout each
1.4 Git Command Wrapper (internal/git/)
- Thin wrapper:
func Status(ctx context.Context, repoPath string) (RepoInfo, error) - Uses
os/execwith context for cancellation/timeout - No external git library dependency —
os/execis sufficient for porcelain commands
Phase 2: CLI & Configuration
2.1 CLI Framework
Use Cobra + Viper (standard Go CLI stack):
| Flag | Type | Default | Description |
|---|---|---|---|
--dir / -d |
string | . (cwd) |
Parent directory to scan |
--interval / -i |
duration | 0 (run once) |
Rescan interval (e.g., 5m, 30s) |
--format / -f |
string | table |
Output format: table, json, compact |
--exclude |
[]string | [] |
Glob patterns to exclude |
--max-depth |
int | 0 (unlimited) |
Max traversal depth |
--ai |
bool | false |
Enable AI suggestions |
--ai-provider |
string | openai |
AI backend |
--ai-model |
string | gpt-4o |
AI model |
--watch / -w |
bool | false |
Watch mode (alias for interval) |
2.2 Configuration File
Support ~/.gitflow.yaml for defaults:
ai:
provider: openai
api_key_env: OPENAI_API_KEY
model: gpt-4o
defaults:
interval: 5m
format: table
exclude:
- "node_modules"
- "vendor"
2.3 Commands
gitflow scan # one-shot scan
gitflow watch # periodic scan (uses --interval)
gitflow config # show/edit config
gitflow version # version info
Phase 3: Presentation Layer
3.1 Table Output (default)
Rich terminal table using bubbletea / lipgloss (or simpler: tablewriter):
REPOSITORY BRANCH STATUS AHEAD/BEHIND CHANGES
~/projects/api main ✓ clean 0 / 0 -
~/projects/web feat/login ✗ modified 3 / 0 2M, 1U
~/projects/lib main ⚠ behind 0 / 5 -
~/projects/legacy (detached) ⚠ detached - -
4 repos scanned | 1 clean | 2 need attention | 2 errors
3.2 JSON Output
For scripting / piping:
{
"scanned_at": "2026-01-01T12:00:00Z",
"parent_dir": "/home/user/projects",
"repos": [...],
"summary": {"total": 4, "clean": 1, "attention": 2, "errors": 1}
}
3.3 Compact Output
One line per repo with color-coded status symbols.
Phase 4: Periodic Scanner (Scheduler)
4.1 Watch Mode (internal/scheduler/scheduler.go)
- Runs scan on a
time.Tickerat the configured interval - Clears terminal and re-renders (or uses TUI refresh)
- Handles SIGINT/SIGTERM for graceful shutdown
- Shows time until next scan in footer
Pattern: Use signal.NotifyContext for graceful shutdown. Defer cleanup immediately after resource acquisition.
4.2 Change Detection
- Between scans, compare current vs previous
ScanResult - Highlight repos that changed state
- Optionally trigger desktop notifications (via
beeepornotify-send)
Phase 5: AI Agent Integration
5.1 AI Module (internal/ai/)
Interface-first design (for testability and provider flexibility):
type Provider interface {
Suggest(ctx context.Context, repos []RepoInfo) ([]Suggestion, error)
}
type Suggestion struct {
RepoPath string
Action string // "commit", "push", "pull", "stash", "pr", "cleanup"
Message string // Human-readable suggestion
Command string // Suggested git command to run
Priority int // 0=low, 1=medium, 2=high
}
5.2 Providers
- OpenAI (default): GPT-4o with structured output (JSON Schema) for reliable parsing
- Ollama (local/offline): Support for local models
- Anthropic Claude: Alternative cloud provider
5.3 Prompt Design
Construct a prompt that includes:
- A summary table of all repos and their statuses
- The top 3-5 repos needing attention
- Instructions to output structured JSON with specific action types
5.4 AI Output Display
- Show suggestions in a separate section below the status table
- Color-coded by priority
- Optional:
--ai-executeflag to auto-run suggested commands (with confirmation)
Phase 6: Polish & Advanced Features
| Feature | Description |
|---|---|
| Color themes | Light/dark terminal themes via lipgloss |
| TUI mode | Full interactive TUI with bubbletea — navigate repos, expand details, trigger AI suggestions |
| Custom actions | User-defined rules: "if behind > 10 commits, mark as critical" |
| Webhook/notifications | Send alerts to Slack/Discord when repos need attention |
| Multi-platform | Test on Linux, macOS, Windows (WSL) |
| Completion | Shell completions for bash, zsh, fish via Cobra |
Technology Choices Summary
| Concern | Choice | Rationale |
|---|---|---|
| CLI framework | Cobra + Viper | Industry standard, completions, env binding |
| Git interaction | os/exec (porcelain) |
No dependency needed; porcelain output is stable |
| TUI (optional) | Bubble Tea + Lip Gloss | Best Go TUI ecosystem |
| AI integration | HTTP client + JSON Schema | Provider-agnostic, no heavy SDK required |
| Concurrency | errgroup + semaphore |
Bounded parallelism, error propagation |
| Testing | testing + testify |
Standard + assertions |
| Linting | golangci-lint |
Comprehensive Go linting |
Milestone Schedule
| Milestone | Scope | Estimated Effort |
|---|---|---|
| M1 — Skeleton | Phase 0: module, layout, Makefile, CI | 0.5 day |
| M2 — Discovery | Phase 1: repo walker + git status parser | 1–2 days |
| M3 — CLI | Phase 2: Cobra commands, flags, config | 1 day |
| M4 — Display | Phase 3: table + JSON + compact output | 1 day |
| M5 — Watch | Phase 4: scheduler, auto-refresh, signals | 1 day |
| M6 — AI | Phase 5: provider interface, OpenAI, suggestions | 1–2 days |
| M7 — Polish | Phase 6: TUI, themes, completions, docs | 2–3 days |
Total estimated effort: ~7–10 days for a solid v1.0
Implementation Progress
All phases from this plan are implemented and merged into main (branch
per phase, merged with --no-ff, no remote pushes).
| Phase | Branch | Status |
|---|---|---|
| 0 — Scaffolding | feat/phase-0-scaffolding |
✅ done |
| 1 — Discovery & scanning | feat/phase-1-discovery-scanning |
✅ done |
| 2 — CLI & configuration | feat/phase-2-cli-config |
✅ done |
| 3 — Presentation | feat/phase-3-presentation |
✅ done |
| 4 — Scheduler / watch | feat/phase-4-scheduler |
✅ done |
| 5 — AI agent | feat/phase-5-ai |
✅ done |
| 6 — Polish | feat/phase-6-polish |
✅ done |
Deviations from the plan
LastFetchfield dropped (phase 1): the only reliable source is a reflog of the remote-tracking ref, which does not exist on fresh clones; noted as future work instead.- Full bubbletea TUI deferred (phase 6): the plan listed it as optional; watch mode + completions + themes + notifications were implemented instead.
- Webhooks deferred (phase 6): desktop notifications cover the alerting case; Slack/Discord noted as future work.
- AI defaults:
ai-modeldefaults togpt-4o(plan) with provider-specific fallbacks (ollama →llama3.2, anthropic →claude-3-5-haiku-latest);--ai-executeimplemented with an allowlist + per-command confirmation instead of a bare auto-run. - testify was not added: stdlib
testingcovers all suites, keeping the dependency tree minimal.