Back to Kun Chen

L8 Principal's Agentic Coding Config Fom Scratch

Kun ChenJuly 5, 202644m
In a Nutshell

The video demonstrates building a fully reproducible agentic coding environment on macOS from scratch using Nyx (Nix) for declarative system configuration, Home Manager for user-level setup, and a Git-managed dotfiles repo. Core components include WezTerm, Zsh with Starship, a modular Neovim setup with Lazy.nvim plugins (Snacks, Oil, Neogit, gitsigns, which-key), and Herder as the terminal multiplexer optimized for parallel AI agent sessions. A global memory file (agents.md) enforces consistent agent behavior across tools, with all configs linked and restorable via a single rebuild script.

AI-Generated Notes

These notes were generated by AI and may contain inaccuracies.

The speaker begins setting up a complete agentic engineering development environment from scratch on a freshly installed Mac Mini. Only basic items like Chrome, Git, and an SSH key for GitHub were pre-installed. The goal is full reproducibility so configurations can be applied identically to another machine or recovered instantly if an AI agent damages the system.

Nyx is introduced as the solution for declarative and reproducible configuration. Although primarily designed for Nyx OS (Linux-based), a portable installer called Determinate Nyx works on Mac. The speaker runs the install command, confirms with yes, then executes the follow-up command to refresh the environment. Nyx is now properly set up.

A new GitHub repository named "files" is created and initialized with Git. This will be published publicly after the video. A symbolic link is created at a fixed location in the home directory pointing to the current directory so all later scripts can reference a stable path regardless of where the actual git clone exists.

Nyx Darwin is used to configure Mac OS settings declaratively. The speaker creates a flake.nix file using the boilerplate content, changing the username references from "John" to "Mac" and pinning both the Nyx Darwin and Nixpkgs inputs from unstable to specific stable version numbers to avoid surprises. A configuration.nix file is created with minimal settings: nix.enable set to false (since Determinate manages the installation), allowUnfree enabled, hostPlatform set to aarch64-darwin for Apple Silicon, the primary user username specified, and stateVersion set to "6" and left untouched thereafter.

The configuration is activated by first tracking all files under Git, then running darwin-rebuild switch --flake .#mac. The first run takes significant time. A helper script rebuild.sh is created that repeats this exact command, made executable, allowing future updates to be applied simply by running ./rebuild.sh.

System preferences are configured through configuration.nix including dark theme, fast key repeat with short delay, autohiding the menu bar, always showing file extensions, autohiding the dock, list view for Finder, a clean desktop showing only the wallpaper, and enabling trackpad tap-to-click. These settings are applied via another rebuild, immediately changing dock behavior to autohide.

Homebrew is installed as a Nyx package rather than through the website script for reproducibility. The nix-homebrew input is added to flake.nix along with the corresponding module. In configuration.nix, Homebrew is enabled with cleanup = "zap" so that each rebuild removes any Homebrew packages not explicitly listed in the Nyx config. This forces all packages to be declared in the configuration. Initial casks listed include WezTerm. After rebuilding, brew --version confirms installation and WezTerm is now available.

Home Manager manages user-directory (home directory) configuration separately from Nyx Darwin's system-level settings. The home-manager input is added to flake.nix with the module and the line home-manager.users.<username> = import ./home.nix;. In configuration.nix, the user's home directory is explicitly set. A home.nix file is created with the username, state version "6", and a symbolic link created from ~/.config/wezterm pointing to the dotfiles repository path so WezTerm configuration lives in version control.

Home Manager installs user-level packages including the Hack Nerd Font. Environment variables are set so the default editor is Neovim. After rebuilding, the font is available without manual download.

Zsh is enhanced through Home Manager with the zsh-autosuggestions and zsh-syntax-highlighting plugins. initExtra content is added directly to .zshrc. A keybinding maps Ctrl+F to accept autosuggestion ghost text. Multiple shell aliases are defined for frequently used commands. After rebuilding and starting a fresh WezTerm session, autosuggestions and syntax highlighting are active.

Starship is installed via Home Manager with basic customization to replace the default shell prompt. After rebuilding, a new WezTerm session shows the cleaner prompt.

WezTerm is configured via wezterm.lua in the symbolic-linked config directory. The configuration returns an object with settings. The rose-pine-moon color scheme is applied first, followed by Hack Nerd Font at size 15. Window background opacity and blur are adjusted. The tab bar is hidden when only one tab exists and the window frame is removed entirely, producing a clean frameless terminal. WezTerm hot-reloads configuration on save.

Neovim configuration begins with creating the ~/.config/nvim directory and init.lua file. A symbolic link is added in home.nix so the Neovim config lives in the dotfiles repo. After rebuilding, Neovim loads successfully.

The init.lua requires two modules: vim-config and plugins. A lua directory is created containing vim-config.lua with sensible defaults: mapleader set to space, expandtab enabled, shiftwidth and tabstop set to 2, absolute and relative line numbers enabled, ignorecase with smartcase for searching, system clipboard integration via unnamedplus, scrolloff set to 16, and persistent undo files. These options are centralized in one file.

Lazy.nvim (by Folke) manages Neovim plugins. The standard bootstrap snippet is pasted into init.lua, configured to load every file in a plugins subdirectory. A plugins directory is created.

