Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions configs/git/aliases.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Git alias catalog for Botstrap Phase 2 / Phase 3.
# Applied via ~/.config/botstrap/git-aliases (included from ~/.gitconfig).

defaults:
enabled: true

aliases:
- id: st
name: st
command: status -sb
description: Short status with branch info
default: true

- id: co
name: co
command: checkout
description: Switch branches
default: true

- id: br
name: br
command: branch -vv
description: List branches with tracking info
default: true

- id: ci
name: ci
command: commit
description: Create a commit
default: true

- id: ca
name: ca
command: commit --amend
description: Amend the last commit
default: true

- id: cane
name: cane
command: commit --amend --no-edit
description: Amend without editing the message
default: true

- id: unstage
name: unstage
command: restore --staged
description: Unstage files
default: true

- id: undo
name: undo
command: reset HEAD~1 --mixed
description: Undo last commit, keep changes
default: true

- id: last
name: last
command: log -1 HEAD
description: Show the latest commit
default: true

- id: lg
name: lg
command: log --oneline --graph --decorate -20
description: Compact recent history graph
default: true

- id: df
name: df
command: diff
description: Show unstaged diff
default: true

- id: dc
name: dc
command: diff --cached
description: Show staged diff
default: true

- id: pullr
name: pullr
command: pull --rebase
description: Pull with rebase
default: true

