Repository navigation
Conversation
Port every kept role to a mise conf.d module under modules/<name>/, loaded through ~/.config/mise/conf.d -> ~/.dotfiles/modules and applied with `mise bootstrap`: [bootstrap.packages], [dotfiles] links/copies/merges/blocks, [tools], [bootstrap.files], and bootstrap:<module> tasks. bin/dotfiles is now a small wrapper that installs git+mise, picks the omarchy/cachyos/macos profile, and runs `mise bootstrap --yes`. Removes the Ansible playbook, group_vars, per-role docs, tests that grep YAML, Ubuntu/Fedora/WSL paths, and the dropped roles. CI dry-runs both Linux profiles in an Arch container plus macOS, and runs the module tests.
bootstrap:omarchy caches success via outputs = { auto = true }. Agent and
SSH shells lack HYPRLAND_INSTANCE_SIGNATURE, so a run from there printed
"not in Hyprland" and marked the sources handled without reloading or
validating. Discover the running instance with `hyprctl instances` instead.
herdr/tmux panes that outlive a Hyprland restart keep a dead HYPRLAND_INSTANCE_SIGNATURE, so `hyprctl reload` failed and stopped the later bootstrap tasks. Use the variable only when `hyprctl instances` lists it, else the running instance; name the instance when reload fails.
svelte-language-server needs svelte ^4.2.19, which resolves to 4.2.20. mise refuses it as a trust downgrade: 4.2.20 was published without provenance after 5.0.0 had it. Same svelte-admin publisher and an upstream svelte@4.2.20 tag; 4.2.19 was unattested too. Exclude only that version so a later unattested release still fails.
mise loads a module folder's mise.toml as project config whenever it runs there (bootstrap:devtools, or anyone working in the folder), so node = "lts" overrode Omarchy's global 26.8.2 pin and the task run installed node@24. Declare node only for CachyOS and macOS, which have no Omarchy pin.
The old jj role re-rendered user.email from 1Password on every run. The port only filled an empty value, so a machine that once got the noreply fallback kept it while git used the real address. Set jj to the same email as git (1Password, else the last synced value) when it differs; use noreply only when jj has no email at all.
Deploy modes had been carried over from the Ansible roles as-is. Most copies dated from each role's first version with no recorded reason, and a copy silently overwrites live edits on every run. - Symlink files the app only reads: zsh (per-file links for ~/.config/zsh, so deleted sources lose their links), ghostty, kitty, lsd, lfk, gh-dash, worktrunk, Taskfile, commit_template, omp AGENTS.md, Omarchy keyboard.lua (now in hypr/), and on CachyOS/macOS tmux, neofetch, the btop theme, starship, bat, k9s, bash, bordersrc. - herdr config.toml becomes a merge: its settings screen writes keys in place, which every run reverted. - ~/.npmrc becomes three line edits: the copy deleted npm login tokens on every run. - Copies that remain carry a comment with the reason (app replaces the file, rewrites it on exit, or ignores symlinks), and AGENTS.md states the rules plus a mise hazard: switching a directory symlink to symlink-each with --force-dotfiles writes through the old link and replaces repo files with self-referencing links.
bun 1.4.3 made `bun --check` a full type check, which fails in CI where neither @types/node nor the omp package is installed. On bun 1.4.0 the step only ever caught parse errors, so keep that with `bun build --no-bundle`; the behavioural checks below are unchanged.
Centre the logo with a CI status badge, turn the reference-only and run-twice notes into GitHub callouts, and replace the bootstrap prose with a Mermaid diagram of what `dotfiles` does.
A failed package install stops the whole mise run before dotfiles, tools and tasks. Verified in a clean Arch container: with 1Password in [bootstrap.packages] and unavailable, `mise bootstrap` exited 1 at the packages step and applied nothing else. Install the app and CLI from bootstrap:1password instead (pacman when a repo ships them, as Omarchy does; paru or yay otherwise; the Homebrew casks on macOS, leaving a hand-installed app alone). Every failure only warns. Same container, three cases (no repo, no AUR helper, a failing AUR build): exit 0 with dotfiles and all tasks applied.
TechDufus
commented
Oct 14, 2026
TechDufus
left a comment
Owner
Author
There was a problem hiding this comment.
Review notes (zsh-only scope; pacman + macOS only by design).
Fix before merge
- Homebrew prefix is hardcoded to
/opt/homebrewand breaks Intel Macs (/usr/local). Use$(brew --prefix):bin/dotfiles:67eval "$(/opt/homebrew/bin/brew shellenv)"fails underset -ewhen brew isn't theremodules/zsh/mise.macos.toml:5login_shell = "/opt/homebrew/bin/zsh"modules/clangd/mise.macos.toml:5clangd source/opt/homebrew/opt/llvm/bin/clangd
Docs
- README: note that only omarchy/cachyos/macos are supported now (
bin/dotfiles:36-59) and that Ubuntu/Fedora/etc. Ansible support is recoverable from history. - Migration notes for existing Ansible-managed machines: old links/copies, the
conf.dbackup behavior (bin/dotfiles:89-98), and version-manager cleanup.
Leftovers (suggestions)
modules/bash/bashrc:110still loads the oh-my-bashgoenvplugin.modules/zsh/zsh/paths_vars.zsh:18-20rbenv / Homebrew ruby PATH branch.modules/zsh/p10k.zsh:53nvmprompt segment; consider removing it or swapping in a mise/asdf segment.- Nothing removes
~/.nvm,~/.pyenv,~/.asdf; consider a one-time cleanup task or a README note so they can't shadow mise.
Tests / CI
.github/workflows/mise.ymlonly dry-runs. Consider a job that applies for real and then runs a second time to prove idempotency, plus a zsh smoke test (e.g.zsh -ic 'command -v node').bin/tests/test_dotfiles_requirements.shwas deleted with nothing replacing that coverage.
Verify
- Check
min_version = "2026.10.6"(under[bootstrap.brew]inmodules/base/mise.macos.toml) and the mise features this relies on (mise bootstrap,[dotfiles],[bootstrap.packages],system_packages.managers) against the mise docs.
Optional
mise activate zshis only needed if you want per-folder[env]; shims (paths_vars.zsh:14) are fine otherwise.
mise's brew manager skips every entry on Intel Macs and Homebrew's installer refuses them, so stop early with "unsupported machine (Intel Mac)". Run brew shellenv only when /opt/homebrew/bin/brew exists. test:base runs the real script in a sandbox (env -i, temp HOME and XDG dirs, stub mise/uname/brew) and covers profile detection, the conf.d backup and link, miserc rewrites and the pull rules. DOTFILES_SYSROOT lets it fake /etc/os-release and /usr/share/omarchy. check now runs from home. Inside modules/base, mise also loads that file as a project config whose tasks run from ~, so the nested `mise run 'test:*'` could not find test:base's script.
Dry-runs missed both run-stopping bugs of the migration: the npm trust-policy failure in the tools step and a failed package install. The apply job runs the dotfiles and tools steps for real in an Arch container (cachyos profile) three times. The second run settles permissions on files the first run's merges create; the third must change nothing. Then zsh must find the mise shims, interactive or not. Packages, services and system files stay dry-run only: a stock container has no systemd, AUR helper, multilib or Omarchy repo. go tools need gcc for cgo, and registry lookups get 120s instead of the 20s default. About 3 minutes, in parallel with the arch job.
Other systems stop with "unsupported machine"; the Ansible version, which also covered Ubuntu, Fedora and WSL, is tagged ansible-final. macOS means Apple Silicon, and an existing conf.d is moved aside.
mise manages every runtime now; no goenv or rbenv is installed. The oh-my-bash ansible plugin stays: it only adds aliases for the Ansible CLI, which is still in use.
Replace the 1,669-line wizard config with a hand-written one that looks like Tern's "Tern" preset in other terminals: rounded chips for the directory (…/ plus the last three parts, the last in bold) and the git status, the clock on the right, ❯ on its own line, and earlier prompts collapsed to ❯. Colors are Catppuccin Mocha; each chip's background is its text color at about 14% over the base, as sampled from Tern's preset. Kept: the git counters (⇣⇡ *~+!?), the status, duration, background job, direnv, virtualenv, kubecontext, terraform, aws and context segments with their show-on-command rules, transient prompt and quiet instant prompt. Dropped: os_icon with its CachyOS override, and the dead nvm segment. Inside Tern its own preset still draws the prompt; Tern's "Your p10k config" option would draw these chips with flat edges.
A mise older than the module-folder support loads no module, never reads min_version, and `mise bootstrap` exits 0 having done nothing. The first macOS CI run did exactly that with mise 2026.9.1. Read min_version from modules/base/mise.toml and compare it with `mise --version` field by field before linking anything. On macOS try `brew upgrade mise` once; on Linux stop with the upgrade hint. Never run pacman -Sy here: that is a partial upgrade, and Omarchy blocks it.
The macos job passed while checking nothing. The runner image sets HOMEBREW_NO_AUTO_UPDATE=1, so brew poured a stale mise 2026.9.1, which ignores the module folders. Run brew update first, and in every job check that the base module's check task exists right after linking conf.d. Also move actions/checkout and actions/setup-node to v7 (Node 24); v4 ran on the deprecated Node 20 runtime.
In a terminal, dotfiles now runs mise bootstrap one stage at a time (packages, system, dotfiles, shell, tools, modules) behind a Catppuccin summary. Each stage shows a spinner with the live log line, then its result: counts from mise's JSON when jq is present, fail-soft module warnings, or a box with the log tail when it fails. mise's full output goes to ~/.local/state/dotfiles/last-run.log. It asks for sudo up front, applies the dotfiles a second time when the first pass created files that permission entries need, and runs the login-shell stage on the terminal when chsh will prompt. Piped output, --plain, -v, NO_COLOR and flags the UI does not handle keep the old behaviour: one `mise bootstrap --yes` with mise's output.
color_theme only styles mise's interactive prompts, such as the task picker in `mise run`; it matches the dotfiles summary and the prompt.
A fresh Omarchy ships its own ghostty, kitty and nvim configs, and omp leaves its own files too. mise refuses to replace a real file or directory with a link, so the first run stopped with "refusing to overwrite existing files" until it was forced. Before bootstrapping, ask mise which targets it would refuse (`mise dot apply --dry-run` lists them) and move each one to <path>.pre-dotfiles.<epoch>, as conf.d already is and as the Ansible version kept backups. A dry run only reports them and previews with --force-dotfiles, which writes nothing then. Runs that leave out the dotfiles part move nothing.
The repo config merges into Omarchy's herdr config, which sets prefix = "ctrl+space". The Ansible copy never set a prefix, so herdr's ctrl+b default applied; pin it explicitly. herdr 0.9.1 rejects a prefix array, so ctrl+space cannot be kept alongside.
Mirrors the Hammerspoon GrokBot binding (summon = 'G'). Matches the grok-bot window class and launches /usr/bin/grok-bot.
Omarchy's ~/.local/bin wrappers for codex, claude, omp and opencode
run `mise use -g`. A second global declaration in conf.d made omp and
codex fail ("declared in multiple global config files") and made
claude/opencode pin versions into the repo's mise.toml. Declare these
tools only on macOS and CachyOS.
Tern manages the omp version; update manually with `omp update` outside Tern.
Every cell now floats: windows sharing a cell overlap (focused on top, inset by Hyprland gaps/border) and nothing reflows on open or close. Summon and Super+U raise the window they place. - Hyper+P / Hyper+; / Hyper+' pick, cycle, reset the screen layout - lilHyper+O / Hyper+O move the window to the next/previous screen - Super+L toggles a workspace between cells and full screen only - Super+U and screen layout choices persist in $XDG_STATE_HOME/dotfiles/cells.lua across logouts Verified live on eDP-1: cell geometry, stacking, Super+U persistence, Super+L round trip, reset back to the Fullscreen default.
Ctrl+] / Ctrl+[ move to the next / previous block, and Ctrl+Shift+] / Ctrl+Shift+[ to the next / previous tab across sessions. A second merge entry owns only these chords in Tern's settings.json, so other bindings stay per machine. macOS keeps Tern's defaults for now.
Standard Dev puts the browser left and terminals right; both need the same workspace for the cells to show side by side.
Ctrl+Shift+[ misbehaved on Omarchy, so next / previous tab across sessions moves to Ctrl+Alt+] / Ctrl+Alt+[. Ctrl+Shift+] / [ fall back to Tern's default next / previous block. Ctrl+Alt+[ / ] were only editor fold / unfold in Tern and are unbound in Hyprland.
gaps_in 2 / gaps_out 4 (Omarchy: 5 / 10). Cells re-snap the windows they floated on every config reload, so gap and layouts.lua changes (and Omarchy's no-gaps toggle) apply without reopening windows.
Only targets mise refuses (a real file or folder where a module wants a link) are moved aside. Copy-mode targets such as fcitx5's keyboard.conf are overwritten, and mise keeps no checkpoint of them or of what --force-dotfiles replaces (`mise dot undo`: nothing to undo).
Clone Omarchy themes with [bootstrap.repos] into ~/.config/omarchy/themes/<name>, where Omarchy's theme menu finds them; `dotfiles --update` fast-forwards them. Pulsar is the first. bootstrap:omarchy-theme switches to OMARCHY_DEFAULT_THEME once per value of it, so a theme picked later in Omarchy's menu stays until the default changes. Outside a live Hyprland session it uses Omarchy's headless mode, which stages the theme for the next login. The live-session lookup moves into hypr-instance.sh, shared with bootstrap.sh, so the stale-signature handling has one copy.
Catppuccin, a built-in theme, is now the default, and Pulsar is no longer cloned. The theme support stays: the comment on bootstrap:omarchy-theme shows how to add a theme repo again. An existing Pulsar clone is left where it is.
Preserve Mac-specific app, SSH-agent, Claude and shell behavior. Keep stable Raycast and existing sudo policy; retain Tern summon. Stage Spoon updates with failure and interruption rollback. Make setup previews non-mutating and conflict backups collision-safe. Use native pnpm and remove Vimscript language-server management. Verified with isolated native mise checks and focused regressions, 31 tool installs, 13 LSP lifecycles, real Spoon release convergence, and synthetic dotfile apply, repeatability and rollback. Preparation only: live main and host configuration remain unchanged. No remote state was changed. Refs #159.
Keep only theme and TUI in the Mac profile. Herdr owns its generated integration; it is no longer a migration prerequisite. Verified isolated mise deployment and an unchanged repeat apply. Live configuration and other profiles remain unchanged.
Prioritize mise runtimes in Darwin login shells while keeping Linux wrapper precedence. Retire stale role links and manage Yazi directly. Repair fresh Neovim plugin and Solargraph installs. Keep TypeScript 7 as the compiler and give language-server 6 its own compatible SDK. Verified native login shells, simulated Linux PATH guards, actual Yazi/Neovim runs, standalone TS diagnostics, a clean Solargraph install, and no-change managed dotfile reapplication. Refs #159.
Select supported Catppuccin Mocha options, remove near-black overrides, and enable transparent ordinary floats while retaining text contrast. Manage ApplePressAndHoldEnabled=false for Tern's macOS domain only. Preserve global repeat timing, Linux settings, and terminal opacity. Verified normal Neovim startup and native PTY rendering, applied native preference type/value, no-change repeat, and managed dotfile state. Physical key-repeat confirmation awaits a user-controlled Tern relaunch; no running editor or chat was restarted.
Keep bootstrap in HOME unless explicitly redirected. Validate Linux sudoers before installation and transfer Git includes without losing signing policy, unrelated globals, or repository-local overrides. Repair retained Helm and language-server dependencies, remove stale sesh consumption and unconditional Ollama deletion, and respect Omarchy's native update ownership. Align docs and validation gates. Verified the full eight-suite macOS gate and real wrapper preview; Linux sudoers, Git and Task scenarios; real Helm, tmux and mise consumers; and the exact ShellCheck gate. Live Git migration preserves effective values and is idempotent. No full fresh Omarchy installation. Refs #159
Recognize ~/.local/share/omarchy consistently in the wrapper and Taskfile while retaining explicit profile precedence and existing system-marker and OS-ID detection. Add wrapper regression coverage and document both supported installation roots. Reproduced ordinary task update rejecting the home-only layout before the fix. Verified real Linux GoTask dispatch afterward across 18 scenarios, the exact ShellCheck gate, and the full eight-suite macOS gate. No actual system updater or package installation was run. Refs #159
Clone the Ayaka theme (abhijeet-swami/omarchy-ayaka-theme) into ~/.config/omarchy/themes/ayaka and make it the default theme. The url matches the existing clone's origin, .git suffix included.
btop.conf was deployed whole on macOS/CachyOS and not at all on Omarchy, so Omarchy's default replaced every repo setting. mise only merges JSON/TOML/YAML and btop rewrites its file wholesale, so bootstrap:btop now sets just the keys in settings.conf and leaves the rest to btop. The theme key comes from omarchy.conf (color_theme = "current", Omarchy's theme link) or catppuccin.conf elsewhere. shown_boxes gpu0 is dropped: without a GPU library btop removes the box and saves that, so the key would flip back on every run.
btop reads AMD GPU stats from librocm_smi64.so and drops a gpu0 box it cannot read. Install rocm-smi-lib on the Omarchy profile and own shown_boxes with gpu0 there; the integrated Renoir Radeon shows up.
Keep Discord personal-only on macOS and Linux without changing shared apps or OS profiles. Persist purpose locally through config-only setters. Verify native package selection, preview safety and idempotence. Fix the macOS Zsh fixture's temporary-path alias without weakening cache guards.
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.
Replaces the Ansible
roles/tree with mise modules (modules/*/mise*.toml) and a slimmedbin/dotfilesthat runsmise bootstrap. Supported profiles: omarchy, cachyos, macos.Opened as a draft for review.