# Dotfiles Roadmap

This document is the planning source for the dotfiles installer. It separates
agreed direction from open questions so implementation does not get ahead of
decisions.

## Goals

- Install required software for macOS and Linux.
- Link dotfiles into the user's home directory.
- Verify the current machine after installation.
- Verify Linux behavior in Docker.
- Keep software installation explicit and inspectable per tool.

## Principles

- `bootstrap` links dotfiles only; it should not install system software.
- `make deps` installs or upgrades software.
- `make install` links dotfiles into the real `HOME`.
- `make doctor` verifies the current machine without modifying it.
- Each dependency has its own installer strategy in `deps.toml`.
- Prefer official upstream installation methods for user tools.
- Allow system package managers for bootstrap/system tools such as `git`,
  `make`, `curl`, `tar`, `unzip`, and certificates.
- Do not silently fall back to old distro packages for tools where a fresh
  upstream version matters.
- Linux user-level binaries should install into `~/.local/bin`.
- Unsupported installers should fail clearly instead of doing a surprising
  install.
- Default dependency target is `latest` until reproducibility work is added.
- `make deps` installs missing tools and upgrades existing tools to latest.
- `make deps-check` reports installed versions only.
- `make bootstrap` runs `deps`, `install`, and `doctor`.
- Docker verifies GUI tools by installation and version output only; it does
  not attempt to launch GUI applications.
- Uninstall and cleanup commands are deferred until an install record or lock
  file exists.
- `make deps` is lock-aware for downloaded tools and fails when the current
  platform has no matching `deps.lock` entry for those tools.

## Confirmed Decisions

- Dependency version policy:
  - v0.2-v0.4 use `target=latest`.
  - v0.5 adds pinned versions, checksums, and a lock file.
- Linux support:
  - First target is Ubuntu/Debian only.
- Linux install paths:
  - Official release binaries install into `~/.local/bin`.
  - System/bootstrap tools may use apt.
- macOS install strategy:
  - Prefer Homebrew for CLI formulae.
  - Prefer Homebrew casks for GUI apps.
  - Use system `git`; do not force Homebrew Git.
  - Use system `make`; do not force Homebrew GNU Make.
  - Use Homebrew for tmux, fish, Neovim, Starship, yazi, zoxide, eza, and lazygit.
  - Use a cask for Ghostty.
- Linux tool strategy:
  - `git`: apt
  - `make`: apt
  - `tmux`: apt
  - `fish`: official Fish Ubuntu/Debian repository
  - `ghostty`: community-maintained Ubuntu package via `ghostty-ubuntu`
  - `zoxide`: official install script
- Command boundaries:
  - `make deps`: install or upgrade software only.
  - `make install`: link dotfiles only.
  - `make doctor`: verify current machine only.
  - `make bootstrap`: run `deps`, `install`, then `doctor`.
- Non-interactive install modes:
  - `./bootstrap` defaults to interactive.
  - `make install` defaults to interactive.
  - `make bootstrap` defaults to `INSTALL_MODE=backup`.
  - Explicit modes should include `backup`, `overwrite`, and `skip`.
  - CLI flags are `--backup`, `--overwrite`, and `--skip`.
  - `make install` uses `INSTALL_MODE` with the same values.
- `deps-plan` output fields:
  - `name`
  - `command`
  - `target`
  - `platform`
  - `installer`
  - `source`
  - `install_path`
  - `status`
  - `action`
  - `current`
- `deps-plan` column order:
  - `name`
  - `command`
  - `target`
  - `platform`
  - `installer`
  - `source`
  - `install_path`
  - `status`
  - `action`
  - `current`
- `deps-plan` action/current semantics:
  - `name` is the manifest dependency name.
  - `command` is the executable name used for version checks.
  - `target` is the manifest target string, unchanged.
  - `action=install` for missing tools.
  - `action=upgrade` for installed tools that will be upgraded to `latest`.
  - `action=skip` for entries excluded by `--only` or not applicable on the current platform.
  - `platform` is the current runtime platform label, `mac` or `linux`.
  - `installer` is the manifest installer token, unchanged.
  - `current` shows the full installed version string or `missing`.
  - `source` shows the full upstream URL.
  - `skip` rows remain visible in the plan output.
- `deps-plan` rendering:
  - Stable plain-text table or tab-separated output.
  - Column order is fixed to match the field list above.
  - No JSON in v0.2.
- Safety and automation:
  - Checksum verification is deferred to v0.5.
  - CI is deferred to v0.6.

## Current State

- Dotfile linking supports:
  - `~/.tmux.conf`
  - `~/.config/fish`
  - `~/.config/nvim`
  - `~/.config/ghostty`
- `make check` validates script syntax and a temporary-home install.
- `make doctor` validates the current machine and real symlinks.
- `deps.toml` declares dependencies per tool.
- `deps.lock` records frozen dependency state for downloaded tools only.
- Lock entries are selected by both platform and architecture.
- `scripts/install-deps` supports `list`, `check`, `plan`, partial `install`,
  and lock-aware installs.
- `scripts/update-lock.py` refreshes the current platform section in `deps.lock`.
- `make docker-deps-update-lock` refreshes the Linux lock section in Ubuntu.
- `make docker-deps-update-lock-amd64` refreshes the Linux/amd64 lock section.
- Lock refresh runs with `LOCK_STRICT=0` so a missing current-platform lock
  section does not block generating the new entry.
- macOS dependency verification currently covers:
  - `nvim` via Homebrew
  - `ghostty` via Homebrew cask
- Docker dependency verification currently covers:
  - `git` via apt
  - `make` via apt
  - `fish` via Fish Launchpad PPA
  - `ghostty` via community-maintained Ubuntu package
  - `nvim` via Homebrew on macOS and official release tarball on Linux
  - `starship` via Homebrew on macOS and official install script on Linux
  - `yazi` via Homebrew on macOS and official release archive on Linux
  - `zoxide` via Homebrew on macOS and official install script on Linux
  - `eza` via Homebrew on macOS and official release archive on Linux
  - `lazygit` via Homebrew on macOS and official release archive on Linux

## Version Plan

### v0.1: Installer and Verification Skeleton

Status: done.

Scope:

- Make targets:
  - `help`
  - `check`
  - `doctor`
  - `install`
  - `deps-list`
  - `deps-check`
  - `docker-check`
- Cross-platform `bootstrap` path handling.
- Dotfile symlink installation.
- Dependency manifest.
- Dependency script with `list` and `check`.

### v0.2: Linux User Tool Installers

Status: done.

Done:

- `git`: apt
- `make`: apt
- `tmux`: apt
- `fish`: official repository
- `ghostty`: community Ubuntu package
- `nvim`: Homebrew
- `starship`: Homebrew
- `yazi`: Homebrew
- `eza`: Homebrew
- `lazygit`: Homebrew
- `zoxide`: Homebrew

Remaining:

### v0.3: macOS Install and Upgrade

Status: done.

Done:

- Use Homebrew for tmux, fish, Neovim, Starship, yazi, zoxide, eza, and lazygit.
- Use a cask for Ghostty.
- Use system `git`.
- Use system `make`.

Proposed scope:

- Use Homebrew for formulae where acceptable.
- Use casks for GUI apps where acceptable.
- Upgrade existing packages before checking versions.
- Verify `make deps` on a real macOS machine.

### v0.5: Reproducibility and Safety

Status: done.

Done:

- Root `deps.toml` replaces the TSV manifest.
- Root `deps.lock` stores frozen dependency state.
- `make deps-update-lock` refreshes the current platform section.
- `make docker-deps-update-lock` refreshes the Linux section from Ubuntu.
- `make docker-deps-update-lock-amd64` refreshes the Linux/amd64 section from
  Ubuntu/amd64.
- `scripts/update-lock.py` generates TOML lock output.
- `make deps` is lock-aware for downloaded tools and validates against
  `deps.lock` during install.
- Pinned targets are supported for lock generation and install-time source
  selection.
- Downloaded artifacts are verified with SHA256 before installation.

### v0.6: CI

Status: done.

Done:

- GitHub Actions workflow runs `make check` and the Python test suite on
  macOS and Ubuntu.
- GitHub Actions workflow runs the Linux Docker dependency smoke test on
  Ubuntu.
- GitHub Actions workflow runs `make lint-shell` with `shellcheck` on Ubuntu.
- GitHub Actions workflow runs `make check-shellfmt` with `shfmt` on Ubuntu.
- `make lint-shell` runs `shellcheck` across repository-owned executable shell
  scripts.
- `make fmt-shell` formats repository-owned executable shell scripts with
  `shfmt`.

## Open Decisions

- None.