- id: pushf
name: pushf
command: push --force-with-lease
description: Safer force push
default: true
5 changes: 4 additions & 1 deletion docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ For **defaults**, **automation env vars**, and **how to customize** (reconfigure
|-----------------|----------------------|
| `configs/git/gitconfig` | Copied to **`~/.gitconfig`** only when that file does **not** already exist (Unix Phase 3). |
| `configs/git/gitignore_global` | Copied to **`~/.gitignore_global`**; `git config --global core.excludesfile` set to that path when Git is available. |
| `configs/git/aliases.yaml` | Catalog of recommended git aliases (not copied verbatim). Phase 2 uses it for preview and multi-select; Phase 3 writes selected aliases to **`~/.config/botstrap/git-aliases`** and adds a **`[include]`** in **`~/.gitconfig`** (marker **`# botstrap git-aliases`**). |

Global **`user.name`** and **`user.email`** are set from **`BOTSTRAP_GIT_NAME`** and **`BOTSTRAP_GIT_EMAIL`** when non-empty (not from static files).
Global **`user.name`** and **`user.email`** are set from **`BOTSTRAP_GIT_NAME`** and **`BOTSTRAP_GIT_EMAIL`** when non-empty (not from static files). Git alias selection is driven by **`BOTSTRAP_GIT_ALIASES`** (see [Reference — Phase 2 selection variables](./REFERENCE.md#phase-2-selection-variables-unix)).

## `configs/shell/`

Expand Down Expand Up @@ -57,6 +58,8 @@ Phase 3 also writes:

- **`~/.config/botstrap/theme.env`** — `theme=<value>`
- **`~/.config/botstrap/editor.env`** — `editor=<value>`
- **`~/.config/botstrap/git-aliases.env`** — `selected=` and `managed=` alias id lists
- **`~/.config/botstrap/git-aliases`** — generated `[alias]` fragment included from **`~/.gitconfig`**

## `themes/`

Expand Down
4 changes: 3 additions & 1 deletion docs/DEFAULTS_AND_CUSTOMIZATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ When **gum** is not on `PATH`, Phase 2 (`install/phase-2-tui.sh` / `phase-2-tui.
| Variable | Default when gum is missing |
|----------|-----------------------------|
| `BOTSTRAP_GIT_NAME` / `BOTSTRAP_GIT_EMAIL` | Empty unless already set in the environment. |
| `BOTSTRAP_GIT_ALIASES` | All catalog entries with **`default: true`** when **`configs/git/aliases.yaml`** has **`defaults.enabled: true`**, unless **`git-aliases.env`** already has **`selected=`** (reconfigure). Set to **`none`** to skip. |
| `BOTSTRAP_EDITOR` | `none` |
| `BOTSTRAP_LANGUAGES` | Empty (no optional language installs from TUI). |
| `BOTSTRAP_DATABASES` | Empty. |
Expand All @@ -22,7 +23,7 @@ You can **pre-set any `BOTSTRAP_*`** before running `install.sh`, `install.ps1`,

Phase 3 copies or merges from **`configs/`** and runs optional installs from **`registry/optional.yaml`**. Typical defaults:

- **Git:** `configs/git/gitconfig` is copied to **`~/.gitconfig`** only if that file **does not** already exist. Global **`user.name`** / **`user.email`** are set from **`BOTSTRAP_GIT_NAME`** / **`BOTSTRAP_GIT_EMAIL`** when non-empty.
- **Git:** `configs/git/gitconfig` is copied to **`~/.gitconfig`** only if that file **does not** already exist. Global **`user.name`** / **`user.email`** are set from **`BOTSTRAP_GIT_NAME`** / **`BOTSTRAP_GIT_EMAIL`** when non-empty. **Git shortcuts** (`git st`, `git co`, …) from **`configs/git/aliases.yaml`** are written to **`~/.config/botstrap/git-aliases`** and included from **`~/.gitconfig`** when selected in Phase 2 (or when **`BOTSTRAP_GIT_ALIASES`** is preset).
- **Git ignore:** `gitignore_global` is copied and **`core.excludesfile`** is pointed at it when Git is available.
- **Starship:** `configs/shell/prompt.toml` → **`~/.config/starship.toml`** (overwrites when the repo file exists).
- **Shell rc files:** `aliases` and `functions` are appended **once** inside `# botstrap aliases` / `# botstrap functions` blocks to **`~/.zshrc`** and **`~/.bashrc`** (Unix). The PATH snippet sources **`~/.config/botstrap/env.sh`**.
Expand Down Expand Up @@ -50,6 +51,7 @@ Export **`BOTSTRAP_*`** variables before the orchestrator or before sourcing Pha
### 4. Manual edits in your home directory

- Prefer editing **`~/.config/...`** files directly for Starship, editor configs, and Git excludes when you do not want to flow changes through the repo.
- **Git aliases:** edit **`~/.config/botstrap/git-aliases`** directly, or run **`botstrap reconfigure`** to change the Phase 2 selection. To add custom aliases outside Botstrap, set them in **`~/.gitconfig`** (not in the include file) so reconfigure does not overwrite them.
- For **`~/.zshrc`** / **`~/.bashrc`**, avoid duplicating Botstrap blocks: either edit **outside** the `# botstrap …` sections or adjust **`configs/shell/*`** in the clone and re-run Phase 3 so a single marked block stays canonical.

### 5. Fork or extend the registry
Expand Down
6 changes: 5 additions & 1 deletion docs/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Operational facts: **CLI**, **environment variables**, and **artifacts** Botstra
| `botstrap update` | **Interactive (TTY + `gum`):** **`gum choose`** among **Botstrap repo only**, **Installed tools only**, **Both**, or **Cancel**. **Non-interactive, no flags:** repo-only pull (backward compatible) and prints a one-line hint about **`--tools`**, **`--all`**, and **`self-update`**. **Flags:** **`--self`** — git pull only; **`--tools`** — run **`install/update-tools.sh`** (Bash) or **`install/update-tools.ps1`** (PowerShell) to upgrade **prerequisites**, **selected core**, and **persisted optional** selections per registry **`update`** snippets; **`--all`** — self then tools. Does **not** re-run full Phase 3 except what each **`update`** snippet does. |
| `botstrap reconfigure` | **Bash:** sets **`BOTSTRAP_ROOT`**, runs **`lib/detect`**, then sources **`install/phase-2-tui.sh`** and **`install/phase-3-configure.sh`** only. **PowerShell:** sets **`BOTSTRAP_ROOT`**, dot-sources **`install/phase-2-tui.ps1`** and **`install/phase-3-configure.ps1`**. |
| `botstrap doctor` | **Bash:** prints a short **status** header (`BOTSTRAP_ROOT`, semver, optional git head, whether **`~/.config/botstrap/env.sh`** exists), then runs **`install/phase-4-verify.sh`**. **PowerShell:** similar header (whether the **`# botstrap PATH`** hook is present in **each** known profile path—see Windows Phase 3 artifacts), then dot-sources **`install/phase-4-verify.ps1`**. Exits **0** if every verify passes, **1** if **`yq`** is missing or any verify fails. |
| `botstrap uninstall` | Removes **Phase 3 shell integration** only (see **`install/uninstall.sh`** / **`install/uninstall.ps1`**). **Unix:** strips **`# botstrap PATH`**, **`# botstrap aliases`**, and **`# botstrap functions`** blocks from **`~/.zshrc`** and **`~/.bashrc`**, and deletes **`~/.config/botstrap/env.sh`**. **Windows:** removes **`# botstrap PATH`**, **`# botstrap starship`**, **`# botstrap zoxide`**, and **`# botstrap aliases`** regions from **each** PowerShell profile path Botstrap manages (same set as Phase 3). **Does not** uninstall packages (Homebrew, apt, winget, mise, etc.) or remove files Botstrap copied elsewhere (e.g. **`~/.config/starship.toml`**, editor settings, **`~/.gitconfig`**). **Exit 1** if the user cancels, a guard refuses **`--remove-checkout`**, or usage is invalid. |
| `botstrap uninstall` | Removes **Phase 3 shell integration** and **Botstrap-managed git aliases** (see **`install/uninstall.sh`** / **`install/uninstall.ps1`**). **Unix:** strips **`# botstrap PATH`**, **`# botstrap aliases`**, and **`# botstrap functions`** blocks from **`~/.zshrc`** and **`~/.bashrc`**, removes the **`# botstrap git-aliases`** **`[include]`** block from **`~/.gitconfig`**, deletes **`~/.config/botstrap/git-aliases`**, and deletes **`~/.config/botstrap/env.sh`**. **Windows:** removes **`# botstrap PATH`**, **`# botstrap starship`**, **`# botstrap zoxide`**, and **`# botstrap aliases`** regions from **each** PowerShell profile path Botstrap manages (same set as Phase 3), plus the git alias include and fragment as on Unix. **Does not** uninstall packages (Homebrew, apt, winget, mise, etc.) or remove other files Botstrap copied elsewhere (e.g. **`~/.config/starship.toml`**, editor settings, the rest of **`~/.gitconfig`**). With **`--purge`**, also deletes **`git-aliases.env`**. **Exit 1** if the user cancels, a guard refuses **`--remove-checkout`**, or usage is invalid. |
| `botstrap` (no arguments) | If **stdin** and **stdout** are TTYs (**Bash**) or the console is not redirected (**PowerShell**) **and** **`gum`** is on **`PATH`**, shows a **`gum choose`** menu for **`update`**, **`self-update`**, **`reconfigure`**, **`doctor`**, **`uninstall`**, **`version`**, or **`quit`** (exit **0**). Otherwise prints **usage** and exits **1**. For automation and **AI agents**, pass an explicit subcommand (e.g. **`botstrap doctor`**, **`botstrap update --all`**) instead of relying on the menu. |
| Any other first argument | Prints **usage** and exits with code **1**. |

Expand Down Expand Up @@ -46,6 +46,7 @@ Set by **`install/phase-2-tui.sh`** (or defaults when gum is missing). Group ids
|----------|---------|
| `BOTSTRAP_GIT_NAME` | Global Git `user.name` (Phase 3). |
| `BOTSTRAP_GIT_EMAIL` | Global Git `user.email` (Phase 3). |
| `BOTSTRAP_GIT_ALIASES` | Comma-separated alias **`id`** values from **`configs/git/aliases.yaml`** (e.g. `st,co,lg`), or **`none`** to skip. Interactive Phase 2 shows a preview and multi-select; non-interactive default: all catalog entries with **`default: true`** when **`defaults.enabled`** is true (or persisted **`selected=`** from **`git-aliases.env`** on reconfigure). |
| `BOTSTRAP_CORE_TOOLS` | Comma-separated tool **`name`** values from **`registry/core.yaml`** to install in Phase 3 (registry order). Set by the TUI (default: all names) or non-interactive defaults; may be preset for automation. |
| `BOTSTRAP_EDITOR` | One of: `cursor`, `vscode`, `neovim`, `zed`, `none`. |
| `BOTSTRAP_LANGUAGES` | Comma-separated mise-related choices: `node`, `python`, `ruby`, `go`, `rust`, `java`, `elixir`, `php`, `none`, … |
Expand All @@ -72,6 +73,8 @@ Unless otherwise noted, paths are under **`$HOME`**.
| `~/.config/starship.toml` | Overwritten from `configs/shell/prompt.toml` when that file exists in the repo. |
| `~/.gitignore_global` | Copied from `configs/git/gitignore_global`; `core.excludesfile` set globally. |
| Git user.name / user.email | Set from `BOTSTRAP_GIT_*` when non-empty. |
| Git aliases | Selected ids from **`BOTSTRAP_GIT_ALIASES`** written to **`~/.config/botstrap/git-aliases`**; **`~/.gitconfig`** gets a one-time **`# botstrap git-aliases`** **`[include]`** pointing at that file. Existing global aliases with the same name are skipped unless Botstrap previously managed them. |
| `~/.config/botstrap/git-aliases.env` | **`selected=`** and **`managed=`** comma-separated alias ids (Phase 3) for reconfigure TUI defaults and conflict detection. |
| `~/.zshrc`, `~/.bashrc` | Appended **once** (marker-guarded) with contents of `configs/shell/aliases`, `configs/shell/functions`, and `configs/shell/env_path_snippet.bash` when those repo files exist. The PATH snippet sources **`~/.config/botstrap/env.sh`**. |
| `~/.config/botstrap/core-tools.env` | **`core_tools=`** comma-separated list (persisted Phase 3) for **`botstrap doctor`** / reconfigure default core selection when **`BOTSTRAP_CORE_TOOLS`** is not set in the shell. |
| `~/.config/botstrap/optional-selections.env` | **`languages=`**, **`databases=`**, **`ai_tools=`**, **`optional_apps=`** (Phase 3) for **`botstrap update --tools`** and TUI **`--selected`** defaults on reconfigure. |
Expand All @@ -88,6 +91,7 @@ Paths use **`%USERPROFILE%`** where relevant.
|--------|-----------|
| **`%USERPROFILE%\.config\botstrap\core-tools.env`** | **`core_tools=`** persisted list (Phase 3) for **`doctor`** / TUI defaults when **`BOTSTRAP_CORE_TOOLS`** is unset. |
| **`%USERPROFILE%\.config\botstrap\optional-selections.env`** | **`languages=`**, **`databases=`**, **`ai_tools=`**, **`optional_apps=`** for **`update --tools`** and reconfigure TUI defaults. |
| Git aliases | Same as Unix: **`%USERPROFILE%\.config\botstrap\git-aliases`**, include block in **`%USERPROFILE%\.gitconfig`**, **`git-aliases.env`** for persistence. |
| Editor configs (**`BOTSTRAP_EDITOR`**) | **cursor** / **vscode:** under **`%USERPROFILE%`** as in [Configuration file map](./CONFIGURATION.md). **neovim:** **`%LOCALAPPDATA%\nvim`** — LazyVim from core tool **`neovim`** (**`install/modules/lazyvim.ps1`**); minimal **`init.lua`** only when **`lua\config\lazy.lua`** is missing. |
| Zellij **`config.kdl`** (`default_shell`) | When **`zellij`** is in **`BOTSTRAP_CORE_TOOLS`**: Phase 3 runs **`install/modules/zellij.ps1`** which sets **`default_shell`** to the resolved `pwsh`/`powershell` path in **`config.kdl`** (location from `zellij setup --check`; fallback **`%USERPROFILE%\.config\zellij\config.kdl`**). Marker comment `// botstrap: default_shell (Windows)` guards repeated runs. |
| PowerShell **profiles** (dual host): **`Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`** (Windows PowerShell 5.1) and **`Documents\PowerShell\Microsoft.PowerShell_profile.ps1`** (**`pwsh`** 7+), plus **`$PROFILE`** when it differs (e.g. VS Code host) | Each file is updated **once** (marker-guarded) with the same blocks: **`# botstrap PATH`** sets **`$env:BOTSTRAP_ROOT`**, prepends **`$BOTSTRAP_ROOT\bin`** to **`$env:PATH`**, and defines **`function Global:botstrap`** invoking **`bin\botstrap.ps1`**. Also **`# botstrap starship`**, **`# botstrap zoxide`**, and **`# botstrap aliases`** when missing. |
Expand Down
82 changes: 82 additions & 0 deletions install/phase-2-tui.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,22 @@ if (-not (Get-Command gum -ErrorAction SilentlyContinue)) {
if ($om.Count -gt 0) { $env:BOTSTRAP_OPTIONAL_APPS = ($om[0] -replace '^\s*optional_apps=', '').Trim() }
}
if (-not $env:BOTSTRAP_OPTIONAL_APPS) { $env:BOTSTRAP_OPTIONAL_APPS = '' }
. (Join-Path $env:BOTSTRAP_ROOT 'lib\git-aliases.ps1')
if (-not $env:BOTSTRAP_GIT_ALIASES) {
$gitAliasesEnv = Get-BotstrapGitAliasesEnvPath
if (Test-Path -LiteralPath $gitAliasesEnv) {
$gaMatch = @(Get-Content -LiteralPath $gitAliasesEnv -ErrorAction SilentlyContinue | Where-Object { $_ -match '^\s*selected=' } | Select-Object -First 1)
if ($gaMatch.Count -gt 0) {
$env:BOTSTRAP_GIT_ALIASES = ($gaMatch[0] -replace '^\s*selected=', '').Trim()
}
else {
$env:BOTSTRAP_GIT_ALIASES = Get-BotstrapGitAliasesDefaultCsv
}
}
else {
$env:BOTSTRAP_GIT_ALIASES = Get-BotstrapGitAliasesDefaultCsv
}
}
return
}

Expand Down Expand Up @@ -83,6 +99,72 @@ if (-not $env:BOTSTRAP_GIT_EMAIL) {
$env:BOTSTRAP_GIT_EMAIL = & gum input --placeholder $gitEmailPlaceholder @emailArgs
}

. (Join-Path $env:BOTSTRAP_ROOT 'lib\git-aliases.ps1')
if (-not $env:BOTSTRAP_GIT_ALIASES) {
$gitAliasLabels = @(Get-BotstrapGitAliasesChooseLabels)
if ($gitAliasLabels.Count -gt 0) {
$previewLines = @(Get-BotstrapGitAliasesPreviewLines)
$previewText = ($previewLines -join "`n")
$ErrorActionPreference = 'Continue'
& gum style --border normal --padding '0 1' --foreground 212 `
'Git shortcuts' '' `
'Run git st, git co, and similar aliases from configs/git/aliases.yaml.' '' `
$previewText
$ErrorActionPreference = 'Stop'
$installAliases = $false
$ErrorActionPreference = 'Continue'
if (& gum confirm 'Install git shortcuts? (git st, git co, …)') {
$installAliases = $true
}
$ErrorActionPreference = 'Stop'
if ($installAliases) {
$gitAliasEnvFile = Get-BotstrapGitAliasesEnvPath
$gitAliasGumArgs = @('choose', '--no-limit', '--ordered', '--header', 'Git shortcuts (git <name>)')
$seedCsv = ''
if (Test-Path -LiteralPath $gitAliasEnvFile) {
$gaSeed = @(Get-Content -LiteralPath $gitAliasEnvFile -ErrorAction SilentlyContinue | Where-Object { $_ -match '^\s*selected=' } | Select-Object -First 1)
if ($gaSeed.Count -gt 0) {
$seedCsv = ($gaSeed[0] -replace '^\s*selected=', '').Trim()
}
}
if ($seedCsv -eq 'none') {
# no pre-selection
}
elseif ($seedCsv) {
foreach ($rawId in $seedCsv.Split(',')) {
$id = $rawId.Trim()
if (-not $id) { continue }
foreach ($label in $gitAliasLabels) {
if ($label.StartsWith("$id → ")) {
$gitAliasGumArgs += @('--selected', $label)
}
}
}
}
else {
$gitAliasGumArgs += @('--selected', '*')
}
$gitAliasGumArgs += $gitAliasLabels
$ErrorActionPreference = 'Continue'
$aliasLines = @( & gum @gitAliasGumArgs )
$ErrorActionPreference = 'Stop'
$aliasIds = @($aliasLines | ForEach-Object { Get-BotstrapGitAliasIdFromLabel -Label "$_".Trim() } | Where-Object { $_ })
if ($aliasIds.Count -gt 0) {
$env:BOTSTRAP_GIT_ALIASES = ($aliasIds -join ',')
}
else {
$env:BOTSTRAP_GIT_ALIASES = 'none'
}
}
else {
$env:BOTSTRAP_GIT_ALIASES = 'none'
}
}
else {
$env:BOTSTRAP_GIT_ALIASES = 'none'
}
}

$ErrorActionPreference = 'Stop'
$coreYaml = Join-Path $env:BOTSTRAP_ROOT 'registry\core.yaml'
$coreNames = @(& yq -r '.tools[].name' $coreYaml 2>$null | ForEach-Object { "$_".Trim() } | Where-Object { $_ })
Expand Down
Loading