gitFlow/buildAndRun.md

14 KiB

gitflow — Build & Run Guide

Prerequisites

Requirement Minimum Check with
Go toolchain 1.24 go version
Git any recent git --version
make (optional) make --version
golangci-lint (optional) any recent golangci-lint --version

Linux, macOS, and Windows (WSL / MSYS2) are supported. The binary compiles for all three platforms (ARM64 on macOS verified).

Quick start

# Clone
git clone https://gitea.oblak.solutions/dimitar/gitFlow.git
cd gitFlow

# Build (either method)
make build                  # produces ./gitflow
# or
go build -o gitflow ./cmd/gitflow

# Run
./gitflow version           # → "gitflow dev"
./gitflow scan              # scans $PWD, asks for directory if stdin is a tty
./gitflow scan -d ~/projects

Make targets

make build         # compile the binary, injects VERSION via ldflags
make test          # run the full test suite (go test ./...)
make fmt           # format all Go sources (gofmt)
make vet           # run go vet over all packages
make lint          # run golangci-lint (needs it on PATH)
make install       # install into $GOPATH/bin (or $GOBIN)
make clean         # remove the binary and coverage output

Stamped version (optional):

VERSION=v2.0.1 make build
./gitflow version  # → "gitflow v2.0.1"

Commands

Command Purpose
scan One-shot scan of repos under --dir, render and exit
watch Rescan every --interval, detect changes, notify, fire webhooks
tui Interactive terminal UI (bubbletea) with navigation, detail pane, AI panel
config Print the resolved configuration (flags + env + file merged)
completion Emit shell completions for bash, zsh, fish, or PowerShell
version Print version and exit

Every command accepts the same flag set. Use gitflow <cmd> --help for the full list.

scan — single pass

gitflow scan                         # prompt for dir, table output
gitflow scan -d ~/projects           # explicit dir
gitflow scan -d ~/projects -f json   # JSON to stdout, no human-facing sections
gitflow scan -d ~ --exclude node_modules --exclude vendor
gitflow scan -d ~/projects --max-depth 2 --workers 16

watch — periodic scan ---

gitflow watch -d ~/projects -i 30s              # scan every 30 seconds
gitflow watch -d ~/projects -i 5m --notify      # also fire desktop notifications
gitflow watch -d ~/projects -i 1m --theme=light --color=always

Webhooks fire automatically when a webhooks: section exists in your config file (no flag needed — they are config-only, like custom rules).

tui — interactive terminal UI

gitflow tui -d ~/projects                       # one-shot scan, browse with j/k
gitflow tui -d ~/projects -i 30s                # periodic scan, countdown in bar
gitflow tui -d ~/projects --ai --ai-provider ollama

TUI keybindings:

↑/↓  or  j/k       navigate repository list
g / Home            jump to top
G / End             jump to bottom
Enter / Space       toggle detail pane for selected repo
r                   trigger immediate rescan
a                   toggle AI suggestion panel (requires --ai)
?                   toggle help overlay
q / Ctrl-C          quit

config — show effective configuration

gitflow config                        # defaults
gitflow config -d /tmp -f compact     # with flag overrides
GITFLOW_DIR=/tmp gitflow config       # with env overrides

completion — shell integration

# bash
eval "$(gitflow completion bash)"

# zsh
gitflow completion zsh > ~/.zsh/completion/_gitflow

# fish
gitflow completion fish > ~/.config/fish/completions/gitflow.fish

# powershell
gitflow completion powershell > gitflow.ps1

Configuration

Settings resolve with this precedence (highest first):

  1. CLI flags--dir, --format, etc.
  2. Environment variablesGITFLOW_ prefix, dots replaced by underscores: GITFLOW_DIR, GITFLOW_FORMAT, GITFLOW_AI_PROVIDER, …
  3. Config file~/.gitflow.yaml (or ./.gitflow.yaml); override the path with GITFLOW_CONFIG=/some/path.yaml
  4. Built-in defaults. directory, table format, auto color, dark theme, 8 workers, AI disabled, etc.

Complete config file reference

# ~/.gitflow.yaml
dir: ~/projects
interval: 5m
format: table          # table | json | compact
color: auto            # auto | always | never
theme: dark            # dark | light
notify: true           # desktop notifications (linux notify-send, macOS osascript)
max_depth: 3           # 0 = unlimited
workers: 8
exclude:               # glob patterns matched against base name and full path
  - node_modules
  - vendor
  - ".cache"

