fix: clone external zsh plugins referenced by dotfiles .zshrc#122
Merged
Conversation
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.
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.
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.
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
Fixes oh-my-zsh logging
plugin '...' not foundat shell startup afteropenboot install <slug>for configs whose shell setup comes entirely fromdotfiles.
Root cause: when a remote config carries no
shellblock (rc.Shell == nil) but does set adotfiles_repo, the theme/plugins live only in thedotfiles' stowed
.zshrc. OpenBoot's plugin-cloning only ever ran offrc.Shell.Plugins, so the external plugins named in the dotfiles.zshrc(
zsh-autosuggestions,zsh-syntax-highlighting,fast-syntax-highlighting,zsh-autocomplete, …) were never git-cloned into$ZSH_CUSTOM/plugins. PR#121's plan-level fix could not help here — there was no shell block to carry
through.
Fix: add
shell.CloneExternalPluginsFromZshrcand call it from thedotfiles step after linking. It reads the effective
~/.zshrc, parsesplugins=(), and clones any catalog (external) plugins not already present.Built-in/unknown names are left untouched and a failed clone stays non-fatal,
matching the existing
cloneExternalPlugins. It is a no-op when oh-my-zshisn't installed or
.zshrcis absent, and is dry-run safe.Test plan
go vet ./internal/shell/... ./internal/installer/...go test ./internal/shell/... ./internal/installer/... ./internal/archtest/....zshrc, skipsbuilt-ins, no-op without OMZ / without
.zshrc, dry-run safeopenboot install fullstackjam→ new shell tab has no"plugin not found" warnings;
~/.oh-my-zsh/custom/pluginsis populated(pending user confirmation)
https://claude.ai/code/session_019iBMJXrKC2FXQ4hWay8Lds
Generated by Claude Code