os-user-shell.ts:33 calls scripts/setup/starship.toml "the prompt config the
owner's own install uses — one file, both audiences". It was not: the original
machine script wrote a DIFFERENT config inline, so the owner got a prompt that
only disabled language modules while every member got the repo file with its
custom format. Two prompts, one comment claiming otherwise.
This deploys the same file the platform does, which makes the comment true.
Verified with cmp against a fresh account: byte-identical to what a member gets.
Nothing overwrites any more:
.config/starship.toml and .tmux.conf go through install_config, so they are
written when absent, skipped when identical, and KEPT when they differ — with
the cp printed, so taking ours stays the reader's decision. On this host that
is what happens: the existing config differs and is left alone.
The starship line in .zshrc is marker-wrapped by append_once. Verified over
three consecutive runs: one block, not three. The original appended it
unguarded every time.
The login shell is now its own question. Having zsh on the machine and being
handed it at every login are different decisions, and `chsh` made the second one
silently. It also adds the shell to /etc/shells first, which chsh requires.
.tmux.conf lives here now, with the rest of the dotfiles, rather than in user
creation where the original put it only because that is where $USER_HOME first
exists.
One bug found by running it: install_config returns 2 for "kept yours", which is
an outcome rather than a failure — but still non-zero, so calling it as a plain
command under `set -e` ended the run before `case $?` could read it. Captured with
&& / || at both call sites, and the contract is documented where the function is
defined so the next caller does not repeat it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Detects first, then asks. If there is a name and email configured it shows them
and offers to change them, defaulting to no — the common reason to re-run this
script is everything except this. If there is nothing configured it just asks.
Default branch is master rather than main, unless the answer says otherwise.
Three problems in the original, beyond running unconditionally:
prompt_value accepts an empty answer, so pressing Enter wrote `user.name = ""`.
An empty name is worse than none: unset makes git refuse to commit and say why,
empty makes it commit with a blank author and never mention it. ask_required
re-asks instead.
core.editor was set to nvim four sections before Neovim is installed, so
anything invoking the editor in between failed. Dropped for now rather than
moved — it is a preference, and worth deciding separately.
Nothing checked whether the writes worked.
That last one was not theoretical. Testing against a throwaway account, all three
writes failed and the section still printed "OK: written". `git config --global`
needs no repository, but git stats the working directory on the way, looking for
one — and the script runs from under the invoking user's home, which is 0750, so
the target account cannot stat it:
fatal: failed to stat '<cwd>': Permission denied
The wrappers now run in a subshell from /, which every account can stat, and the
caller checks the exit status and reads the value back before claiming success.
Also recorded where it is written: docs/agent-git-identity.md says every agent
Officer runs commits as the owner, because it runs as the owner. This is not only
the human's identity, it is what git log attributes agent commits to — which is
worth knowing while choosing it.
Verified both paths: this host's existing identity is shown and left alone by
default, and a fresh account gets a correct .gitconfig owned by that account with
defaultBranch master.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>