Skip to content

About

My home-manager configuration with nix.

Resources

Stars

5 stars

Watchers

1 watching

Forks

Latest commit

 

History

288 Commits

Folders and files

Repository files navigation

Home Manager Configuration

Personal Nix home-manager configuration for macOS (Apple Silicon) that manages user environment, packages, and dotfiles using Nix flakes.

Features

  • 🏠 Declarative Environment: Complete user environment managed through Nix
  • 📦 Package Management: Reproducible package installation across machines
  • 🔧 Development Tools: Comprehensive development environment setup
  • 🚀 Flake-based: Modern Nix flakes for better reproducibility
  • 🍎 macOS Optimized: Specifically configured for Apple Silicon Macs
  • 💾 Binary Caches: Fast package installation with pre-built binaries
  • ⚙️ Global Direnv: Universal direnv integration across all terminals and editors

Quick Start

Prerequisites

  1. Install Nix (if not already installed):

    curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
  2. Install Home Manager:

    nix run home-manager/master -- init --switch

Installation

  1. Clone this repository:

    git clone https://github.com/sadjow/home-manager ~/.config/home-manager
    cd ~/.config/home-manager
  2. Apply the configuration:

    home-manager switch --flake .

Configuration Structure

├── flake.nix              # Flake definition with inputs and outputs
├── flake.lock             # Locked dependency versions
├── darwin-configuration.nix # nix-darwin system config (hostname, etc.)
├── home.nix               # Main home-manager configuration
├── home/
│   ├── AGENTS.md          # Shared global agent instructions
│   ├── claude/            # Authored Claude Code configuration
│   ├── nix/
│   │   ├── caches.nix     # Binary cache URLs and public keys
│   │   └── default.nix    # User Nix settings
│   ├── agent-skills.nix   # Pinned public skills and local private links
│   ├── claude-code.nix    # Claude Code integration
│   ├── codex/             # Codex profiles shared with T3 Code
│   ├── codex.nix          # Codex CLI, defaults, and isolated profiles
│   ├── t3-code.nix        # T3 Code provider instances
│   └── shell.nix          # Shell configuration (zsh/bash with global direnv)
├── docs/
│   ├── AGENT_HARNESS_SKILL_LINEAGE.md # Personal and project skill feedback loop
│   └── CHANNEL_STRATEGY.md             # Nixpkgs channel strategy and alternatives
├── overlays/
│   └── README.md          # Information about custom overlays
├── AGENTS.md              # Shared repository guidance for coding agents
└── README.md              # This file

Included Packages

Development Tools

  • Languages: Ruby, Dart, Node.js (via asdf)
  • Editors: Neovim
  • Version Control: Git, GitHub CLI
  • Build Tools: CocoaPods, FFmpeg
  • Shell: tmux, direnv, ripgrep, bat

Utilities

  • Security: AWS Vault, GPG
  • Network: nmap
  • AI Tools: Claude Code (via external flake)
  • Package Management: Cachix, asdf-vm

External Flakes

  • devenv: Fast, declarative development environments
  • claude-code: AI coding assistant with dedicated Node.js runtime

Codex permissions

home/codex.nix manages the personal Codex defaults in ~/.codex/config.toml. Each activation sets Full access: sandbox_mode = "danger-full-access" and approval_policy = "never". This removes command sandbox restrictions and disables approval prompts governed by that policy. Computer Use app permissions and Locked Use remain separate controls.

The activation preserves other settings and TOML comments, keeps the file writable with mode 600, and saves the previous content to config.toml.home-manager-backup when it changes. An incompatible default_permissions selector is removed. Existing task overrides and the isolated codex-spireworks profile are unchanged.

See OpenAI's default permissions documentation.

T3 Code providers

home/t3-code.nix declares the provider instances T3 Code shows in its Settings UI: the claudeAgent and codex instances, the isolated claude_spireworks, claude_stackbuilders, and codex_spireworks instances built from home/claude/profiles.nix and home/codex/profiles.nix, and one Cursor instance per organization, cursor_spireworks and cursor_durst. Each activation merges them into ~/.t3/userdata/settings.json with the same three-way reconciliation as the Claude settings: the file stays writable with mode 600, provider fields chosen in the UI survive while the declared fields are unchanged, and T3 Code reloads the file as soon as activation rewrites it. The baseline lives in ~/.t3/userdata/.home-manager-settings/, and the previous content is saved beside the runtime file with the suffix .home-manager-backup.

Provider authentication stays with each CLI's own home directory, so nothing in the declared settings is secret. To add another isolated Claude Code or Codex account, add its profile to the matching profiles file and describe its instance in home/t3-code.nix; the instance runs the profile's wrapper command and points homePath at the same config directory.

The Cursor agent keeps a single browser login per machine in the macOS keychain, which cursor_spireworks uses. Every other organization authenticates with an API key from its Cursor dashboard, supplied as a sensitive CURSOR_API_KEY variable in the Environment section of its instance in T3 Code; the value goes to T3 Code's secret store, never to this repository. cursor_durst is declared disabled so it cannot fall back to the keychain login, and enabling it in the UI after adding the key survives later activations because the declared field is unchanged.

