Projects
Project checkout automation should be explicit and safe. A public workstation repo can describe common structure without exposing private work.
Canonical Layout
Use the ghq directory model for local checkouts:
~/repos/github.com/YunYouJun/workstationConfigure ghq once per machine:
git config --global ghq.root ~/reposCheck the current value:
git config --global --get ghq.rootClone repositories through ghq when possible:
ghq get [email protected]:YunYouJun/workstation.git
cd "$(ghq list -p github.com/YunYouJun/workstation)"This keeps the local path close to the remote URL and avoids private shorthand such as ~/repos/gh/yyj.
Active GitHub Repositories
Use the CLI to fetch and clone the most recently pushed repositories owned by YunYouJun:
workstation projects clone-activeThe command is a dry-run by default. Apply it explicitly after reviewing the target paths:
workstation projects clone-active --yesConfigure how many active repositories to fetch:
workstation projects clone-active --limit 20Shorter form:
wst p active --limit 20Select repositories interactively before previewing or cloning:
wst p active --limit 50 -iYou can also set the script/default count, which works well in a shell profile or machine-local config:
WORKSTATION_ACTIVE_PROJECT_LIMIT=20 pnpm projects:clone-activeConfigure the project root:
workstation projects clone-active --root ~/reposUpdate existing checkouts:
workstation projects clone-active --update --yesUse HTTPS clone URLs:
workstation projects clone-active --https --yesInclude forks and archived repositories:
workstation projects clone-active --include-forks --include-archivedFor script-style use, run the root package alias:
pnpm projects:clone-activeThe implementation delegates repository discovery to gh api graphql and sorts by PUSHED_AT DESC, which is closer to "recently active" than alphabetical or created-time listings. Authenticate once with:
gh auth loginWhen ghq is installed and the primary ghq.root matches the requested --root, the command uses ghq get. Otherwise it falls back to explicit git clone targets under:
~/repos/github.com/<owner>/<repo>Local Status Audit
Before switching machines or cleaning up an old machine, inspect local Git repositories under ~/repos:
workstation projects statusShort alias and script entry:
wst p status
pnpm projects:statusBy default, only repositories that need attention are shown. The audit reports uncommitted files, committed-but-unpushed work, stashes, missing upstreams, and gone upstreams. Show every repository:
workstation projects status --allThe scan descends up to 6 directory levels by default. Increase it for deeper checkout layouts, or lower it to constrain the audit:
workstation projects status --max-depth 8For scripts or pre-migration checks, return a non-zero exit code when any repository needs attention:
workstation projects status --checkManifest Pattern
Manifest mode can clone common projects from any Git host, including GitHub, GitHub Enterprise, GitLab, git.example.com, or other internal sources. It also defaults to dry-run; add --yes after reviewing the target paths:
wst p manifest --file projects.local.yaml
wst p manifest --file projects.local.yaml --yesYou can also keep the manifest in a private configuration repository. The CLI clones that repository into a local cache, then reads projects.yaml:
wst p manifest https://git.example.com/<user>/<config-repo>
wst p manifest https://git.example.com/<user>/<config-repo> --group common --yesIf the manifest does not live at projects.yaml or projects.yml in the configuration repository root, pass the internal path:
wst p manifest --repo https://git.example.com/<user>/<config-repo> --manifest workstation/projects.yamlPrivate configuration repositories are cached under ~/.cache/workstation/project-manifests/. Projects still clone into the ~/repos/<host>/<repo-path> layout. group is only a manifest selection and organization mechanism; it does not become part of the target path. When the primary ghq.root matches the target root and the target path matches the path inferred from the clone URL, the CLI uses ghq get; otherwise it falls back to explicit git clone.
Commit only a sample manifest to the public repo:
projects.example.yamlKeep private or machine-specific projects in:
projects.local.yamlprojects.local.yaml is ignored by Git.
Manifest shape:
groups:
common:
root: ~/repos
host: git.example.com
repositories:
- name: github.com/YunYouJun/workstation
url: [email protected]:YunYouJun/workstation.git
- example/private-service
- name: local-alias/private-service
path: example/private-serviceIf an entry only has name: git.example.com/<group>/<repo>, the CLI infers an SSH clone URL by default; with --https, it infers an HTTPS clone URL instead. For entries that need both, define sshUrl and httpsUrl, and the command will choose based on --https. You can also define host at the manifest or group level and then list concise repository paths such as example/private-service.
When the local target path intentionally differs from the remote repository path, use object entries with name for the local path and path for the remote repository path. Those entries automatically avoid ghq get and use explicit git clone <url> <target>, so ghq does not place the checkout at the remote URL path instead.
Multiple Git Accounts and Source Isolation
When one machine talks to GitHub, GitHub Enterprise, company GitLab, or other internal Git hosts, keep commit identity separate from remote authentication:
- Select commit identity with Git
includeIfrules based on checkout paths. - Select authentication accounts with SSH
Host/IdentityFileentries or HTTPS credential helpers. - Enable
user.useConfigOnlyglobally so Git does not guess the wrong email. - When the same host has multiple accounts, use SSH host aliases and point repository remotes at those aliases.
Keep the global Git config as routing only, without a default identity:
[user]
useConfigOnly = true
[includeIf "gitdir:~/repos/github.com/"]
path = ~/.gitconfig-github
[includeIf "gitdir:~/repos/git.example.com/"]
path = ~/.gitconfig-workPut per-source identities in separate files:
# ~/.gitconfig-github
[user]
name = Your Name
email = [email protected]# ~/.gitconfig-work
[user]
name = Your Name
email = [email protected]Choose SSH authentication through host entries:
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
IdentitiesOnly yes
Host git.example.com-work
HostName git.example.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yesFor multiple accounts on the same host, point the repository remote at the alias:
git remote set-url origin [email protected]:team/repo.gitInspect the effective identity and authentication entry for the current repository:
git config --show-origin --get user.name
git config --show-origin --get user.email
git remote -v
ssh -G git.example.com-work | grep identityfileAvoid making includeIf "hasconfig:remote.*.url:..." the default way to select identity from remote URLs. New clones, fork + upstream setups, and multi-remote repositories can make those rules ambiguous; path-based identity under ~/repos/<host>/... is easier to predict and audit.
The matching CLI init task is git.include-if. List tasks and preview writes first:
wst init --list
wst init git.include-if --git-profile 'id=github;host=github.com;name=Your Name;[email protected]'Apply after reviewing the plan:
wst init git.include-if --git-profile 'id=github;host=github.com;name=Your Name;[email protected]' --yesIf the machine already has ~/.gitconfig-github with user.name and user.email, the CLI can infer the default GitHub profile:
wst init git.include-if --yesUse interactive mode when you want to choose init tasks and enter identities by hand:
wst init -iBest Practices
- Prefer
ghqfor ordinary project checkouts. - Switch Git commit identity by
~/repos/<host>/...path, and switch remote authentication by SSH host or credential helper. - Enable
user.useConfigOnlyso repositories without a matching identity cannot commit. - Group projects by purpose, not by accident of history; groups should not change clone target paths.
- Keep public examples generic.
- Prefer SSH URLs for repositories you actively push to.
- Make clone scripts default to dry-run.
- Skip repositories that already exist unless an explicit update mode is requested.
- Keep target directories configurable, with
~/reposas the default root. - Use
ghfor GitHub-specific listing and authentication workflows. - Use
PUSHED_ATordering for active repository discovery.
Manifest mode can keep expanding around this shape without forcing private repository names into public Git. For ordinary Git repositories, it produces the same target path shape as ghq.
Migrating Old Paths
If this repository already exists at an older shorthand path, move it once and leave a compatibility symlink only while old editor windows or scripts still refer to the previous location:
mkdir -p ~/repos/github.com/YunYouJun
mv ~/repos/gh/yyj/workstation ~/repos/github.com/YunYouJun/workstation
mkdir -p ~/repos/gh/yyj
ln -s ~/repos/github.com/YunYouJun/workstation ~/repos/gh/yyj/workstationAfter shell history, editor workspaces, and local scripts use the new path, the compatibility symlink can be removed.