Migrate filesystem layout to XDG-compliant, fully isolated directory structure #18

Open
opened 2026-06-26 23:03:31 +05:30 by sortedcord · 0 comments
Owner

Bootstrap currently scatters files across multiple unrelated locations in the user's home directory:

  • Binaries go to ~/.local/bin/, polluting a directory the user may already use for their own executables
  • Neovim + asciinema require sudo to install into /opt/nvim and /usr/local/bin
  • Managed runtimes colonize the home directory root: ~/.nvm/, ~/.cargo/, ~/.rustup/
  • pnpm lives in ~/.local/share/pnpm — isolated from the rest of Bootstrap's data
  • Mutable state (registry.json) is stored in ~/.config/bootstrap/, which is semantically wrong — .config is for configuration, not runtime state
  • Multiple installers each write their own redundant env.d/local-bin.sh snippet to add ~/.local/bin to PATH

This fragmentation makes clean uninstallation impossible without a manifest, violates the XDG Base Directory Specification, and contradicts Bootstrap's core principle of being a single, nukeable, fully isolated system.

Proposed Layout

~/.config/bootstrap/                  # Lightweight config only
├── b.sh                              # CLI entrypoint
├── VERSION
├── env.d/*.sh                        # Modular PATH/env snippets
├── aliases.d/*.sh                    # Modular alias snippets
├── lib/                              # Bootstrap libraries
├── installers/                       # Cached installer scripts
├── commands/                         # CLI subcommands
└── plugins/                          # Plugin scripts

~/.local/share/bootstrap/             # Heavy storage (binaries, runtimes)
├── bin/                              # All standalone binaries
├── opt/                              # Multi-file installations (e.g. nvim/)
├── runtimes/                         # Managed tool homes (nvm/, cargo/, rustup/, pnpm/)
└── completions/                      # Shell completions (future)

~/.local/state/bootstrap/             # Mutable state
├── registry.json                     # Tool manifest
├── logs/                             # Installation logs
└── rollback/                         # Rollback state

~/.cache/bootstrap/                   # Disposable cache
├── downloads/                        # Cached archives
└── tmp/                              # Temp working dirs

Environment Variables

Variable Default Purpose
BOOTSTRAP_DIR ~/.config/bootstrap Config, shell snippets, libs
BOOTSTRAP_DATA_DIR ~/.local/share/bootstrap Binaries, runtimes, opt
BOOTSTRAP_STATE_DIR ~/.local/state/bootstrap Registry, logs, rollback
BOOTSTRAP_CACHE_DIR ~/.cache/bootstrap Download cache, temp dirs
BOOTSTRAP_BIN $BOOTSTRAP_DATA_DIR/bin Binary executables
BOOTSTRAP_OPT $BOOTSTRAP_DATA_DIR/opt Multi-file installs
BOOTSTRAP_RUNTIMES $BOOTSTRAP_DATA_DIR/runtimes Managed tool homes

Clean Removal

After this migration, full removal becomes:

rm -rf ~/.local/share/bootstrap      # All binaries and runtimes
rm -rf ~/.config/bootstrap           # Config and shell integration
rm -rf ~/.local/state/bootstrap      # State and registry
rm -rf ~/.cache/bootstrap            # Cache
sed -i '/bootstrap/d' ~/.bashrc      # Remove shell hook
Bootstrap currently scatters files across multiple unrelated locations in the user's home directory: - **Binaries** go to `~/.local/bin/`, polluting a directory the user may already use for their own executables - **Neovim + asciinema** require `sudo` to install into `/opt/nvim` and `/usr/local/bin` - **Managed runtimes** colonize the home directory root: `~/.nvm/`, `~/.cargo/`, `~/.rustup/` - **pnpm** lives in `~/.local/share/pnpm` — isolated from the rest of Bootstrap's data - **Mutable state** (`registry.json`) is stored in `~/.config/bootstrap/`, which is semantically wrong — `.config` is for configuration, not runtime state - **Multiple installers** each write their own redundant `env.d/local-bin.sh` snippet to add `~/.local/bin` to PATH This fragmentation makes clean uninstallation impossible without a manifest, violates the XDG Base Directory Specification, and contradicts Bootstrap's core principle of being a **single, nukeable, fully isolated** system. ## Proposed Layout ``` ~/.config/bootstrap/ # Lightweight config only ├── b.sh # CLI entrypoint ├── VERSION ├── env.d/*.sh # Modular PATH/env snippets ├── aliases.d/*.sh # Modular alias snippets ├── lib/ # Bootstrap libraries ├── installers/ # Cached installer scripts ├── commands/ # CLI subcommands └── plugins/ # Plugin scripts ~/.local/share/bootstrap/ # Heavy storage (binaries, runtimes) ├── bin/ # All standalone binaries ├── opt/ # Multi-file installations (e.g. nvim/) ├── runtimes/ # Managed tool homes (nvm/, cargo/, rustup/, pnpm/) └── completions/ # Shell completions (future) ~/.local/state/bootstrap/ # Mutable state ├── registry.json # Tool manifest ├── logs/ # Installation logs └── rollback/ # Rollback state ~/.cache/bootstrap/ # Disposable cache ├── downloads/ # Cached archives └── tmp/ # Temp working dirs ``` ## Environment Variables | Variable | Default | Purpose | |---|---|---| | `BOOTSTRAP_DIR` | `~/.config/bootstrap` | Config, shell snippets, libs | | `BOOTSTRAP_DATA_DIR` | `~/.local/share/bootstrap` | Binaries, runtimes, opt | | `BOOTSTRAP_STATE_DIR` | `~/.local/state/bootstrap` | Registry, logs, rollback | | `BOOTSTRAP_CACHE_DIR` | `~/.cache/bootstrap` | Download cache, temp dirs | | `BOOTSTRAP_BIN` | `$BOOTSTRAP_DATA_DIR/bin` | Binary executables | | `BOOTSTRAP_OPT` | `$BOOTSTRAP_DATA_DIR/opt` | Multi-file installs | | `BOOTSTRAP_RUNTIMES` | `$BOOTSTRAP_DATA_DIR/runtimes` | Managed tool homes | ## Clean Removal After this migration, full removal becomes: ```bash rm -rf ~/.local/share/bootstrap # All binaries and runtimes rm -rf ~/.config/bootstrap # Config and shell integration rm -rf ~/.local/state/bootstrap # State and registry rm -rf ~/.cache/bootstrap # Cache sed -i '/bootstrap/d' ~/.bashrc # Remove shell hook ```
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sortedcord/bootstrap#18