This repository is a small, direct configuration center for disposable
machines. The source tree is intentionally visible; a single YAML menu maps
those sources to the hidden paths applications expect under $HOME.
The default path needs only a POSIX shell and Git:
git clone https://github.com/JulyFinal/dotfiles.git ~/dotfiles
cd ~/dotfiles
./setupsetup presents a short interactive menu. On a temporary machine, selecting
Core configurations is enough; personal files, tool installation, and
diagnostics remain separate choices.
config/ visible configuration sources
config/README.md source-tree guide
manifests/files.yaml source, target, method, mode, and platform menu
manifests/agent-skills.yaml
external skills and their agent targets
secrets.example.toml copyable secret-file shape; secrets.toml is ignored
minijinja.toml repository-local template defaults
scripts/install-mise standalone Mise installer
systems/ Arch installer inputs plus Linux/macOS package references
recipes/ commands worth keeping, not deployed configuration
docs/ maintenance and contributor notes
tests/ smoke test and secret scanner
The repository source path does not have to match the destination path. For
example, config/mise/config.toml maps to
~/.config/mise/config.toml, while config/agents/codex/mcp.toml.j2 merges
only its managed MCP keys into ~/.codex/config.toml. See
config/README.md for the visible layout and
manifests/files.yaml for the complete mapping.
The deployment menu currently has two groups:
- Core: shell entrypoints, Tmux, Navi cheats, Mise, Starship, and portable shell paths.
- Personal: Neovim, Helix, Kitty, Yazi, Atuin, Tealdeer, Vicinae, and the local agent configuration.
The group is only a selection menu. The exact files and behavior live in the manifest, so adding or removing one file does not require changing the shell engine.
Real secret values stay in the ignored repository-root secrets.toml:
cp secrets.example.toml secrets.toml
chmod 600 secrets.tomlThe file is never linked into $HOME. A .j2 source is rendered when its
manifest entry uses template or a merge method; ordinary link and copy
entries use the source directly. MiniJinja receives the root TOML file as
template data, so a template can use values such as:
{{ service.api_token }}
{{ home }}
{% if docker_available %} ... {% endif %}On a temporary machine, apply only core and no secret file is needed. If the
secret file was moved elsewhere, point at it explicitly:
DOTFILES_SECRETS_FILE=/path/to/secrets.toml \
./dotfiles apply personalUse the interactive installer:
./setupIt can select core or personal configuration, install the Mise tool set, and run diagnostics. Before changing the destination it prints the complete plan and unified diffs. After confirmation it applies the repository version directly; it does not create backups.
The public backend is intentionally small:
./dotfiles plan core personal
./dotfiles apply core personal
./dotfiles apply core --yes
./dotfiles install core
./dotfiles install yazi
./dotfiles doctor core personal
./dotfiles explain ~/.zshrcUseful boundaries:
applynever accesses the network.installis the only networked action.- Existing destination files are replaced only after the plan is shown and confirmed.
- Deleted repository files are not removed from old machines automatically.
platformsin the manifest controls platform-specific entries; there are no separate overlay trees.
Preview against an isolated home:
DOTFILES_HOME=/tmp/test-home DOTFILES_PLATFORM=macos \
./dotfiles plan core personalThe manifest parser intentionally uses a small, flat YAML subset so the core
workflow still works on a fresh POSIX machine. yq, when available, validates
the manifest in the smoke test; it is not required to apply core files.
The method field in manifests/files.yaml is the
source of truth:
linkcreates an absolute symlink to the repository source.copycreates an independent file and reapplies the declared mode.templaterenders a.j2source through MiniJinja and applies the declared mode.merge-jsonrecursively updates only fields present in the source; thepackagesarray is add-only, and unknown fields remain untouched.merge-tomlupdates only TOML keys present in the source fragment; other tables and fields remain untouched, and absent managed sections are not deleted.- Existing JSON/TOML merge targets require
jqorpython3; if neither is available,applyrefuses to overwrite the target.
Shell entrypoints such as ~/.zshrc are copied because installers often append
to them. Their repository-owned configuration lives in config/shell/.
Reapplying shows a diff and recreates the thin entrypoint. Codex and Pi agent
settings use merge methods so model choices, project trust, Feishu values, and
other machine-specific fields are preserved.
Core installation uses the official Mise installer when Mise is missing, then
installs the tools declared by
config/mise/config.toml:
./dotfiles install coreThat tool set includes rclone for the Navi file-server cheat and the Git
Cargo build of simple-completion-language-server (scls) used by Helix
snippets. After applying personal configuration, fetch the external snippet
repository explicitly when needed:
simple-completion-language-server fetch-external-snippets
simple-completion-language-server validate-snippetsTool declarations intentionally use latest. Agent skills are declared in
manifests/agent-skills.yaml. Synchronize the
shared copy for Codex, Claude Code, and Pi with:
mise run skills-syncPreview without changing anything with:
mise run skills-sync -- --dry-runSee recipes/mise.md for the direct commands.
Yazi keeps only its flavor selection and flavor dependency lock in the repository:
config/yazi/theme.toml and
config/yazi/package.toml. Applying personal
configuration is offline; install the locked Yazi plugin/flavor explicitly
afterward:
./dotfiles apply personal
./dotfiles install yaziThe Yazi install step uses ya pkg install and downloads the locked packages
into the target home's Yazi configuration directory.
Arch system installation is deliberately outside the dotfiles workflow:
systems/arch/install --profile laptop-intel --dry-run
systems/arch/install --profile desktopsetup and dotfiles apply never call this installer.
The Arch package files are consumed by systems/arch/install. The Linux and
macOS files are deliberately manual reference lists for package-manager
translation; no generic dotfiles command pretends to install them.
./tests/smoke.sh
./tests/pre-commit worktreeThe pre-commit scanner rejects credential-shaped content. Put real secret
values in the ignored root secrets.toml; do not add runtime provider names or
URLs to configuration examples.