Shared Codex daemon

Home Manager installs codex-daemon-reconcile. Running it without arguments checks saved daemon feature overrides against the installed CLI without changing state. It exits with status 1 when overrides conflict or the check fails.

codex-daemon-reconcile
codex-daemon-reconcile --restart

Use --restart when ready to interrupt active or queued work on the shared daemon. The helper stops the daemon and starts it fresh through Codex's lifecycle commands, which clear saved session feature overrides. Other daemon settings are left to Codex to preserve. Desired persistent feature preferences belong in config.toml. CODEX_HOME selects the target profile; the default is ~/.codex. Home Manager activation does not restart the daemon.

Codex 0.161.0 can retain a stale api_key_model_discovery override after a CLI upgrade. app-server daemon restart --enable api_key_model_discovery was observed to report success while retaining the disabled override. The interactive “Restart with these settings” action also repairs it. A fresh stop/start avoids editing Codex's internal settings file directly. Upstream report: openai/codex#51787.

After reconciliation, launch codex and confirm the compatibility prompt is gone. Matching versions, features list, and a successful restart are insufficient: CLI defaults, persisted overrides, and the live server handshake are separate evidence. The helper checks saved overrides and daemon availability; it does not claim to verify the live feature handshake. If a lifecycle command fails or is interrupted, check codex app-server daemon version before retrying.

Agent skills

Public skills are maintained in sadjow/skills. home/agent-skills.nix installs the revision pinned by the skills flake input into these discovery directories:

Consumer Directory
Shared agent discovery ~/.agents/skills
Codex ~/.codex/skills
Claude Code ~/.claude/skills and each isolated profile's skills
Cursor ~/.cursor/skills

Each public skill has a symbolic link in every directory, resolving to the same pinned source in the Nix store. The destinations do not contain independent copies. Edit the public skills repository; installed Nix store files are read-only. Local checkout edits become installed public skills only after publishing them, updating the pin, and activating the resulting Home Manager generation.

To adopt a newer published revision:

nix flake update skills --flake 'path:.'
nix flake check 'path:.'
home-manager build --flake 'path:.#sadjow'

A path: build includes uncommitted changes. When the worktree has any, compare the first two paths below before updating the pin: a match means that work is already active, while a difference means the switch would also activate it. After the build, the closure difference should list only the updated skills source.

nix eval --raw 'path:.#homeConfigurations.sadjow.activationPackage.outPath'
readlink -f ~/.local/state/nix/profiles/home-manager
nix store diff-closures "$(readlink -f ~/.local/state/nix/profiles/home-manager)" ./result

Activate separately with home-manager switch --flake 'path:.#sadjow' when ready. Home Manager does not run npm or fetch a moving skills branch during activation. Unmodified upstream skills keep their existing installer-managed source; their installation commands are in the public repository's upstream catalog.