A navigation.lua file in the plugins directory installs the Snacks plugin from folke/snacks.nvim with priority 1000 and lazy loading disabled. Options enable picker, notifier, and input. Keybindings are set: leader+F for file picker, leader+S for grep picker, leader+B for buffers picker, and gd for go to definition. After reloading Neovim, Lazy installs the plugin and the pickers become functional.

Oil.nvim is added to the same navigation.lua file with options to show hidden files and a keybinding of leader+E. After restarting Neovim, Oil presents the filesystem as an editable buffer. Files can be copied by yanking and pasting lines then writing the buffer; Oil recognizes the intent and performs the filesystem operation. Deletion works similarly via dd followed by write.

Two plugins are configured in a new git.lua file: Neogit (launched via keybinding) and gitsigns (configured to show git blame on the current line). The gitsigns plugin uses event = "BufWinEnter" for lazy loading. After reloading, Neogit can be launched via the configured keybinding.

A tool is available to review and operate on code changes tracked by Git. This is used frequently to review diffs and to stage changes that have been reviewed and approved.

A plugin called which-key is used to help remember keybindings for plugins. It is placed under a UI configuration file. The plugin is written by Folky. After installation, pressing the leader key (space) displays a popup at the bottom showing available next key presses. This is especially useful when new plugins or keybindings have been added and muscle memory has not yet been developed.

A new require statement is added to the init.lua file pointing to a keys configuration file. This file stores all keybinding-related configuration.

One keybinding configures the ESC key to save the file. In Neovim, edits require entering insert mode, and returning to normal mode is done by pressing ESC. Since saving is typically desired at the same moment as returning to normal mode, this binding allows spamming ESC after useful edits to save the file.

Another keybinding replicates the standard Control-A shortcut for selecting all text, matching behavior found in most other editors.

A third keybinding addresses a counterintuitive default Vim behavior related to registers. When selecting and yanking (copying) text with Y, then selecting other text and pressing P (paste), the default behavior performs replacement. Pressing P again does not replace with the originally yanked content but instead produces unexpected results due to how registers function. The keybinding fixes this by preventing replacement actions from interfering with the clipboard, making the experience more intuitive.

While LSP and Tree-sitter configurations are skipped in favor of existing tutorials, terminal session management becomes critical when working with agents. Multiple agent sessions must be managed in parallel—launching new agents while others work, or reviewing outputs from completed agents. Regular terminal windows make this difficult.

Terminal multiplexers solve this by enabling creation of sessions, windows, tabs, and splitting tabs into panes.

Tmux (terminal multiplexer) is the original popular option and was demonstrated in a previous video. Wezterm includes multiplexing functionality, but Herder is preferred because it was built in the agent era. It understands agents and integrates well with mainstream agent harnesses. After years of Tmux use, Herder provides a better experience and is noted as potentially the only terminal multiplexer that works on Windows.

Herder is installed via the homebrew configuration in configuration.nix. A config directory is created with a config.toml file containing keybindings that preserve Tmux muscle memory. A symbolic link is created to apply the configuration. After rebuilding Nix, Herder displays a side panel organizing workspaces and agents alongside a main terminal area. Tabs can be created, named, and split into panes.

Cloud Code is installed as a cask through homebrew. Its settings are stored in a settings.json file located at ~/.config/claude/. A symbolic link is created for the settings file, followed by a Nix rebuild. When starting Cloud Code inside Herder, basic settings are configured and login is performed.

The status line in Cloud Code is customized using the /statusline command to display the model name and percentage of context window used. Herder displays agent status in its left panel and supports this monitoring consistently across agent harnesses. Real-time monitoring shows information such as "opus 4.8" and "context 2% used" under the prompt line.

A central global memory file ensures consistent agent behavior across different systems (Claude, Codex, Open Code, Pi, Grok, etc.). The file is placed at ~/agents.md within the files repo and contains the following rules:

  • Never use m-dash; use plain dash instead. AI models are trained to use m-dash, which feels robotic in commit messages and PR descriptions.
  • When writing commit messages, never auto-add the agent's name as co-author. This fights against Claude's tendency to do so, as accountability ultimately rests with the human.
  • Never manually modify CHANGELOG.md files or any files marked as autogenerated.
  • When making technical decisions, do not give much weight to development cost. Instead prefer quality, simplicity, robustness, scalability, and long-term maintainability. This counters the tendency of agents (trained on human data) to overestimate development cost and favor cheap but non-scalable solutions.
  • When doing bug fixes, always start by reproducing the bug in an end-to-end setting as closely aligned with actual user experience as possible. This prevents agents from fixing non-existent problems.
  • When end-to-end testing, be picky about UI and obsessed with pixel perfection. Fix issues even if not directly related to current work.
  • Apply the same high standard to engineering excellence. Fix lint failures, test failures, and test flakiness even when not caused by current work.

Home Manager distributes the global memory file to all agents by creating symbolic links to each agent's expected location (Claude uses CLAUDE.md; other agents use different paths). After a rebuild, all agents load the same memory file consistently.

The rebuild script can fully reproduce the entire configuration. From any freshly installed Mac, cloning the files repo and running the rebuild immediately restores the complete setup.

The files repo has been published on GitHub, providing the same development environment demonstrated. Viewers are directed to a previous video on the agentic engineering workflow for guidance on using the setup for actual work.

Keep Kun Chen in your library

Save the videos and channels worth coming back to, and find them again in one place.