- Shell 82.5%
- CSS 6.8%
- Python 6.7%
- Lua 2.6%
- Go Template 1.4%
The Waybar module reports the whole manual set and never says which workspace just changed, so a toggle on the focused workspace had no immediate feedback. Notify the workspace and the resulting state, with the glyph the indicator already prints and the stack tag pattern of sway-toggle-nightlight, so a run of toggles replaces the notification in place rather than stacking one per keypress. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .agents/skills/software-fit | ||
| .chezmoiscripts | ||
| .claude/skills | ||
| docs | ||
| dot_bashrc.d | ||
| dot_config | ||
| dot_docker/cli-plugins | ||
| dot_local | ||
| dot_var/app | ||
| host | ||
| manifests | ||
| tests | ||
| Work | ||
| .chezmoi.toml.tmpl | ||
| .chezmoiignore | ||
| .gitignore | ||
| AGENTS.md | ||
| BOOTSTRAP.md | ||
| bootstrap.sh | ||
| CLAUDE.md | ||
| dot_bash_profile | ||
| dot_bashrc | ||
| dot_gitconfig | ||
| dot_inputrc | ||
| README.md | ||
dotfiles
chezmoi source for a Fedora Sway Atomic workstation: an immutable host, a stock
Sway desktop, and every tool installed through exactly one mechanism. It drives
four machines from the same tree, with per-host differences resolved from
detected hardware rather than from hand-maintained branches, and it is
reproducible from scratch with bootstrap.sh.
It is not a portable framework. It assumes rpm-ostree, stock Sway on Wayland,
bash, rootless Podman, and mise, and it takes positions that only make sense
together: Secure Boot stays on because the disk unlock depends on it, the host
layer stays small because rebases have to stay cheap, and nothing is installed
by curl | sudo.
Repository layout
| Path | Contents |
|---|---|
dot_*, private_dot_* |
Everything applied into $HOME by chezmoi |
dot_config/sway/config.d/ |
Ordered Sway fragments, from input to theming |
dot_local/bin/ |
Helper scripts, most of them Sway-specific |
dot_config/desktop-themes/ |
22 themes, one directory per theme |
.chezmoiscripts/ |
Idempotent hooks for fonts, icons, and manual binaries |
manifests/ |
Authoritative package lists: rpm-ostree, Flatpak, MIME defaults |
host/ |
Files that belong outside $HOME: /etc overrides, udev rules, units |
docs/ |
Storage, snapshots, Sway, theming, and TPM2 runbooks |
bootstrap.sh |
Staged, resumable, idempotent setup from scratch |
AGENTS.md |
Operating context shared by the coding agents |
host/ and manifests/ are deliberately outside chezmoi's apply path: they
describe machine state, not home state, and bootstrap.sh is what installs
them.
Installation architecture
Every tool belongs to exactly one category, and the boundary is the point:
- mise for development CLI tools and runtimes in userspace. The default
choice.
dot_config/mise/config.tomlis the inventory. - rpm-ostree only for real host components and Wayland/Sway integrations. The layer stays small and the manifests are authoritative.
- Distrobox, with Toolbx as the Fedora-native fallback, for mutable development environments.
- Flatpak for GUI applications and browsers/PWAs.
Nothing lands in /usr/local/bin, and a manual binary in ~/.local/bin is a
last resort that has to be inventoried, because the update command does not
cover it.
Userspace toolchain
dot_config/mise/config.toml is the authoritative inventory and carries the
reason behind every non-obvious line. What follows is the map of what is
installed and what it is for. Versions stay at latest for portable CLI tools,
which mup updates in one pass; only compatibility pairs and fragile runtimes
are pinned.
Shell and filesystem. fzf for fuzzy selection, zoxide for directory
jumps, eza and fd in place of ls and find, ripgrep for search, bat
for a highlighted cat, dust for disk usage by directory, yazi as the file
manager, starship for the prompt, tealdeer for tldr pages, glow for
Markdown in the terminal, gum for prompts inside scripts.
Sessions. tmux, and herdr next to it for the trial recorded in
AGENTS.md. herdr brings its own multiplexer rather than driving tmux, so the
overlap is deliberate and only one of the two is meant to survive.
Code and git. neovim, shellcheck, delta as the pager for diffs,
lazygit, and gh. Its Forgejo counterpart tea is the only manual binary in
~/.local/bin and is not a mise tool, so mup does not update it.
Data, HTTP, and network. jq for JSON, dasel for the same query syntax
across YAML, TOML, XML, and CSV, duckdb for in-process SQL over local CSV,
Parquet, and JSON files, xh as the HTTP client, oha for load tests, doggo
for DNS.
Coding agents and LLM tooling. claude-code, codex, opencode, and
pi-coding-agent are the interactive agents. aichat is deliberately not a
fifth one: it is installed for shell pipes, RAG, and its local embeddings
server, and it reaches the LiteLLM gateway. mistral-vibe authenticates against
its own subscription instead, so it keeps its own credential and its own
endpoint. ramalama serves local models from OCI registries through rootless
Podman and is a frontend for the engine, never a host layer. defuddle strips a
web page down to article content on demand, for the shell.
Desktop daemons, driven by Sway. cliphist for clipboard history, voxtype
for local dictation, autotiling for the split direction. All three run in
userspace, which is why they belong here and not in the ostree layer: the
voxtype release also ships a 342 MB RPM, and layering it would put a userspace
daemon in the image for nothing.
Containers. docker/compose, which is the Compose CLI talking to the
rootless Podman socket and not Docker Engine, and lazydocker against the same
engine.
Backup and sync. restic, the intended engine for the external backup that
is still being designed, and proton-drive, pulled from Proton's own release
endpoint with the published SHA-512 verified on update.
Runtimes and plumbing. node, ruby, and uv. usage is what mise's
generated shell completions delegate their argument parsing to.
The rest. chezmoi itself, btop for processes, fastfetch, yt-dlp,
try-cli for throwaway project directories, and cliamp, a retro terminal
music player.
Desktop
Stock Sway, with Kanshi authoritative for output geometry and a strict division of feedback: Waybar for persistent status, Dunst for actionable notifications, SwayOSD for immediate state changes. No signal is duplicated across the three.
sway-menuis the single face of the helpers, a nested Rofi tree reachable fromSuper+Alt+space, from the Copilot key on the laptop, and by route (sway-menu capture) for the direct submenu bindings. It adds no behaviour: every entry calls a script that already exists.sway-keybindingsonSuper+Kgenerates the searchable keymap from the effective configuration, so there is no second static copy to drift.- Window management uses Sway's native scratchpad, tabbed groups, autotiling, directional swaps, and a workspace history stack.
- On a letter shared by a work app and a personal one, Alt is the work modifier and carries all three Office tenants at once. The plain chord goes to the personal equivalent.
- Rofi is the launcher, Ghostty the terminal with
footas the fallback, and Firefox on the host is the general browser while Chromium hosts personal PWAs and Edge keeps Office tenants in separate profiles.
Capture, clipboard, and dictation
- Screenshots, screen recording, screen OCR, and a color picker built from grim and slurp rather than from another dependency.
- Clipboard history through cliphist behind a single entry point that applies a restrictive umask and honours selections advertised as sensitive, plus universal copy/paste bindings that adapt to the focused client.
- Local dictation on voxtype with whisper, push-to-talk on F9 and a toggle for longer passages, with a dedicated Sway mode so a modifier released late cannot turn the transcription into keybindings. Nothing leaves the machine.
Theming
One command switches the whole session. Each theme directory carries the
palette for Sway, Waybar, Rofi, Ghostty, Dunst, SwayOSD, btop, yazi, Neovim,
Obsidian, VS Code, and the Chromium tint, plus its own wallpaper set and
swaylock configuration. Eighteen themes come from Omarchy, four from the
community. See docs/THEMING.md.
System integration
- TPM2-backed LUKS unlock with systemd native enrollment, Secure Boot,
PCR 7, and an interactive PIN. Enrollment is always manual; no PIN,
passphrase, recovery key, or header backup is ever tracked.
Runbook in
docs/TPM2-LUKS.md. - Local Btrfs home snapshots, three home tiers and two cold VM tiers on a
timer, with nested subvolumes for the areas that must stay out of the parent
snapshot, a rehearsal drill, and fail-closed behaviour under space pressure.
They are not a backup and are never described as one. See
docs/SNAPSHOTS.md. - Signed out-of-tree kernel modules, because Secure Boot is required by the unlock and refuses an unsigned module in silence. Two mechanisms are in use and they are not interchangeable.
- Rootless Podman as the only engine, with Docker compatibility exposed through the socket and the Compose CLI. The emulation banners are left in place on purpose.
- Windows VM as a Podman quadlet user service, reached over local RDP.
- Storage layout, mounts, and the per-host
fstabrules that are deliberately untracked are indocs/STORAGE.md.
Getting started
# Audit an existing machine against the declared state, read only
./bootstrap.sh --plan
# Add whatever is declared and missing
./bootstrap.sh --apply
# Full setup from scratch: runs the next pending phase, resumes after reboots
./bootstrap.sh
The run is staged across eight phases, from preflight and GPU repositories to
layers, chezmoi, mise, Flatpak, host files, and user services. Every phase
checks whether its work is already done and skips it, and interactive steps
that cannot be automated (tokens, OAuth, SAML, tenant logins) are listed rather
than attempted. BOOTSTRAP.md is the narrative counterpart.
Documentation
BOOTSTRAP.md: setup from scratch, hardware notes, local steps and secrets.AGENTS.md: the operating context, durable constraints, and open work.docs/SWAY.md: desktop architecture, change rules, and backlog.docs/THEMING.md: themes and wallpapers.docs/STORAGE.md: disks, mounts, and per-host layout.docs/SNAPSHOTS.md: the home snapshot design and its runbook.docs/TPM2-LUKS.md: enrollment, verification, and recovery.
Screenshots
Conventions
Documentation, comments, and runtime messages are in English. Source files are
authoritative: edit here or capture a change with chezmoi add, never treat the
applied copy in $HOME as the original. No plaintext token, key, or credential
belongs in this repository; secrets live in local 0600 files and in the keyring,
and .chezmoiignore keeps them out.

