xydacshell upgrade path: profiles, x command, safe installer#1
Merged
Conversation
added 12 commits
April 12, 2026 09:02
- Split shell config into profiles (classic + modern); root zshrc.file and
vimrc.file become dispatchers that read ~/.xydacshell/profile. Existing
~/.zshrc symlinks keep working with no action needed; missing profile
defaults to classic, which loads the original setup unchanged.
- Rewrite install.sh as idempotent, profile-aware, with --dry-run, --force,
and --profile flags. New backups go to backup/<timestamp>/ so the legacy
pre-install backup/.zshrc and backup/.vimrc stay untouched. The installer
refuses to run with uncommitted local edits, and hash-verifies that
zshrc.custom and vimrc.custom are not modified during a run.
- Add modern profile: starship config echoing the classic two-line prompt,
a small nvim init.lua keeping the backtick leader for muscle memory, and
a zshrc that uses fzf/zoxide/eza/bat when present with graceful fallbacks.
- Fix broken %{...%} escape sequences in materialshell-electro.zsh-theme
(lines 68-73) that leaked raw escapes on dirty repos.
- Add CI: shellcheck, zsh -n syntax check, nvim headless load-check.
- Rewrite README, add CHANGELOG.
All five submodules are retained; classic still needs them. Plan for a
future major cut is captured in CHANGELOG.
Replace the static 'here are install hints' block with OS and package-manager detection plus per-tool install prompts. Supports brew/apt/dnf/pacman/apk; uses official curl installers for tools the pm does not ship (starship, zoxide); flags eza as cargo-install on apt. --force auto-accepts; --dry-run previews without running. Missing tools continue to degrade gracefully in the modern zshrc.
lsd is more broadly packaged (in apt since Debian 11; no cargo fallback needed), so it drops cleanly into every supported package manager. Updates the installer tool list, zshrc aliases (ls/ll/la/tree), README and CHANGELOG.
Introduces bin/xydacshell as a subcommand dispatcher for day-to-day
operations. Both profile zshrcs prepend $XYDACSHELL_HOME/bin to PATH
so 'xydacshell <verb>' works after install.
Subcommands:
- install forwards to install.sh (unchanged)
- update git pull + submodule sync + reinstall current profile
- switch shorthand for install --profile <profile>
- doctor diagnostic: profile, symlinks, custom file sizes, PM,
tool presence, latest backup, git state
- rollback restore from backup/<timestamp>/; --stamp picks one
- storage disk-usage report; covers local filesystems, $HOME
top dirs, package-manager caches (brew, npm, pnpm,
cargo, pip, uv), docker, trash; --clean prompts to
prune each cache with its native command
- uninstall remove our symlinks, restore legacy pre-install
backup/.zshrc /.vimrc, do not delete the repo itself
Also: add ncdu, dust, duf to the modern-profile installer tool list
(with cargo-install-du-dust fallback on apt/apk). Add LICENSE file
(MIT, matching what README already declared). Move xs_prompt_yn from
modern-tools.sh to util.sh so every command can use it.
Primary command is now 'x' (short, fast to type) with 'xydacshell' kept as a symlink alias for discoverability, tab completion, and existing muscle memory. Both work identically. During install, check PATH for an existing 'x' that isn't ours and print a clear warning listing the conflicting path(s), with a reminder that shell aliases (which override PATH in interactive shells) won't be visible from install.sh — the user needs to run 'alias | grep ^x=' themselves. If the user wants to keep their existing 'x', the 'xydacshell' symlink still works.
After printing the diagnostic, doctor now checks: is the user on the classic profile, is the repo clean, and is stdin a tty? If all three, it offers to preview (dry-run) and then apply a switch to the modern profile. Declining leaves everything untouched. This turns 'x doctor' into the friendly post-git-pull entry point for existing users. The upgrade flow becomes: cd ~/.xydacshell git stash && git pull --rebase && git submodule update --init --recursive && git stash pop exec zsh # new shell picks up the x command on PATH x doctor # report + optionally switch to modern Classic users who say no never see a change. Their shell remains byte-for-byte what it was. Also: --no-prompt / --report flag for doctor to skip the offer (useful for scripts and CI).
Drop the submodule update step from the README upgrade instructions. No submodule refs change in this PR, so it would be a no-op for the first upgrade. For subsequent pulls that may bump submodules, 'x update' handles it in one step (and install.sh itself does submodule update for the classic profile).
vhs/demo.tape scripts a ~25s showcase: 'x' help, 'x storage --top 5' (the real win), 'x doctor --no-prompt'. Renders to vhs/demo.gif. Rendering requires 'brew install vhs' (or equivalent on other platforms). Chrome sandbox restrictions in some Linux environments prevent vhs from rendering there; run it on macOS or a box with working Chrome sandbox. README embeds vhs/demo.gif so the gif appears at top once committed after the first render.
Two changes:
1. Add '# shellcheck shell=bash' directive to profiles/{classic,modern}/zshrc.
These files are sourced by the dispatcher (no shebang); shellcheck
refused to lint them without a shell hint (SC2148 error).
2. Set severity=error on the shellcheck action so the pipeline doesn't
fail on stylistic notes/warnings — unused ZSH_THEME/plugins/SAVEHIST
variables (oh-my-zsh and zsh read them implicitly, but shellcheck
can't see that), SC1091 for sourced files at runtime paths, SC2086
quoting notes inside zsh idioms, etc.
Real errors still fail the build.
~25s showcase: 'x' help → 'x storage --top 5' → 'x doctor --no-prompt'. Rendered with asciinema + agg on Linux (vhs failed here due to Chrome sandbox restrictions). vhs/demo.tape stays as the canonical script for future rerenders; use 'brew install vhs && vhs vhs/demo.tape' on macOS to rebuild.
Use 'git pull --rebase --autostash' (built in since git 2.9) so the upgrade flow compresses to one line and works whether or not the user has local changes: cd ~/.xydacshell && git pull --rebase --autostash && git submodule update --init --recursive && exec zsh Then 'x doctor' in the new shell. Removed the multi-step stash / pull / pop recipe and the half-written upgrade.sh helper.
The user-facing help and doctor output no longer lead with the word 'xydacshell'. The header reads 'x — your terminal setup, managed.', doctor's banner is 'x doctor', and the uninstall line refers to 'installation' instead of 'xydacshell'. A small footer line retains '(also available as xydacshell.)' for discoverability. The repo and project are still called xydacshell; only the interactive command-line surface favors 'x'. The xydacshell symlink still works. Re-renders vhs/demo.gif with the updated help output.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Turns xydacshell into a maintained tool without breaking any existing classic-profile user. Adds a
modernprofile (starship + nvim + modern CLI tools), introduces the shortxcommand (subcommands:install,update,switch,doctor,rollback,storage,uninstall), and rewrites the installer to be idempotent, safety-rail-guarded, and interactive where it matters.Safety guarantees for existing users
~/.zshrc -> ~/.xydacshell/zshrc.filesymlinks keep working with zero action required. Missing profile file → dispatcher defaults toclassic, which loads the original oh-my-zsh + materialshell-electro setup byte-for-byte.~/.xydacshell/zshrc.customandvimrc.customare hash-verified before and after every install run.backup/.zshrcandbackup/.vimrc(pre-install originals) are never touched. New backups go tobackup/<timestamp>/.--force).%{…%}git-status escape sequences inmaterialshell-electro.zsh-themefixed (lines 68-73 — benefits classic users immediately on next pull).The
xcommandx install [--profile classic|modern] [--dry-run] [--force]x update— git pull + submodule sync + reinstall current profilex switch <classic|modern>— profile flip with dry-run preview + confirmationx doctor [--no-prompt]— diagnostic (profile, symlinks, custom file sizes, PM, tool presence, latest backup, git state). When on classic with clean repo and interactive tty, offers to preview and apply a switch to modern. This makesx doctorthe friendly entry point for existing users aftergit pull.x rollback [--stamp TS]— restore from a timestamped backupx storage [--caches] [--top N] [--clean]— disk-usage report: filesystems (via duf/df), $HOME top dirs (via dust/du), package-manager caches (brew/npm/pnpm/cargo/pip/uv), docker, trash.--cleanprompts per-cache for native cleanup commands.x uninstall— removes our symlinks, restores legacy backups. Does not delete the repo.bin/xis the primary command;bin/xydacshellis a symlink. Both work. Installer warns on PATH conflicts (anotherxalready on PATH or shadowed by a shell alias).Modern profile
init.lua(backtick leader to preserve classic muscle memory; no plugin manager)Interactive tool installer: detects OS + package manager (brew / apt / dnf / pacman / apk), prompts per missing tool with the exact command it will run. Uses the native PM where possible; falls back to official curl installers (starship, zoxide) or
cargo install(dust on apt). Missing tools degrade gracefully.Upgrade story for existing users
Classic users who decline the switch see zero change. Future updates run via
x update.CI
Added GitHub Actions workflow:
shellcheckon all shell scripts,zsh -nsyntax check on all zshrc files,nvim --headlessload-check on the moderninit.lua.Demo
vhs/demo.tapescripts a ~25s showcase:xhelp →x storage --top 5→x doctor --no-prompt. Render locally withvhs vhs/demo.tape(needsbrew install vhs). The renderedvhs/demo.gifis referenced at the top of the README — commit it after first render.Deferred for a follow-up
x cron list | edit | add | remove | history | restore)]in starship second line; add contextual modules: cmd_duration, language detectors, k8s/aws context)curl | bashone-liner that installs Homebrew, git, zsh, clones the repo, and runs install.sh)Test plan
x doctoron classic offers the upgrade;--no-promptskips itx storagereports sane values for brew/npm/cargo/etcx rollbackrestores from the most recent backupx uninstall --dry-runpreviews cleanlyCommits (8)