diff --git a/DISTRIBUTION-PLAN.md b/DISTRIBUTION-PLAN.md deleted file mode 100644 index bbb8d9d..0000000 --- a/DISTRIBUTION-PLAN.md +++ /dev/null @@ -1,222 +0,0 @@ -# Distribution Plan for `move` - -**Status:** Tabled 2026-06-15. Revisit after the initial Gitea push lands -and the repo is publicly reachable at . - -This document captures the analysis and decisions for distributing the -`move` CLI as an end-user-friendly tool, so we can resume without redoing -the discussion. - ---- - -## Decisions locked in - -| Decision | Choice | -| -------- | ------ | -| Primary hosting | Self-hosted Gitea (`https://gitea.cahlen.com/nokeo08/Move`) | -| Default branch | `master` | -| Audience | Anyone who finds the repo (broader public-ish) | -| Effort budget for now | Smallest viable curl-able `install.sh` | -| Bun handling | Fail with a clear message when missing (no auto-install) | -| Reinstall behavior | Idempotent via a version-marker file; `MOVE_FORCE=1` overrides | -| Install location | `~/.local/bin` + `~/.local/share/move` (XDG, no sudo), env-overridable | -| `move` shim | Bash wrapper script, not symlink | -| PATH rc files | Never modified; print instructions if PATH isn't right | -| Uninstaller | In scope; same `curl ... \| sh` pattern | -| npm publishing | Out of scope | -| Standalone binaries (`bun build --compile`) | Future work; depends on nut.js native-bundling testing | -| Homebrew tap | Future work; cheap once releases exist | - ---- - -## Distribution-option survey (from the discussion) - -Four options were weighed: - -1. **Compiled standalone binary** (`bun build --compile`). Best UX (single - binary, no Bun needed) but needs per-platform builds, a release - pipeline, code signing on macOS, and depends on nut.js's prebuilt native - `.node` files bundling correctly under `--compile` — **unverified**. -2. **Curl-piped installer** — **chosen**. Single command, no clone, - source-and-Bun model. Conventions used by bun, deno, rustup, nvm. - Slight cold-start cost vs. compiled binary; tradeoff accepted. -3. **Package-manager distribution** (`bun add -g`, brew). `move` is taken - on npm; brew is macOS-centric; both add publishing overhead. Out of - scope for first cut. -4. **Status quo** (clone + `./install.sh` + `bun link`). Developer flow - only; will be renamed to `dev-setup.sh`. - ---- - -## Target end-user UX - -```sh -curl -fsSL https://gitea.cahlen.com/nokeo08/Move/raw/branch/master/install.sh | sh -move --help -``` - -One command. No clone. No `bun link`. No `chmod`. After this the user has -a global `move` on their PATH. - ---- - -## `install.sh` design (end-user, curl-able) - -- **Shebang:** `#!/usr/bin/env sh` (POSIX). -- **Strict mode:** `set -eu`. Trap on errors with a clear - "install failed at " message. - -### Top-to-bottom behavior - -1. **Platform detection:** - - `uname -s` → `Darwin` / `Linux` / else → "unsupported OS" + exit 1. - - `uname -m` → `arm64` / `x86_64` (mapped to `x64`) / else → - "unsupported arch" + exit 1. - - nut.js supports darwin-arm64/x64, linux-x64, win32-x64. WSL users - fall under Linux. -2. **Bun check:** - - `command -v bun` present → continue. - - Absent → print - `Error: bun is not installed. Install from https://bun.sh (e.g. 'curl -fsSL https://bun.sh/install | bash'), then re-run.` - → exit 1. -3. **Resolve paths:** - - `INSTALL_DIR=${MOVE_PREFIX:-$HOME/.local/share/move}` - - `BIN_DIR=${MOVE_BIN_DIR:-$HOME/.local/bin}` - - `mkdir -p` both. -4. **Resolve version:** - - `VERSION=${MOVE_VERSION:-master}`. -5. **Idempotence check:** - - If `$INSTALL_DIR/.installed-version` exists AND its content equals - `$VERSION` AND `${MOVE_FORCE:-0}` is not `1`: - - Print `move already installed at $BIN_DIR/move. Set MOVE_FORCE=1 to reinstall, or pass a different MOVE_VERSION.` - - Exit 0. -6. **Clean install dir:** `rm -rf "$INSTALL_DIR"/*` (preserving the dir - itself so user-set permissions on it are kept). -7. **Download source:** - - `TARBALL="https://gitea.cahlen.com/nokeo08/Move/archive/${VERSION}.tar.gz"` - - `curl -fsSL "$TARBALL" -o "$TMP"` (mktemp) → on failure, fail - loudly with the offending URL. - - `tar -xzf "$TMP" -C "$INSTALL_DIR" --strip-components=1` - - `rm -f "$TMP"` -8. **Install deps:** `cd "$INSTALL_DIR" && bun install --production`. - `--production` skips devDependencies (TypeScript, @types/bun); saves - tens of MB and seconds per install. -9. **Drop the wrapper:** - ```sh - cat > "$BIN_DIR/move" < "$INSTALL_DIR/.installed-version"`. -11. **PATH sanity check:** - - If `$BIN_DIR` is not on `$PATH`, print: - `Warning: $BIN_DIR is not on your PATH. Add this to your shell rc: export PATH="$BIN_DIR:$PATH"` - - Do **not** mutate the user's rc files — that breaks the "clean - uninstall" contract. -12. **macOS Accessibility hint** (carried over from current `install.sh`). -13. **Final message:** `Installed move $VERSION at $BIN_DIR/move. Run 'move --help' to get started.` - -### Env vars - -| Var | Default | Purpose | -| --- | ------- | ------- | -| `MOVE_VERSION` | `master` | Branch or tag to fetch from Gitea. | -| `MOVE_PREFIX` | `$HOME/.local/share/move` | Source install location. | -| `MOVE_BIN_DIR` | `$HOME/.local/bin` | Wrapper install location. | -| `MOVE_FORCE` | unset | Force reinstall even if version marker matches. | - ---- - -## `uninstall.sh` design - -```sh -curl -fsSL https://gitea.cahlen.com/nokeo08/Move/raw/branch/master/uninstall.sh | sh -``` - -**Behavior:** - -1. `set -eu`. -2. Respect `MOVE_PREFIX` and `MOVE_BIN_DIR` env vars (same defaults as - install). -3. `rm -f "$BIN_DIR/move"`. -4. `rm -rf "$INSTALL_DIR"`. -5. Print `Uninstalled. (Bun was not touched.)`. - -Does **not** uninstall Bun — that's the user's runtime, not ours. - ---- - -## `dev-setup.sh` design (renamed from current `install.sh`) - -The current `install.sh` is appropriate for contributors but inappropriate -as the end-user installer. Rename to `dev-setup.sh`. Content stays nearly -identical: - -- Verify Bun is installed (hard-error if missing). -- `bun install`. -- macOS Accessibility hint. -- Trailing message updated to: - `Done. Dev workflow: 'bun run start' to run, or 'bun link' to install the global 'move' command. End-user installer is install.sh.` - ---- - -## README changes (when we resume) - -- `## Install` section becomes the curl one-liner targeting `master`, plus - a short note about env-var overrides and a pointer to uninstall. -- `## Run` section collapses to `move` / `move --help` for the global - install path. -- New `## Uninstall` section with the curl-pipe uninstall command. -- New `## For contributors` section absorbing the existing - `bun run start` / `bun run src/move.ts` / `bun link` examples; points - at `dev-setup.sh`. -- `## Files` table updates: add `install.sh` (end-user, curl-able), - `uninstall.sh` (end-user, curl-able), `dev-setup.sh` (contributor - bootstrap). - ---- - -## Verification plan (when we resume) - -1. `sh -n install.sh` and `sh -n uninstall.sh` — POSIX syntax check. -2. Local end-to-end with overridden paths: - ```sh - MOVE_PREFIX=/tmp/movetest MOVE_BIN_DIR=/tmp/movetest/bin ./install.sh - /tmp/movetest/bin/move --help - ./install.sh # second run: already-installed message - MOVE_FORCE=1 ./install.sh # forced reinstall - ``` -3. Uninstall against the test prefix; confirm nothing left under it. -4. Re-run existing acceptance tests (`tsc`, `--help`, `--version`, - `--bogus`) — should be unaffected; no source changes in this milestone. -5. After committing/pushing, end-to-end against the actual Gitea URL. - ---- - -## Caveat: Gitea archive URL shape - -The plan assumes -`https://gitea.cahlen.com/nokeo08/Move/archive/.tar.gz` returns a -tarball whose top-level directory contains the project files (peeled by -`--strip-components=1`). This is the standard Gitea archive format, but -if your Gitea version produces a different layout the installer will need -a small tweak. The installer should error loudly with the offending URL -if extraction fails. - ---- - -## Open future work (out of scope for the resume session) - -- Switch `MOVE_VERSION` default from `master` to "latest tag" via the - Gitea API (`/api/v1/repos/nokeo08/Move/tags`) once tagged releases are - routine. -- Investigate `bun build --compile` + nut.js native-binary bundling for - true zero-Bun installs. If it works, layer prebuilt binaries onto the - curl installer so users without Bun also get one-command installs. -- Homebrew tap for macOS users (cheap once a release pipeline exists). -- Possible: PowerShell installer (`install.ps1`) for native Windows users - without WSL.