freshen is an interactive TUI for managing sibling Git repositories. Connect an optional GitHub user or organization to discover repositories and monitor GitHub Actions.
Contributing? See CONTRIBUTING.md for prerequisites, build/test commands, and the CI-critical
scripts/directory.
- Concurrent Parallel Syncing: Syncs 20+ repositories simultaneously in seconds using Go worker pools.
- Organization overview: Starts with repository, Actions and runner health at a glance, then opens dedicated searchable screens for each area.
- Concern queue: Ranks repositories with open PRs or issues and opens their existing detail view for review.
- Explicit repository sync: Startup loads metadata. Sync or clone only when requested; archived repositories are highlighted.
- Alias Mappings: Map GitHub repo names to custom local folder names with a repeatable
-alias local=remoteflag or analiaseslist in the config file..githubβgithubis built in. - GitHub Actions monitoring: Workflow runs, a separate job queue, completed-job and step counts, runner assignments, and a log tail for the selected job.
- Interactive Controls:
- Re-sync / retry individual repositories.
- Safely confirm deletion of archived repositories (
rm -rf).
- Non-Interactive Batch Mode: Run with
-yor--non-interactivefor silent CLI scripting.
Install via the official seankoji-com Homebrew tap:
brew install seankoji-com/tap/freshen(Or tap first: brew tap seankoji-com/tap && brew install freshen)
Install via the Windows Package Manager:
# Install from the manifest attached to a GitHub release
# (download SeanKoji.Freshen.yaml from the release page first).
# Releases are generated by the release workflow starting with the first tag
# cut after it was added; v0.1.1 and earlier have no such asset.
winget install --manifest SeanKoji.Freshen.yaml
# Or once indexed in winget-pkgs
winget install SeanKoji.FreshenPrebuilt release archives for macOS (ARM64 / Intel), Linux (ARM64 / x86_64), and Windows (ARM64 / x64) are published on GitHub Releases.
git clone https://github.com/seankoji-com/freshen.git
cd freshen
go build -o freshen .Launch the TUI interface:
./freshen| Key | Action |
|---|---|
0 / 1 / 2 / 3 / 4 |
Overview / Repositories / Actions / Runners / Concerns |
Tab / Shift+Tab |
Next / previous screen |
ββ or j/k |
Move within a list, or scroll open details |
Enter / β |
Open details; Actions opens run β jobs β steps and log tail |
Esc / β |
Back; clear a list filter when at the top level |
/ |
Filter the current list; Enter applies, Esc clears |
Home / End, PgUp / PgDn |
First/last item or page through the current view |
Space |
Contextual action menu |
r |
Refresh data, without syncing repositories |
v |
Toggle Actions workflow runs / job queue |
f |
Filter runs: Active / Needs attention / Recent |
[ / ] |
Repository detail tabs: Logs / Branches / Issues / PRs |
o / y |
Open GitHub / copy link or runner ID (local path without an owner) |
s / a |
Sync selected repository / confirm sync all |
b |
Switch selected repository between original and default branch |
p |
Confirm commit all changes, push, create PR and switch to default |
X |
Confirm force-removing worktrees and deleting non-default branches |
d |
Confirm deleting an archived local clone |
? |
Scrollable help |
q / Ctrl+C |
Quit (Ctrl+C works inside search and confirmations) |
Repository actions run in the background with busy and result feedback. Destructive confirmations retain the exact target across refreshes. Navigation never moves to another screen merely because you reach the end of a list.
Actions retains all job results. Bars count completed jobs or steps, including skipped/cancelled steps; they do not estimate remaining time. The recent view covers 30 runs per repository. Active runs are additionally queried when that window fills, and job lists are paginated. Missing job details and partial repository failures are labelled. Fleet access failures show observed assignments with unknown availability. The organisation poll starts at 20 seconds and slows with workspace size to budget API requests; the footer shows the interval. Selected running-job logs refresh with the runner tick. GitHub may provide only step status while logs are unavailable.
# Specify a workspace and GitHub user or organization
freshen -dir ~/repos -owner octocat
# Non-interactive sync; archived repositories are never deleted by default
freshen -y
# Keep the GitHub repo "my-wiki" in a local folder named "wiki"
# (local folder name first, GitHub repo name second; repeatable)
freshen -alias wiki=my-wiki -alias docs=product-docs
# Display version
freshen -vIn TUI mode nothing is printed to the terminal β stray writes corrupt the alternate screen β so diagnostics go to a file under the user cache dir: ~/Library/Caches/freshen/freshen.log on macOS, ~/.cache/freshen/freshen.log on Linux. Set FRESHEN_LOG_LEVEL to debug, info (default), warn, or error.
tail -f ~/Library/Caches/freshen/freshen.logBatch mode (-y) leaves logging on stderr.
On first interactive launch, freshen asks for a sibling-repository workspace and an optional GitHub owner. Configuration is stored as freshen/config.json in the platform config directory; it contains no credentials. To keep alias mappings without passing -alias every run, add an aliases list in the same local=remote form to your existing config.json (run freshen once first so setup creates it):
{
"workspace": "/Users/you/repos",
"owner": "octocat",
"concurrency": 4,
"aliases": ["wiki=my-wiki", "docs=product-docs"]
}Flags override config. A -alias replaces any config alias that uses the same local folder name or the same GitHub repo name, so each folder maps to exactly one repo. Then FRESHEN_OWNER (or legacy FRESHEN_ORG) can supply an owner.
Workspace-only mode requires git and never calls GitHub. GitHub features require an authenticated GitHub CLI (gh auth login) or GH_TOKEN. Use a token with access to the target repositories; organization runner visibility may require organization-admin or runner permissions.
d d deletes an archived repository and X force-removes secondary worktrees and non-default branches. Review the selected workspace carefully. Batch deletion requires --delete-archived.
Release binaries are published for macOS, Linux, and Windows with checksums.txt. Homebrew/Linuxbrew and winget manifests are generated from tagged releases; their upstream publication may require a maintainer submission. Verify checksums before installing binaries manually.
To publish a release, push a version tag such as v1.0.0. The release workflow
builds the supported OS and architecture combinations, uploads archives and
checksums to GitHub Releases, and updates the configured Homebrew tap when the
repository token has write access to that tap. Configure a dedicated
HOMEBREW_TAP_GITHUB_TOKEN repository secret with write access to
seankoji-com/homebrew-tap; the default GITHUB_TOKEN cannot write to that
separate repository. The Homebrew formula is written to
Formula/freshen.rb in the tap. The workflow also generates
SeanKoji.Freshen.yaml from the release's checksums.txt
(scripts/winget-manifest.sh) and attaches it to the release. Winget
publication is a separate upstream submission: validate that file with
winget validate, then open the corresponding pull request in
microsoft/winget-pkgs. To render one by hand for any release:
scripts/winget-manifest.sh vX.Y.Z checksums.txt SeanKoji.Freshen.yaml (the
checksums.txt from that release). CI runs goreleaser check and a snapshot build on every
pull request so release config errors surface before a tag.
- Language: Go 1.26+
- TUI Framework: Bubble Tea
- Styling & Widgets: Lip Gloss & Bubbles
- Integrations:
git& GitHub CLI (gh)
Interested in contributing? See CONTRIBUTING.md for details on setting up your development environment, build & test workflow, commit conventions, and debugging tips.