# AI agent (requires --ai flag or enabled: true)
ai:
  enabled: false
  provider: openai        # openai | ollama | anthropic
  model: gpt-4o           # empty → provider default (ollama: llama3.2, anthropic: claude-3-5-haiku-latest)
  api_key_env: OPENAI_API_KEY
  base_url: ""            # override provider endpoint; empty → vendor default
  execute: false          # run confirmed AI commands (experimental, allowlist-guarded)

# Custom threshold rules
rules:
  - name: stale-branch
    field: behind         # ahead | behind | stash | changes
    op: ">="              # == | != | < | <= | > | >=
    value: 10
    label: stale
  - name: dirty-workspace
    field: changes
    op: ">="
    value: 1
    label: dirty

# Webhooks (config-file-only, no CLI flags)
webhooks:
  - name: team-slack
    type: slack           # slack | discord | generic
    url: https://hooks.slack.com/services/T00/B00/TOKEN
    on_change_only: true  # skip when nothing changed
    min_priority: 0       # 0 = fire on any change
    rate_limit: 5m        # minimum interval between fires
    timeout: 10s          # HTTP timeout per attempt
    retry:
      max_attempts: 3     # max 5
      backoff: 2s         # exponential backoff start

  - name: ops-discord
    type: discord
    url: https://discord.com/api/webhooks/...
    send_all: false       # when true, include every repo, not just changed

  - name: internal-dashboard
    type: generic
    url: https://dashboard.internal/api/gitflow
    headers:
      Authorization: Bearer ${DASHBOARD_TOKEN}
      X-Source: gitflow

Environment variable mapping

Config key Env var
dir GITFLOW_DIR
interval GITFLOW_INTERVAL
format GITFLOW_FORMAT
color GITFLOW_COLOR
theme GITFLOW_THEME
notify GITFLOW_NOTIFY
max_depth GITFLOW_MAX_DEPTH
workers GITFLOW_WORKERS
exclude GITFLOW_EXCLUDE (comma-separated)
ai.enabled GITFLOW_AI_ENABLED
ai.provider GITFLOW_AI_PROVIDER
ai.model GITFLOW_AI_MODEL
ai.api_key_env GITFLOW_AI_API_KEY_ENV
ai.base_url GITFLOW_AI_BASE_URL
ai.execute GITFLOW_AI_EXECUTE

Output formats

Table (default)

REPOSITORY      BRANCH  STATUS    AHEAD/BEHIND  CHANGES  STASH
~/projects/api  main    clean     -              -        -
~/projects/web  feat/x  modified  3/0           2M 1U    -
~/projects/lib  main    behind    0/5           -        2

5 repos | 2 clean | 3 need attention | 0 errors

Colorised per status class (--color=auto respected, NO_COLOR honoured). Path prefix $HOME collapsed to ~.

JSON

{
  "scanned_at": "2026-08-02T10:00:00+02:00",
  "parent_dir": "/home/user/projects",
  "repos": [
    {
      "path": "/home/user/projects/api",
      "name": "api",
      "branch": "main",
      "status": "clean"
    }
  ],
  "summary": {
    "total": 5,
    "clean": 2,
    "attention": 3,
    "errored": 0,
    "staged": 0,
    "modified": 2,
    "untracked": 1
  }
}

Status fields marshal as string labels ("clean", "modified", …) and unmarshal back from both strings and integers.

Compact

✓ ~/projects/api (main)
✗ ~/projects/web (feat/x) +3/-0 2 change(s)
↓ ~/projects/lib (main) +0/-5

Status symbols: ✓ ✗ ↑ ↓ ⇄ ◉ ▢ !.

AI agent

Enable with --ai (or ai.enabled: true in config):

# OpenAI (requires OPENAI_API_KEY exported or ai.api_key_env set)
gitflow scan -d ~/projects --ai

# Local Ollama
gitflow scan -d ~/projects --ai --ai-provider ollama --ai-model llama3.2

# Anthropic
gitflow scan -d ~/projects --ai --ai-provider anthropic --ai-model claude-3-5-haiku-latest

Suggestions render below the scan table, colour-coded by priority:

AI SUGGESTIONS
REPOSITORY      ACTION   PRIORITY  MESSAGE                    COMMAND
~/projects/web  commit   high      commit the new file        git add -A && git commit -m wip
~/projects/lib  pull     medium    pull 5 commits from origin git pull

In JSON mode AI is skipped (machine-readable streams stay clean). In watch mode AI is queried only on the first frame and when something changed.

--ai-execute (experimental)

Runs suggested commands after explicit per-command y/N confirmation, only for actions on an allowlist (commit, push, pull, stash, checkout). LLM output can never run arbitrary shell commands.

Webhooks

Webhooks fire in watch mode when webhooks: is present in the config file. They run in a background goroutine and never block the scan interval.

