Projects
Renders per-project shell entry points from the machine's projects map — a jump alias per project, a projects list, and a project <name> command — so declaring a project is all it takes to cd into it, title the tab, and switch context.
What it does
- Generates a bare jump alias for each curated project — one that sets
alias:ortitle:— named after the project (itsalias:, else the key's last segment):cdin, set the terminal tab title, apply its context, and show its git state (projectinfo) - Adds a
project <name>command that reaches every project (curated or not) by name, with tab completion and a substring fallback when the name is inexact (one match jumps, several list) - Adds a
projectscommand that lists every project and its path, the waynodeslists nodes - Adds a
projectinfocommand that shows the current project's git state (origin, branches, status) — the read-only counterpart to jumping in - Optionally scopes the shell to a project's
context:on jump (cloud project, cluster namespace, AWS profile), reusing the same per-shell env vars the prompt already renders
All of it derives from the same projects record the git role clones from and the agents role lists in PROJECTS.md, so the jump aliases never drift from the clone list.
Demo
The same projects map pays off for agents: asked for work in a project by name, the agent lists the machine's projects and moves to the right checkout instead of guessing at paths:
Fix the broken link on the website project's homepage.Variables
| Variable | Default | Description |
|---|---|---|
projects_path | the git role's git_repositories_path (~/) | Base directory the jump aliases cd into; a project key resolves under it unless its path: is absolute or ~-prefixed |
projects_functions | See defaults | The static shell functions (project, projects, completion); the per-project data they read is generated from projects |
The role reads the machine-level projects map directly (via projects | default({})); it adds no clone list of its own. Each entry may carry, on top of the keys the git and agents roles use:
| Project key | Meaning |
|---|---|
alias | The bare alias name, and opts the entry in to one (defaults to the key's last segment) |
title | The tab title and header text, and opts the entry in to a bare alias (defaults to the alias name) |
context | Shell run on jump, to scope this terminal — e.g. export CLOUDSDK_CORE_PROJECT=acme |
Setting alias or title is what opts an entry in to a bare alias (dotfilespro on its own). An entry with neither — just a repository/description — gets no bare alias but is still reachable via project <name> and its completion. This keeps a large map from minting dozens of colliding bare aliases when many repos share a leaf name (cert-manager, gitlab-pipelines, …); curate the ones you jump to with a title, reach the rest through project.
Trailing-slash group headings and any entry the git role skips (clone: false, no repository) are handled the same way here: headings never become aliases; a repository-less entry still gets a bare alias only if curated, and a jump if its directory exists.
Example
# host_vars/<host>.yaml — the projects map, shared with the git and agents roles
projects_path: /projects/ # default: the git role's git_repositories_path (~/)
projects:
baksteen/: # group heading — no alias, no clone
title: Baksteen Media
baksteen/dotfilespro:
repository: git@gitlab.com:baksteen/dotfilespro.git
title: Dotfiles Pro # tab title + header; alias is `dotfilespro`
work/api:
repository: git@gitlab.com:acme/api.git
alias: api # `api` jumps to /projects/work/api
context: export CLOUDSDK_CORE_PROJECT=acme-prod # scope gcloud to this shellWith that, dotfilespro jumps to /projects/baksteen/dotfilespro and titles the tab "Dotfiles Pro"; api jumps to /projects/work/api and scopes gcloud for that terminal only; projects lists both; project <tab> completes their names.
Aliases
| Command / alias | Does |
|---|---|
projects | List every project and its path |
project <name> | Jump to a project by name (tab-completed; substring fallback) |
projectinfo | Show the current project's git state (origin, branches, status) |
<name> | The generated per-project alias — jump straight to that project |
How it works
The per-project aliases and the project/projects functions read one generated table, _projects_data, that emits a tab-separated name path title context line per project. The functions themselves are static (in projects_functions); only the table is rendered from the projects map, so the shell logic stays readable and the data stays single-sourced. A jump ends by calling projectinfo, which reuses the header, tab, and keyvalue helpers the unix role defines, so a project banner matches list. The context line is applied with eval in the calling shell before that, which is why it scopes only that terminal — the same per-shell context isolation the prompt renders.