main
5 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
170db93f35 |
fix: nvim first boot on a fresh box — tree-sitter CLI, no luarocks, guarded local plugin
nvim-treesitter (main) hard-requires the tree-sitter CLI: new manifest row via npm. hererocks failed compiling lua 5.1 (readline headers) for oxocarbon's incidental rockspec: rocks disabled, the colorscheme works without. The ~/code/nvim-ai-assist local plugin gets a cond so boxes without the checkout skip it silently. All three found live, phase 5 VM. |
||
|
|
1ea6b492eb |
fix: dotup — installer, picker and private-tier correctness pass
Installer: - channel order is a dependency graph: `script` now runs before `brew`, so core/brew exists by the time lazygit, omp and herdr are attempted. Those three have no apt package at all and failed on every fresh Linux box. - core/brew and core/node are real script/tarball rows now. apt's nodejs is 18.19 while four npm rows declare node>=20; npm only warns on a failed engines check, so the install "succeeded" and `pi` then died at parse time. - apt_known asks `apt-cache policy` for an installation candidate rather than `apt-cache show` for existence: docker-ce exists in the cache with `Candidate: (none)` and exits 0, which kept it in the batch and made apt refuse all thirty packages at once. - failures are reported by manifest key, not by install argument, so the name in the summary is one you can type at the picker or pass to `dotup explain`. - flatpak installs the tool, adds the flathub remote, and uses --user, which is the only scope that works without a session bus. - gh: deb assets fill %a and %v, because a distro-targeted deb names the release as well as the arch (ghostty-ubuntu). - ensure_bws downloads into a `mktemp -d` instead of fixed /tmp paths. - the endpoint password prompt says so out loud when stty cannot turn echo off, instead of silently leaving the password in the scrollback. - cmd_toggle writes tmp-then-rename, matching cmd_expand. Picker: - DU-C1: comments had been inserted between the continued lines of the fzf invocation. The `\`-newline is stripped first, so the comment's own newline terminated the command — fzf ran with two binds and the lines below it ran as a command named `--bind`, so `dotup pick` returned 1 having drawn a dead picker. The comment now sits above the pipeline. - the header is built with a plain variable: `$'...'` is a bashism and /bin/sh on Ubuntu is dash, the one platform this is written for. - the /dev/tty probe runs BEFORE the defaults preset, so a run in a pipe no longer overwrites the selection with 43 rows before failing to draw. - a completed pick is recorded in $STATE/picked, so "install nothing" survives the next run and a prior `dotup plan` no longer counts as having chosen. - $SEL must be readable and writable before anything draws: every bind is execute-silent, which throws its child's status away. - ensure_fzf resolves system-first, cache-second, as the README promises. - ^t clears the query, so rows pulled in along @needs are on screen. |
||
|
|
400bd9b9f1 |
fix: install bws from the private tier, not the manifest
The previous commit put the bws install on the private/bws-secrets row as a tarball channel. That row can never install anything: selected_packages drops every row flagged `private`, which is the invariant that makes --unattended safe to run. The container proved it — unzip installed, bws did not, and the row still could not deliver on its promise. Nor can it be a safe row: the defaults preset ticks every safe package, so that would put a Bitwarden binary and a 12 MB GitHub download on every throwaway public VM, for a tool those machines have no credential to use. So ensure_bws lives in dotup and is called from cmd_private immediately after the token is written. Nothing installs bws unless something is about to hand it a token, and the manifest keeps its invariant. core/unzip stays a real package with the @needs edge — the release is a .zip and 24.04 minimal has no unzip. |
||
|
|
90bca39396 |
fix: install bws, isolate the private config, keep credentials out of logs
Three defects the private tier could not survive a fresh machine with. bws was never installed. The private/bws-secrets row promised seven API keys and shipped no way to fetch them: dotsecrets shells out to `bws secret get`, and nothing put that binary on the box. Added as a tarball channel with checksum verification, musl rather than gnu so it does not pin a glibc newer than an older LTS carries, plus core/unzip as a real @needs dependency since the release is a .zip and 24.04 minimal has no unzip. The releases API needs filtering by tag prefix: sdk-sm is a monorepo and `latest` usually points at a python SDK, not bws. Both tiers rendered their config to ~/.config/chezmoi/chezmoi.toml, so re-running the public installer overwrote the private config and took its seven promptStringOnce answers with it. Silently -- the templates degrade politely when data is missing, so the symptom was `git commit` not knowing who you are, days later. The private tier now renders to private.toml and the cmp alias carries the matching -c. `run` echoes its argv to stderr, and the private init argv ends in https://user:TOKEN@host -- into scrollback, any `dotup 2>log`, and any agent transcript. Traced through redact_url instead, in both the live and dry-run branches. The clone is also chmod -R go-rwx afterwards: it lands at the caller umask, and .git/config stores that same credential URL. Tests: 90 passing, 9 new covering all three. |
||
|
|
b487b0e855 |
feat: public dotfiles tier — no credential, no identity, one installer
Fresh history. This is the repo a throwaway VM clones anonymously: it brings a
machine to a working baseline and carries nothing that makes it mine.
56 files. 50 land in $HOME, 3 are chezmoi metadata, 2 are repo documentation,
1 is the manifest, and a 15-file test harness stays behind in .tests/.
What did not travel, and why:
encrypted_private_bws-token.age a real credential; age is dropped entirely
.chezmoidata/bws.toml env-var -> secret-id map; belongs with the
tier that can use it
SECRETS.md documentation of the rules, not config
finish-setup.sh.tmpl superseded by dotup
nvim/init.lua.backup dead file
dot_claude/**, dot_codex/**, 120 files of agent config, private tier
dot_pi/**
De-identified rather than dropped:
.gitconfig [user], the GitHub ssh rewrite and both Gitea host rewrites are
identity, not configuration. They move behind an [include] of
~/.config/git/config.local, which the private tier writes. Git
treats a missing include as a no-op, so a public-only machine
reads the file and stops.
.zshrc the two gitea aliases carried a personal domain and a LAN IP.
They move behind a guarded source of ~/.config/zsh/local.zsh,
the sibling of the secrets.zsh seam phase 2 established.
nvim a commented-out LM Studio endpoint naming a LAN address.
ghostty a stale auto-generated header naming an absolute home directory.
Newly captured, never tracked before: ~/.zshenv, ~/.config/gh/config.yml. The
former sourced ~/.cargo/env unguarded, so every zsh on a machine without rustup
printed an error -- the same shape as the unguarded oh-my-zsh source phase 2
fixed. It is guarded now.
.chezmoiexternal.toml grows from one entry to six. oh-my-zsh, powerlevel10k,
zsh-autosuggestions, zsh-ai and tpm were hand-installed and declared nowhere,
which is why `chezmoi init --apply` on a clean box produced a .zshrc that broke
the shell it configures. The theme and both plugins nest under
.oh-my-zsh/custom/, which is what $ZSH_CUSTOM resolves to.
dotup gains an install engine. It resolves each selected package to a channel
(apt, brew, npm, uv, snap, deb, flatpak, tarball, script, builtin) through one
function every consumer reads, probes apt-cache before batching so a name apt
does not know moves to brew instead of failing all thirty, and retries
individually if a batch still fails -- which earned its keep on the first real
container run, where mermaid-cli's puppeteer dependency failed and the other
twelve npm packages installed anyway. --unattended computes safe defaults fresh
from the manifest rather than inheriting a state file, and refuses private and
invasive rows outright even when a stale state file ticks them.
The manifest gains @spec, a second directive kind alongside @needs, carrying the
argument a channel needs but a package name cannot supply -- the scoped npm
name, the flatpak app id, the .deb source. The TSV stays five columns wide.
Three bugs the container runs found, all fixed here:
* `apt install nodejs` gives you node WITHOUT npm on Ubuntu, so all thirteen
npm packages failed on a fresh box. The manifest asks apt for both names.
* A tool installed a moment ago is not on this process's PATH -- uv lands in
~/.local/bin, npm -g honours the ~/.npmrc prefix, linuxbrew is outside a
non-login PATH. Resolved by looking in the places we just wrote to, never by
exporting a modified PATH.
* `A || { B && C; }` is one || list, so when `command -v sudo` failed the list
failed and `set -e` killed dotup at load. On a non-root machine with no
sudo it died before printing anything. There is a regression test.
.zshenv and .p10k.zsh are marked private_. Both are shell code the login shell
executes and both applied at 664, group-writable. Third occurrence of the class
of bug phase 1 found on .pi/agent/auth.json and phase 2 found on .zshrc; the
first one found on purpose rather than by accident.
Verification: 81 assertions, 81/81 on this box and in ubuntu:24.04, ubuntu:22.04
and debian:12. The installer is driven against a directory of fake package
managers that record what they were asked to do and install nothing, so the
engine is exercised end to end without a package landing on the test machine.
`gitleaks detect` over the full history and the working tree: no leaks found,
with no allowlist and no .gitleaks.toml.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|