Skip to content

fix: clone all external zsh plugins on remote-config installs#121

Merged
fullstackjam merged 2 commits into
mainfrom
claude/beautiful-archimedes-AOlO3
Jun 2, 2026
Merged

fix: clone all external zsh plugins on remote-config installs#121
fullstackjam merged 2 commits into
mainfrom
claude/beautiful-archimedes-AOlO3

Conversation

@fullstackjam
Copy link
Copy Markdown
Collaborator

Summary

Fixes two bugs that left oh-my-zsh logging plugin '...' not found at every
shell startup for configs that list external plugins.

  • Catalog was incomplete. data/zsh-plugins.yaml was missing
    fast-syntax-highlighting and zsh-autocomplete. cloneExternalPlugins
    treats catalog misses as built-in/unknown and skips the git clone, so these
    two were never cloned. Added both with their canonical maintained repos
    (zdharma-continuum/fast-syntax-highlighting, marlonrichert/zsh-autocomplete).

  • Remote-config installs dropped theme/plugins. planFromRemoteConfig
    set plan.InstallOhMyZsh from rc.Shell.OhMyZsh but ignored
    rc.Shell.Theme and rc.Shell.Plugins. As a result openboot install <slug>
    took the bare "fresh install" branch in applyShell — installing Oh-My-Zsh
    but never writing plugins=() nor cloning any external plugins, even the ones
    already in the catalog. The snapshot/state path (PlanFromSnapshot) already
    copied all three fields; this brings the remote-config path in line.

Together these mean installing a config that lists external plugins now clones
them into $ZSH_CUSTOM/plugins instead of leaving zsh to warn on every login.

Test plan

  • go vet ./internal/...
  • go test ./internal/installer/... ./internal/config/... ./internal/archtest/...
  • New regression test: catalog contains the popular external plugins
    (TestZshPluginRepoURL_PopularExternalPlugins)
  • New regression test: remote-config plan carries theme + plugins
    (TestPlan_RemoteConfig_ShellThemeAndPluginsRestored)

https://claude.ai/code/session_019iBMJXrKC2FXQ4hWay8Lds


Generated by Claude Code

claude added 2 commits June 2, 2026 05:12
These two external oh-my-zsh plugins were referenced by real user configs
but absent from data/zsh-plugins.yaml. cloneExternalPlugins treats catalog
misses as built-in/unknown and skips the git clone, so oh-my-zsh logged
"plugin 'fast-syntax-highlighting' not found" (and likewise for
zsh-autocomplete) at shell startup. Add both with their canonical maintained
repos and a regression test covering the popular external plugins.
planFromRemoteConfig set plan.InstallOhMyZsh from rc.Shell.OhMyZsh but
dropped rc.Shell.Theme and rc.Shell.Plugins. As a result `openboot install
<slug>` (and any remote-config install) took the bare "fresh install" branch
in applyShell — installing Oh-My-Zsh but never writing plugins=() nor
git-cloning external plugins. The snapshot/state path (PlanFromSnapshot)
already copies all three fields; this brings the remote-config path in line.

Combined with the catalog additions, installing a config that lists external
plugins now clones them into $ZSH_CUSTOM/plugins instead of leaving zsh to
log "plugin '...' not found" at every shell startup.
@github-actions github-actions Bot added installer Package installation logic tests Tests only labels Jun 2, 2026
@fullstackjam fullstackjam merged commit 9549bff into main Jun 2, 2026
12 checks passed
@fullstackjam fullstackjam deleted the claude/beautiful-archimedes-AOlO3 branch June 2, 2026 05:37
fullstackjam added a commit that referenced this pull request Jun 2, 2026
* fix: clone external zsh plugins referenced by dotfiles .zshrc

When a remote config carries no shell block (rc.Shell == nil) but does set a
dotfiles_repo, the shell setup comes entirely from the stowed .zshrc. Its
plugins=() list — e.g. zsh-autosuggestions, fast-syntax-highlighting,
zsh-autocomplete — never flowed through RestoreFromSnapshot, so the external
plugins it names were never git-cloned into $ZSH_CUSTOM/plugins. oh-my-zsh
then logged "plugin '...' not found" on every shell startup.

Add shell.CloneExternalPluginsFromZshrc: after dotfiles are linked, read the
effective ~/.zshrc, extract plugins=(), and clone any catalog (external)
plugins not already present. Built-in/unknown names are left untouched and a
failed clone stays non-fatal, matching cloneExternalPlugins. No-op when
oh-my-zsh isn't installed or .zshrc is absent, and dry-run safe.

This is the path `openboot install <slug>` takes for configs like
fullstackjam, where #121's plan-level fix could not help because there was no
shell block to carry through.

* fix: guard plugin name against path traversal before clone

gosec G703 flagged cloneExternalPlugins now that plugin names can originate
from a user-authored .zshrc (via CloneExternalPluginsFromZshrc) and flow into
filepath.Join. Add an explicit path-segment guard rejecting names that aren't
a plain single segment, and annotate the os.Stat with a justified nolint. A
name only reaches here after matching the curated catalog, so this guard only
ever rejects malicious input — it's defense in depth, not a behavior change.

* fix: treat unreadable .zshrc as non-fatal in plugin clone

An unreadable .zshrc now warns and returns nil instead of aborting the
dotfiles step. By the time CloneExternalPluginsFromZshrc runs the dotfiles
are already cloned and linked, and plugin setup is best-effort everywhere
else (cloneExternalPlugins warns and continues on a failed clone), so a
marginal read error should not fail the whole step. Add a test covering the
non-NotExist read-error path.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

installer Package installation logic tests Tests only

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants