README
¶
worktree - Show workspace details

This is a tool for developers that:
- Use
gitworkspaces - Use
gomodules or go workspaces - Use
gh issuesfor issue tracking - Need insight to their workspaces
The tool provides information and overview of the workspace state.
To install the tool:
go install github.com/titpetric/tools/worktree@main
Run worktree anywhere in your source workspace. It uses the nearest current or parent directory containing go.work, go.mod, or .git as the scan root. If no parent contains one of those markers, it recursively scans the current directory. Go modules and Git repositories are both included; when they share a directory they appear as one row. An optional path argument filters the output to projects matching that path:
worktree . # show only the module in the current folder
worktree ./tools # show all modules under the tools folder
worktree /abs/path # show modules matching an absolute path
By default the scan honours .gitignore files. An ignored folder is not descended into, so Git repositories and Go modules inside it are skipped; this keeps vendored checkouts and build output out of the listing. Only .gitignore files are read, not .git/info/exclude or the global excludes file, and a pattern applies even to paths that the repository tracks. Set enable_gitignore: false in the configuration to turn this off; see Configuration.
Two commands print the git commands for tagging a new release of the git repository in the current directory. They read the existing tags, detect the latest semver release, ignoring prereleases and tags that aren't semantic versions, and increment it:
worktree patch # v1.2.3 -> git tag v1.2.4
worktree minor # v1.2.3 -> git tag v1.3.0
The output is written to stdout so it can be reviewed and then piped into a shell:
worktree patch | sh -x
The v prefix of the latest tag is preserved. If the repository has no release tags yet, the version starts at v0.0.0, so patch proposes v0.0.1 and minor proposes v0.1.0, with a shell comment noting it.
Several flags invoke tool functionality:
-vgives a detailed verbose view with extra data; with-u, the update status also lists eachgo getandgo mod tidycommand that ran and marks successful commands with a green check,-uupdates the dependencies of each selected Go module that are known to be stale, meaning the workspace modules it requires at a version below their latest tag, withgo get <module>@<tag>, and then runsgo mod tidy. Dependencies outside the workspace and workspace modules already at their latest tag are left alone; a module with nothing stale is reported asAlready up to date.without running the go tool. It displays each module's path, module name, and the resultinggo.modchanges (dep v1.0.0 → v1.1.0,+ dep,- dep, orAlready up to date.). Results print line by line as each module finishes, so progress is visible while the remaining modules are still updating; the path and module name of the module being worked on appear before its results. Version changes to an existing requirement are orange, new requirements green, dropped ones grey, and failing commands are reported in red. Useworktree -u ./...to update every Go module under the workspace root,-Uupdates every dependency of each selected Go module withgo get -u ./..., including ones outside the workspace, before applying the workspace tag updates andgo mod tidythat-uperforms. It implies-u,--go=<version>sets thegodirective of everygo.modandgo.workin the workspace to that version and then performs the same update as-u. The version is given as1.27,1.27.1orgo1.27. Atoolchaindirective older than the new version is dropped, since it would leave the file invalid;go getandgo mod tidyadd a newer one back when they need it. Changedgo.workfiles are reported before the update table, each module's go directive change (go 1.25 → 1.27) appears in its update status. A module whosego.modalready declares the version is reported asAlready up to date.and skipped without running the go tool, so a repeated run over an updated workspace returns immediately. Combine it with-uto update the stale dependencies of every module regardless of its go directive,--pullpulls new changes for every Git repository in the workspace and displays each repository's path, first remote, branch, andgit pulloutput as a table,-toutputs a dependency matrix, with a green▲for current and yellow▲*for outdated dependencies. Project names show dark-grey(+N)for commits ahead and a dark-orange*for local Git changes; empty rows and columns are omitted, except that projects with local changes are always shown. A footer summarizes these workspace states,-pumlwill render a plantuml representation of the workspace,-d2will render a d2 representation of the workspace.
Table output uses the rounded, colored terminal format when stdout is an ANSI terminal and falls back to Markdown when redirected or piped.
The Go column holds each module's go directive. The versions are compared as semantic versions, where a missing patch reads as .0 and a release candidate such as 1.27rc1 sorts below 1.27. Every module below the highest version the workspace declares is colored orange, the rest teal. Module import paths lose their github.com/ prefix, so the module column stays narrow.
Configuration
Command line flags select what to display and what to update. How the workspace is scanned is configured instead, in ~/.config/worktree.yml. Run worktree config to edit it in a form, printed inline in the same frame the tables use:
worktree config

