Personal development environment shared across macOS and Arch Linux machines.
Configuration installed into a user home directory lives in GNU Stow packages under home/. Platform setup stays outside that tree: macos/ and arch/ install user environments, while the dedicated Box agent host is installed and operated from a separate private infrastructure repository.
.
├── home/ GNU Stow packages projected into $HOME
├── arch/ Arch Linux user configuration and dependencies
│ ├── install
│ ├── stow
│ └── tests/
└── macos/ macOS installation and package selection
├── install
├── install-apps
├── stow
└── tests/
The directories under home/ mirror their destination beneath $HOME. For example:
home/nvim/.config/nvim/ → ~/.config/nvim/
home/pi/.pi/ → ~/.pi/
home/scripts/.local/bin/ → ~/.local/bin/
Package groups include:
- Agent tooling:
agents,herdr,opencode, andpi - Development tools:
git,lazygit,nvim, andscripts - Shell and terminals:
ghostty,starship, andzsh - Browser customization:
vimium - macOS UI:
aerospace,borders, andleaderkey - Stow configuration:
stow
Not every target installs every package. macos/stow and arch/stow define their platform selections; machine-role installers may select additional packages.
Aha is a separate application repository at ~/aha (magoz/aha), not vendored
source or an npm package installed by these dotfiles. Build it with
pnpm install --frozen-lockfile && pnpm build from that checkout. The scripts
package provides ~/.local/bin/aha, which invokes the built CLI while preserving
the caller's working directory. The agents package provides a skill entry that
reads ~/aha/SKILL.md for the canonical workflow and house style. For split DNS,
put the public API endpoint URL (one line, no shell syntax) in
~/.config/aha/endpoint; the launcher uses it when AHA_ENDPOINT is unset.
Explicit --endpoint arguments still take precedence. Neither package clones,
builds, or deploys Aha automatically; credentials and machine-specific endpoint
values stay outside dotfiles.
- macOS
- Homebrew
- Git access to this repository
Clone into the expected location:
git clone [email protected]:magoz/.dotfiles.git ~/.dotfiles
cd ~/.dotfilesRun the workstation installer:
./macos/installIt installs Tailscale's recommended standalone macOS app directly from Tailscale's signed package, installs command-line dependencies with Homebrew, installs Pi and OpenCode, applies the macOS Stow packages, points Leader Key at the stowed config, installs package dependencies, and refreshes configured services and plugins. It removes conflicting Homebrew tailscale formula or tailscale-app cask installations first because the CLI-only formula can fail to register macOS split-DNS routes. Tailscale sign-in and system-extension approval remain attended steps. The installer also removes existing ~/.gitconfig and ~/.zprofile before Stow takes ownership, so inspect the script before using it on a new machine.
Install the optional desktop application set separately:
./macos/install-appsTo apply only the tracked home configuration without installing software:
./macos/stowThe Stow command is safe to rerun. It also migrates symlinks created by the previous root-level package layout to home/ while leaving unrelated symlinks untouched.
On an already installed Arch system, install the development dependencies separately:
sudo pacman -Syu --needed base-devel bat bun curl eza fd fzf git github-cli jq \
lazygit neovim nodejs-lts-krypton npm pnpm ripgrep starship stow tealdeer tree-sitter-cli \
zoxide zsh zsh-autosuggestions zsh-syntax-highlightingThis is an explicit system upgrade: review Arch upgrade notices first. The configured agent packages require Node >=24.18 and <25, supplied by nodejs-lts-krypton, rather than the current nodejs package. Herdr is optional and installed separately; its machine-specific configuration is not applied by the generic Arch installer.
Clone the repository if needed, then install as your normal user:
git clone [email protected]:magoz/.dotfiles.git ~/.dotfiles
cd ~/.dotfiles
./arch/installFor routine updates:
cd ~/.dotfiles
git pull
./arch/installThe installer applies shell, Starship, Neovim, LazyGit, agents, and scripts; installs user-local npm 11.16.0, Pi, stable OpenCode 2 (@opencode/cli), and package/plugin dependencies; and refreshes completions. It sets portable Git workflow defaults and the tracked ignore file while preserving your existing Git identity and credential helpers. It does not install the macOS Git configuration.
To apply configuration only (no dependency installation or Git changes):
./arch/stowNeither command changes the login shell, runs system provisioning, manages services, or touches Hyprland, Ghostty, or other desktop configuration. Omarchy retains ownership of its desktop. Existing conflicting files or unrelated symlinks are reported rather than overwritten; review and back up any configuration you explicitly want to replace before rerunning. Known links from the old root-level package layout are migrated automatically.
Start the configured shell with exec zsh -l. Selecting Zsh as your default login shell is a separate, deliberate choice.
Both installers remove the old @opencode-ai/cli preview and install stable @opencode/cli. The o alias now runs opencode; opencode2 remains a compatibility command. To migrate only OpenCode on an existing setup:
export NPM_CONFIG_PREFIX="$HOME/.local/share/npm"
export PATH="$NPM_CONFIG_PREFIX/bin:$PATH"
npm uninstall --global --ignore-scripts @opencode-ai/cli
npm install --global --allow-scripts=@opencode/cli @opencode/cli
~/.local/bin/update-zsh-completions
exec zsh -lThese npm commands use npm 11.16+ (installed by arch/install). System-managed V1 installations are left untouched; the user-local npm bin directory must precede them in PATH. Check command -v opencode and opencode --version after restarting your shell. The legacy opencode-ai npm package is V1, not the V2 upgrade target.
OpenCode 2.0.3 now has additive Herdr, pane-local worktree handoff/management,
native delegation, shared-skill adapters, until, and /quota wiring.
Shared worktree creation still defaults to Pi; OpenCode requires --agent opencode.
See assessment setup, safety restrictions and remaining live checks.
The dedicated Box host keeps its destructive bootstrap, hardware configuration, services, security checks, audits, and recovery runbooks in the separate private magoz/box repository. That repository treats ~/.dotfiles/home as an external package catalog and applies the Linux-safe subset without owning or duplicating these user configurations.
For the portable user environment, use ~/.dotfiles/arch/install. For the complete Box-specific dotfiles selection and login-shell setup, use ~/.box/install. Neither is destructive system provisioning. Never run the macOS installer on Box.
The macOS box alias remains a direct attach to Box's default session, using
its server-side keybindings and custom commands. It does not open a combined
Local/Box window.
For the combined window, use Herdr 0.9+. Run the following from an ordinary local Mac terminal, not inside Herdr or SSH:
cd ~/.dotfiles
git pull
./macos/stow # or ./macos/install for the full workstation setup
brew update && brew upgrade herdr # Homebrew installs; direct installs use herdr update
./macos/setup-box
herdrmacos/setup-box checks SSH and Herdr config, registers Box's
default session, and reuses an existing profile (enabling it if disabled). It does
not duplicate profiles, overwrite SSH settings/keys, or migrate named sessions.
It runs separately from the installer because remote server replacement requires
an attended decision. Replacing an old server stops its pane processes;
finish running work before approving, or decline and migrate later. Experimental
handoff is not requested. If a saved machine shows Attention, run box from a
local terminal, follow Herdr's prompts, then restart the combined client.
It then sets up ocb, the OpenCode 2 client for Box's tailnet-only OpenCode
server, published by Fleet at https://fleet.oox.sh: it reads the server password over ssh box into the Keychain item
opencode-box (never printed), verifies the server with ocb --check, and
installs the @opencode/cli version the server runs if this Mac differs, and
registers OCB Link.app for ocb://session/<id> links (Fleet's "Open in terminal"), which
open a new Ghostty window running ocb -s <id>. Rerun
./macos/setup-box after a password rotation or an OpenCode upgrade on Box.
Daily use: ocb (UI on the Mac, agents on Box; both Macs see the same
sessions), ocb -c to continue the last session, and ctrl+x l or
/sessions to list every session across projects. Server operations live in
the private Box repo's opencode.md.
Skip these steps if ssh box already works without a password prompt:
-
Open the standalone Tailscale Mac app installed by
./macos/install, sign in to the approved tailnet, approve its system extension when prompted, and connect. Enrollment, access policy, and SSH key authorization are attended steps; neither installer copies private keys or bypasses authentication. -
Configure the existing
Host boxentry in~/.ssh/config, or add one if absent, before anyHost *defaults. Do not create a competing duplicate entry:Host box HostName box User magoz
HostName boxuses Tailscale MagicDNS. Use the verified full tailnet hostname instead if short-name resolution is unavailable. If multiple SSH keys exist, add this Mac's authorizedIdentityFileandIdentitiesOnly yesto the entry; keep the private key on this Mac. Box's public-key authorization is managed through the private Box repo, not the public dotfiles. -
Run
ssh box, verify its host-key fingerprint through a trusted path, then exit back to the Mac. Load passphrase-protected keys withssh-addso Herdr's background connections do not require prompts. -
Run
./macos/setup-box. Its SSH check requires an already trusted host key and non-interactive authentication; a failure changes no Herdr profiles.
Host provisioning and Mac trust for HTTPS development URLs are documented in the
private magoz/box repo (README.md and remote-development.md). Neither Box's
provision nor its install runs on the Mac.
Select Local or Box in the sidebar. Both Macs connect to the same Box
session, workspaces, and running agents; each client's selected tab can differ.
The combined UI uses the viewing Mac's theme and keybindings. box remains
available whenever you want the previous remote-only workflow. Closing a client
or disconnecting leaves the remote server running; stopping the server does not.
The shared home/herdr/.config/herdr/config.toml includes machine labels in the
agent sidebar and requires Herdr 0.9+. Apply this config on each Mac and reload
client config with Ctrl+T, then R.
Saved machine profiles and selection live under Herdr's client/ state directory
and are excluded from Git and Stow. Register Box separately on each Mac; do not
copy runtime state between them. herdr machine list shows saved profile IDs;
herdr machine disable <profile-id> disconnects one without stopping its agents.
The Treesitter configuration uses the rewritten main branch and requires Neovim
0.12+, Tree-sitter CLI 0.26.1+ (not the npm package), a C compiler, curl,
and tar. The platform dependency lists include the CLI. Parsers install
asynchronously into ~/.local/share/nvim/site; run :TSUpdate after updating the
plugin. Syntax selection uses native Neovim mappings: <C-space> expands and
Backspace shrinks a visual selection.
Preview one package without changing $HOME:
stow --dir "$PWD/home" --target "$HOME" --simulate --restow nvimApply or remove one package manually:
stow --dir "$PWD/home" --target "$HOME" --restow nvim
stow --dir "$PWD/home" --target "$HOME" --delete nvimTo add a package:
- Create
home/<package>/using the same paths the files should have beneath$HOME. - Add the package to
macos/stow,arch/stow, and/or the appropriate machine-role installer. - Run a Stow simulation before applying it.
- Keep credentials and runtime state out of the tracked package.
Most edits take effect immediately because the destination is a symlink into this repository. Rerun Stow when adding, removing, or relocating files.
The home/scripts package installs command launchers and their source under ~/.local:
sandbox-dbandprovision-envmanage Vercel-backed environments and expiring Neon database branches.worktreecreates provisioned Herdr worktrees and hands off to fresh Pi sessions.
After installing the configured Neovim plugins and parsers, run the offline Treesitter regression checks from the repository root:
nvim --headless -u NONE -l tests/nvim-treesitter.luaRun the focused repository checks after changing installation or Stow behavior:
./macos/tests/run
./arch/tests/run
git diff --checkThe platform tests use temporary home directories to verify legacy-link migration and preservation of unrelated configuration. Mac tests also exercise Box onboarding with mocked SSH/Herdr, including duplicate profiles, authentication failures, and approval failures. Arch tests also cover desktop/runtime preservation, conflict preflight, Linux Zsh startup, and a mocked dependency installation on an unprivileged Arch host. Machine-role repositories test their own integration with this package catalog independently.
Do not commit credentials, private keys, auth files, machine-local installer values, or runtime sessions.
- Pi, OpenCode, Herdr, package-manager, and browser runtime state is excluded through
.gitignoreor package-local Stow ignore rules. - SSH private keys and machine-local infrastructure configuration are never stored in this repository or copied between machines.