Each webhook has independent rate limiting and retry with exponential backoff. Transient errors (5xx, timeouts) are retried; 4xx client errors fail immediately.

Slack Block Kit payload:

  • Header: "gitflow: scan results"
  • Section: summary line with repo counts
  • Divider + changed-repo list (when changes exist)
  • Context footer: timestamp + "gitflow"

Discord embed payload:

  • Sidebar colour: green (all clean), yellow (attention), red (errors)
  • Title: "gitflow scan"
  • Markdown body with summary + changed repos
  • Footer and timestamp

Generic payload:

  • Raw JSON POST of the webhook.Payload struct (timestamp, parent_dir, summary, changed, all) to any URL with custom headers.

Test suite

make test              # all packages, no race detection
go test -race ./...    # with data-race detector (13 packages)
go test -count=1 -race ./internal/ai ./internal/webhook   # specific packages

Coverage (latest run):

Package Coverage
internal/ai 84.9%
internal/app 76.9%
internal/config 90.9%
internal/git 79.6%
internal/httpclient 89.1%
internal/presenter 86.6%
internal/rules 83.3%
internal/scanner 88.2%
internal/scheduler 88.9%
internal/webhook 91.7%
internal/tui 89.4%
pkg/status 91.1%

Project layout

gitflow/
├── cmd/gitflow/            CLI commands (cobra)
│   ├── main.go             entry point
│   ├── root.go             root command + version + completion
│   ├── scan.go             gitflow scan
│   ├── watch.go            gitflow watch
│   ├── tui.go              gitflow tui
│   └── prompt.go           TTY helpers (dir prompt, y/N confirmation)
├── internal/
│   ├── ai/                 AI providers (OpenAI, Ollama, Anthropic) + prompt
│   ├── app/                orchestration: discovery → scan → result
│   ├── config/             flags, env, config-file resolution (viper)
│   ├── git/                porcelain v2 git wrapper (executor pattern)
│   ├── httpclient/         shared JSON HTTP client (timeout, bounded reads)
│   ├── notify/             desktop notifications (notify-send / osascript)
│   ├── presenter/          table / json / compact output + colors + themes
│   ├── rules/              user-defined threshold rules
│   ├── scanner/            repository discovery + concurrent status scanning
│   ├── scheduler/          interval loop with graceful shutdown
│   ├── tui/                interactive terminal UI (bubbletea + lipgloss)
│   ├── version/            ldflags-injectable version
│   └── webhook/            Slack, Discord, Generic webhook senders + dispatcher
├── pkg/status/             shared domain model (RepoInfo, RepoStatus, ScanResult)
├── go.mod / go.sum
├── Makefile
├── .golangci.yml
├── .github/workflows/ci.yml
├── readme.md               user-facing README
├── implementation.md       original development plan + progress
├── tui.md                  TUI & webhooks plan + milestone status
└── buildAndRun.md          this file

CI

GitHub Actions workflow (.github/workflows/ci.yml):

jobs:
  test (matrix: go 1.24, 1.26)
    - go build ./...
    - go vet ./...
    - go test -race ./...
  lint
    - golangci-lint

No remote pushes were made during development — branches were committed and merged locally with --no-ff.

Troubleshooting

"not a git repository" when scanning a directory that IS a repo

The repo's .git directory may be missing or the path might be a bare .git file pointing at a non-existent gitdir. Check git status manually in that directory.

"no repositories found"

The directory contains no .git entries. If you expected repos deeper in the tree, make sure --max-depth isn't set too low and no --exclude pattern shadows the subtree.

"ai: OPENAI_API_KEY is not set"

Export the key (or the env var name in ai.api_key_env) before running:

export OPENAI_API_KEY=sk-...
gitflow scan --ai

TUI doesn't launch / exits immediately

The TUI requires a terminal that supports the alternate screen buffer. If you are piping or redirecting output, use scan or watch instead.

Webhook not firing

  1. Check gitflow config shows the webhooks: section.
  2. Webhooks only fire in watch mode, not in scan.
  3. If on_change_only: true, the webhook skips when nothing changed between frames.
  4. If rate_limit is set, the webhook won't fire until the cooldown elapses.

Shell completion "command not found" after eval

Make sure gitflow is on your PATH (go install into $GOBIN):

go install ./cmd/gitflow
# Or
sudo cp gitflow /usr/local/bin/

Cross-compilation

GOOS=linux   GOARCH=amd64 go build -o gitflow-linux   ./cmd/gitflow
GOOS=darwin  GOARCH=arm64 go build -o gitflow-darwin  ./cmd/gitflow
GOOS=windows GOARCH=amd64 go build -o gitflow.exe     ./cmd/gitflow