The form shows every setting at once, each on its own row with its value and a short description of what it does; the file it writes is captioned in the bottom border. Nothing is hidden behind a dialog.
Arrow keys move between rows. A flag is toggled where it stands with ←, → or Space. A list setting is typed into where it stands, its entries separated by commas. Enter on a setting changes nothing and moves the focus to the Save button below the settings, where Enter writes the file; Discard beside it leaves the file alone. Saving a form with nothing changed writes nothing. F10 saves from any row, Esc leaves, or moves to Discard first when there are unsaved edits.
The settings are:
| Key | Default | Meaning |
|---|---|---|
scan.enable_gitignore |
true |
Honour .gitignore files while walking. |
scan.enable_git_repos |
true |
List Git repositories that are not also Go modules. |
scan.ignore_paths |
empty | Directory names never descended into, whether or not a .gitignore mentions them. Matched against the directory name alone, at any depth. |
scan.root_markers |
go.work, go.mod, .git |
Files marking the workspace root. The nearest parent directory holding one of them becomes the scan root; with no markers the current directory is used. |
Turn enable_gitignore off when a repository consolidates further Git checkouts below it and gitignores those folders to keep them out of its own index. With the setting on, those checkouts are never descended into, so they do not appear at all:
scan:
enable_gitignore: false
ignore_paths is the way to keep such a listing clean. It is empty by default because it also overrides a negation that re-includes the name, such as !vendor:
scan:
enable_gitignore: false
ignore_paths:
- node_modules
- vendor
The file is the complete configuration. The built-in defaults are not applied underneath it, so a setting the file does not name reads as off, and every setting is named so that off is what a missing key means. worktree config always writes every key back, so editing through the setup screen cannot drop one. Where a flag and a setting ever cover the same behaviour, the flag given on the command line wins.
When no file exists the built-in defaults apply, which are the behaviour the tool had before it was configurable. A file that cannot be parsed is reported rather than ignored; worktree config still opens on it, starting from the defaults, so it can be fixed.
You can create a symlink to git-st.
cd /usr/local/bin
ln -s /usr/local/bin/worktree git-st
Creating the symlink enables running git st and git st -v.
Information summarized
The tool scans and displays information about:
- Go module name
- Go version from the go.mod go directive
- Go module versions in use (for updates)
- Go module dependencies in workspace
- README.md title is read for the description
- Latest git version tag
- Git commits since version tag
- Git branch in source tree
- Unpushed git commits
- Local changes to source tree
- Untracked changes to source tree
- GitHub issues (gh issue list)
It's focused on summarizing of Go workspaces, or git checkouts of standalone Go modules. Git support may be extended to better account for custom remotes and checkouts that aren't a go module source tree.
Examples
Summary workspace view
The following screenshots show standard output, workspace filtering and verbose output for the complete workspace.




D2 Diagram
PlantUML Diagram
Why?
Using a go workspace is a relatively smooth experience, but most software still gets built and delivered outside a workspace.
This process requires updating the go.mod dependencies as a new version gets tagged. For each module in a workspace I'm interested in:
- using the latest release across the workspace in go.mod
- seeing any local changes not yet commited or pushed
- updating dependencies in the correct order
Alternatives considered
For years now, I've been using git st, to get a recursive view of a git source tree. I maintain a bash version of it in my dotfiles, as well as had a php version eons ago. Let's consider this something like a v3 for the approach.
Git source trees don't give enough dependency information, so I wanted something that reads in go.mod go.work files and provides relevant information to you.
Documentation
¶
There is no documentation for this package.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package config holds the worktree configuration document and the setup screen that edits it.
|
Package config holds the worktree configuration document and the setup screen that edits it. |