Optional private skills stay in a separate authenticated checkout at ~/.config/skills-private. Clone that repository using your configured Git credentials and restrict its directory permissions to 700. During activation, Home Manager discovers skills/*/SKILL.md in that checkout and creates local links for the same discovery directories. Each link resolves to the same private checkout, so edits there are available through every link without republishing. New or renamed private skills need another activation to reconcile their links. No private contents or skill-name inventory are read at Nix evaluation time or copied into the Nix store. A missing checkout is allowed; an unrelated existing destination is preserved and reported as a conflict.

Verify installation

A successful build does not activate its links. After switching, verify the installed skill files rather than relying only on the checkout or build result:

bash scripts/check-agent-skills

# Print dangling links in the two discovery directories used by this setup for Codex.
find "$HOME/.agents/skills" "$HOME/.codex/skills" -type l ! -exec test -e {} \; -print

# Replace browser-harness with the skill being investigated.
for directory in .agents/skills .codex/skills .claude/skills .claude-spireworks/skills .claude-stackbuilders/skills .cursor/skills; do
  test -f "$HOME/$directory/browser-harness/SKILL.md" || printf 'Missing: %s\n' "$directory/browser-harness"
done

The integration check exercises the configuration and private-link reconciler in a temporary home; it does not audit the active installation. The filesystem checks above verify installed paths. Confirm discovery in the client as well, starting a new task or restarting it if its catalog has not refreshed.

Recover from migration conflicts

Moving or renaming a skill source can leave an older generation's links dangling. Build and activate the current configuration after migrating sources. If activation fails because a real directory occupies a managed skill path, inspect that exact path and move it to a backup outside the discovery directories before retrying. Keep the backup until the managed replacement has been verified.

For an obsolete dangling link, inspect its target with readlink and confirm that it belongs to a retired or renamed skill before moving it to the backup. Do not bulk-delete unrelated links or directories. A failed switch can already have applied some changes; rerun the switch after resolving the conflict and verify that it completes successfully.

Binary Caches

Cache URLs and public signing keys are defined once in home/nix/caches.nix. Home Manager uses this catalog to generate the user Nix configuration. It takes effect after activation, including for subsequent builds of this configuration.

After home-manager switch, Nix automatically checks these caches for matching packages across projects. Public caches do not require a Cachix token or a separate cachix use command. New caches must be registered in the catalog; Nix does not discover a cache from a package name.

Flake-provided configuration is also accepted automatically through the existing nix.settings.accept-flake-config = true setting. A cached build must match the exact package derivation and platform; changing inputs can require a local build.

The former Garnix cache is excluded because its hosted service shut down on July 15, 2026.

Verification:

# Show only the effective cache URLs and public signing keys
nix config show --json | jq '{substituters: .substituters.value, "trusted-public-keys": ."trusted-public-keys".value}'

Development Environment Integration

Global Direnv Support

This configuration provides comprehensive direnv integration that works seamlessly across all terminals and editors:

Features

  • Universal Support: Works in VSCode, Cursor, and any terminal application
  • Multi-shell: Supports both zsh and bash shells
  • Login Shell Compatibility: Properly configured for login shells spawned by editors
  • Auto-loading: Direnv hooks are loaded automatically without manual setup

How it Works

The global direnv integration is implemented through:

  1. Profile-level hooks: Added to .zprofile and .bash_profile for login shells
  2. Interactive shell integration: Built-in home-manager direnv support
  3. Global PATH configuration: Ensures direnv is available system-wide
  4. Redundant loading protection: Prevents duplicate initialization

Verification

# Test direnv in different shell contexts
zsh -l -c 'command -v _direnv_hook && echo "✓ direnv loaded in zsh"'
bash -l -c 'command -v _direnv_hook && echo "✓ direnv loaded in bash"'
direnv --version  # Should show installed version

This means when you open a project with a .envrc file in any editor, the environment will be automatically activated in all terminal sessions without additional configuration.

Common Commands

Configuration Management

# Apply home-manager configuration
home-manager switch --flake .

# Apply nix-darwin system configuration
sudo darwin-rebuild switch --flake .#codecraft

# Build configuration without switching
home-manager build --flake .

# Preview changes (dry run)
home-manager switch --flake . -n

# Update flake dependencies
nix flake update

# Check configuration validity
nix flake check

Development Commands

# Show flake outputs
nix flake show

# Update specific input
nix flake lock --update-input <input-name>

# Run garbage collection
nix-collect-garbage -d

Customization

Adding Packages

Edit home.nix and add packages to the home.packages list:

home.packages = [
  pkgs.your-package
  # ... other packages
];

Modifying Configuration

The configuration is modular. Key files to modify:

  • home.nix: Main package list and basic settings
  • home/AGENTS.md: Shared global instructions for supported coding agents, held to a word budget (see Context Budget)
  • home/claude/: Authored Claude Code settings, agents, commands, and hooks
  • home/claude-code.nix: Claude Code file ownership and runtime-state boundary
  • home/nix/default.nix: User Nix settings
  • home/nix/caches.nix: Binary cache URLs and public signing keys
  • home/shell.nix: Shell configuration and direnv integration
  • flake.nix: Add new input flakes or change system configurations

Adding Binary Caches

Add the cache URL and its complete public signing key to the caches attribute set in home/nix/caches.nix:

"https://your-cache.cachix.org" = "your-cache.cachix.org-1:your-public-key=";

Apply with home-manager switch --flake .#sadjow. If the change includes a new untracked file, use home-manager switch --flake 'path:.#sadjow' so Nix includes it.

Architecture

Key Design Decisions

  • Flake-based: Uses Nix flakes for improved reproducibility and dependency management
  • Modular: Configuration split into logical modules for easier maintenance
  • macOS Optimized: Specifically configured for Apple Silicon (aarch64-darwin)
  • External Dependencies: Important tools like Claude Code managed as separate flakes
  • Binary Caching: Multiple cache sources for fast package installation
  • Agent Harness Skill Lineage: Keeps portable personal capabilities while deriving independent project-owned copies or adaptations (see Agent Harness Skill Lineage)
  • Channel Strategy: Uses nixpkgs-unstable for latest packages (see Channel Strategy Documentation)

System Compatibility

  • Platform: macOS (Apple Silicon / aarch64-darwin)
  • Nix Version: Compatible with Nix 2.19+
  • Home Manager: Uses latest stable release

Troubleshooting

Common Issues

  1. Flake evaluation errors:

    nix flake check --show-trace
  2. Binary cache issues:

    nix store ping --store https://cache-url.org
  3. Home Manager conflicts:

    home-manager switch --flake . --show-trace

Getting Help

Related Projects

  • claude-code-nix: Dedicated Nix package for Claude Code
  • devenv: Fast, declarative development environments

License

This configuration is provided as-is for personal use. Feel free to adapt it for your own needs.


Note: This configuration is personalized for user "sadjow". You'll need to update usernames, paths, and personal preferences when adapting it for your own use.

About

My home-manager configuration with nix.

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages