repon 0.30.5

A terminal UI for the outer loop: seeing many git repos at once and acting on many in one gesture
# This terminal draws braille, ∅ and the rounded borders fine; keep the full set.
theme = "default"
glyphs = "full"

# Worktrees are rows too; Submodules stay hidden.
show_worktrees = true
show_submodules = false

# advance_on_toggle = false  # true also moves the cursor down after space checks a row

# notice_timeout = "3s"      # "0s" turns the timer off, not Notices

# One declared action runs after a refresh you asked for: `r` and `R`, never the
# background sweep.
on_refresh = "tidy"

# The same shape either side of the built-in sync. Both default to nothing.
# before_sync = "tidy"
# after_sync = "tidy"

# The lifecycle: refresh looks at git state alone, always on; fetch reaches the
# network to keep that state current, off by default; auto_update rides fetch's
# cycle to fast-forward what it finds behind. The built-in `sync` action does
# that same fast-forward on demand, on the same eligibility rule, whenever
# asked rather than on fetch's own cycle; `sync` is also the name of the Cell
# comparing an Entity against its upstream, a different thing from the action.
# Full picture:
# https://github.com/paulchiu/repon/blob/main/docs/spec/config.md#refresh-fetch-and-auto-update

[refresh]
poll_interval = "2s"       # "0s" turns the sweep off
status_stale_after = "5m"
on_focus = true

[fetch]
enabled = true
interval = "5m"
concurrency = 4

[auto_update]
enabled = true             # fast-forward only, rides the fetch cycle

# Everything, both roots. First declared, so this is the default Set.
[[set]]
name = "dev"
roots = ["~/dev", "~/dev-misc"]

# One client, minus the graveyard. Globs are case-sensitive. Its own on_refresh
# names tidy explicitly, so a later edit to the top-level default cannot retarget
# this Set's refresh key by accident.
[[set]]
name = "work"
roots = ["~/dev"]
include = ["**/acme/**"]
exclude = ["**/archive/**", "**/node_modules/**"]
on_refresh = "tidy"
# A Set's own hook wins over the top-level one for the rows in this Set.
after_sync = "tidy"
# before_sync = "tidy"

# origin/HEAD on this one still says master; pin it.
[[repo]]
path = "~/dev/legacy-api"
default_branch = "main"

# A vendored mirror. List it, never touch it.
[[repo]]
path = "~/dev/vendor-mirror"
exclude = true

[[launcher]]
name = "lazygit"
args = ["lazygit"]

[[launcher]]
name = "tuicr"
args = ["tuicr"]

# VISUAL, then EDITOR, then vi. "code --wait" splits into two argv elements.
[[launcher]]
name = "editor"
from_env = "EDITOR"
# env = {}                  # merged over the guaranteed set
# disabled = false          # drops a shipped default

# The pipe is why this one opts into the shell.
[[launcher]]
name = "log"
args = ["git log --oneline -20 | less"]
shell = true
# interactive = false        # $SHELL -ic instead of -c: sources your rc file, needs shell = true

# tmux returns the instant the pane exists, so Repon keeps its screen rather than
# tearing it down and reclaiming it for nothing.
[[launcher]]
name = "pane"
args = ['tmux split-window -c "$REPON_REPO_PATH" lazygit']
shell = true
takes_terminal = false

# Step two runs only if step one exited zero.
[[action]]
name = "reinstall"
description = "Reinstall dependencies from scratch"
concurrency = 4
when = "kind:repo"          # skip Worktrees and Submodules: they share node_modules with the Repo
# confirm = true            # ask before fanning out

[[action.steps]]
args = ["rm", "-rf", "node_modules"]
# shell = false              # runs through $SHELL -c
                              # without it, $VAR and $(cmd) above stay literal, not expanded
# interactive = false        # $SHELL -ic instead of -c: sources your rc file, needs shell = true
# env = {}                   # merged over the guaranteed environment contract

[[action.steps]]
args = ["pnpm", "install"]

[[action]]
name = "tidy"
description = "Whatever each Repo needs once its state is fresh"
concurrency = 4

[[action.steps]]
args = ["tidy-repo"]

# Only what changes. Everything else keeps the default map.
[keys.global]
refresh_all = "ctrl-l"     # a rebind moves the binding: plain r stops refreshing

[keys.list]
anchor_range = ""          # unbind it entirely