diff --git a/AGENTS.md b/AGENTS.md index b45e563..3d631f8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,5 +2,5 @@ Deliberate decisions in this repo - do NOT silently revert them: -- `homebrew.onActivation.cleanup = "zap"` in `configuration.nix` is intentional. It forces the good habit of declaring every Homebrew package in the Nix config instead of installing things ad-hoc, which keeps the machine reproducible. Do not soften it to `uninstall` or `none`. Users are warned about its effect in README.md; this note is for anyone tempted to change the setting itself. -- Never commit `.no-mistakes/` validation evidence to this public repo. `.no-mistakes/` is gitignored; if a validation pipeline stages evidence into a branch, drop it before merging. \ No newline at end of file +- `homebrew.onActivation.cleanup = "none"` in `configuration.nix` is intentional for first adoption on an existing Mac. Do not change it to `zap` until every Homebrew package and cask that should be kept has been declared in `configuration.nix`. +- Never commit `.no-mistakes/` validation evidence to this public repo. `.no-mistakes/` is gitignored; if a validation pipeline stages evidence into a branch, drop it before merging. diff --git a/README.md b/README.md index 928c0e4..c02ad57 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Running the switch builds: - Shell (zsh, aliases, starship prompt) - Editor (Neovim config) - Terminal (WezTerm config) -- Agent configs (Claude, Codex, opencode all share one AGENTS.md) +- Dotfile symlinks for Neovim, WezTerm, and herdr ## Prerequisites @@ -84,8 +84,8 @@ No separate build-and-copy step. This repo is mine. If you clone it, review these before you run `bootstrap.sh`: -- **Username**: run `./bootstrap.sh` (it detects your macOS username and offers to set it) OR change the single `user = "kunchen"` line in `flake.nix`. - Everything else (`configuration.nix`, `home.nix`, home directory paths) is threaded from that one variable. +- **Username**: this copy is configured for `user = "bytedance"` in `flake.nix`. + The home directory is explicitly set to `/Users/bytedance` in `configuration.nix` and `home.nix`. - **Host label** `"mac"`, in three places: `flake.nix` (the `darwinConfigurations."mac"` name), `rebuild.sh:5` (the `#mac` at the end of the flake reference), and `bootstrap.sh`'s first-switch command (also `#mac`). All three have to match. - **CPU architecture**, `hostPlatform` in `configuration.nix` (see Prerequisites above). @@ -104,10 +104,9 @@ programs.git = { }; ``` -**Homebrew cleanup warning:** `configuration.nix` sets `homebrew.onActivation.cleanup = "zap"`. -That means every time you switch, Homebrew removes any package or cask on your machine that isn't listed in the `brews` and `casks` arrays in `configuration.nix`. -If you already have Homebrew stuff installed that isn't in that list, the first switch will uninstall it. -Read through `brews` and `casks` before you run `bootstrap.sh` or `rebuild.sh` for the first time, and add anything you want to keep. +**Homebrew cleanup warning:** this copy starts with `homebrew.onActivation.cleanup = "none"`. +That keeps existing Homebrew packages and casks on the first switch, which is safer on a Mac that already has software installed. +After everything you want to keep is listed in the `brews` and `casks` arrays in `configuration.nix`, you can choose whether to tighten this later. **About `herdr`:** it's in the `brews` list. It's a real public Homebrew formula (`brew info herdr` finds it in homebrew-core, no tap needed), so it will install fine. @@ -115,10 +114,9 @@ If you don't use it, just remove it from `brews` in your copy. **Heads-up:** -- `home/AGENTS.md` is my personal agent policy, and `home.nix` installs it for Claude, Codex, and opencode. - If you clone this repo, you'd silently inherit my agent instructions - edit or delete `home/AGENTS.md` if you don't want that. -- The `cc` and `co` shell aliases in `home.nix` are high-agency shortcuts: `claude --dangerously-skip-permissions` and `codex --full-auto`. - They're convenient for me, but know what they do before you use them. +- `home/AGENTS.md` is kept as an optional template only. This copy does not install it over local Claude, Codex, or opencode instruction files. +- `home/.claude/settings.json` is kept in the repo as an optional template only. This copy does not install it over local Claude settings. +- The `cc` and `co` shell aliases in `home.nix` are conservative shortcuts for `claude` and `codex`. ## Repo tour @@ -128,7 +126,7 @@ If you don't use it, just remove it from `brews` in your copy. - `home.nix` - user-level config: shell, packages, prompt, and the symlinks described below. - `rebuild.sh` - re-applies the config after the first switch. Run this every time you make a change. -- `home/` - the actual config files that get symlinked into place (Neovim, WezTerm, herdr, Claude settings, the shared `AGENTS.md`). +- `home/` - the actual config files that get symlinked into place (Neovim, WezTerm, herdr). `home/AGENTS.md` and `home/.claude/settings.json` are optional templates and are not installed automatically. ## How the symlinks work diff --git a/configuration.nix b/configuration.nix index 74baa39..4bdac15 100644 --- a/configuration.nix +++ b/configuration.nix @@ -1,4 +1,4 @@ -{ user, ... }: +{ pkgs, user, ... }: { # Determinate already manages the Nix daemon, so nix-darwin shouldn't. @@ -7,31 +7,43 @@ nixpkgs.config.allowUnfree = true; nixpkgs.hostPlatform = "aarch64-darwin"; # use x86_64-darwin for Intel CPU + fonts.packages = with pkgs; [ + nerd-fonts.hack + ]; + system.primaryUser = user; users.users.${user} = { - home = "/Users/${user}"; + home = "/Users/bytedance"; }; system.stateVersion = 6; system.defaults = { NSGlobalDomain = { - AppleInterfaceStyle = "Dark"; KeyRepeat = 2; # fast key repeat InitialKeyRepeat = 15; # short delay before repeat _HIHideMenuBar = true; # auto-hide the menu bar AppleShowAllExtensions = true; + "com.apple.mouse.tapBehavior" = 1; # tap to click }; dock.autohide = true; finder.FXPreferredViewStyle = "Nlsv"; # list view by default finder.CreateDesktop = false; # clean desktop trackpad.Clicking = true; # tap to click }; + system.activationScripts.postActivation.text = '' + # Keep local UI choices that nix-darwin does not fully model as first-class defaults. + launchctl asuser "$(id -u -- ${user})" sudo --user=${user} -- defaults delete -g AppleInterfaceStyle >/dev/null 2>&1 || true + launchctl asuser "$(id -u -- ${user})" sudo --user=${user} -- defaults -currentHost write -g com.apple.mouse.tapBehavior -int 1 + killall -qu ${user} cfprefsd || true + killall -qu ${user} SystemUIServer || true + ''; nix-homebrew = { enable = true; + autoMigrate = true; inherit user; }; homebrew = { enable = true; - onActivation.cleanup = "zap"; # remove anything not listed here + onActivation.cleanup = "none"; # first switch: keep existing Homebrew installs onActivation.autoUpdate = true; onActivation.extraFlags = [ "--force" ]; brews = [ diff --git a/flake.nix b/flake.nix index 96b6b8d..16ef865 100644 --- a/flake.nix +++ b/flake.nix @@ -18,7 +18,7 @@ let # The one username line to change if this isn't your machine. # bootstrap.sh offers to rewrite this for you if your macOS username differs. - user = "kunchen"; + user = "bytedance"; in { darwinConfigurations."mac" = nix-darwin.lib.darwinSystem { @@ -30,6 +30,7 @@ { home-manager.useGlobalPkgs = true; home-manager.useUserPackages = true; + home-manager.backupFileExtension = "before-nix"; home-manager.extraSpecialArgs = { inherit user; }; home-manager.users.${user} = import ./home.nix; } diff --git a/home.nix b/home.nix index 365a1cb..54cb8a6 100644 --- a/home.nix +++ b/home.nix @@ -6,7 +6,7 @@ in { home.username = user; - home.homeDirectory = "/Users/${user}"; + home.homeDirectory = "/Users/bytedance"; home.stateVersion = "24.11"; home.packages = with pkgs; [ # cli i use constantly @@ -16,11 +16,25 @@ in jq # json on the command line lazygit neovim - # the font everything renders in - nerd-fonts.hack ]; fonts.fontconfig.enable = true; - home.sessionVariables.EDITOR = "nvim"; + home.sessionPath = [ + "${config.home.homeDirectory}/.npm-global/bin" + "${config.home.homeDirectory}/.local/bin" + "${config.home.homeDirectory}/go/bin" + "${config.home.homeDirectory}/flutter/bin" + "${config.home.homeDirectory}/.pub-cache/bin" + "${config.home.homeDirectory}/.larklink/bin" + "${config.home.homeDirectory}/.bun/bin" + "/usr/local/go/bin" + "/opt/homebrew/bin" + ]; + home.sessionVariables = { + EDITOR = "nvim"; + GOPATH = "${config.home.homeDirectory}/go"; + GOROOT = "/usr/local/go"; + BUN_INSTALL = "${config.home.homeDirectory}/.bun"; + }; programs.zsh = { enable = true; @@ -35,8 +49,8 @@ in push = "git push"; pull = "git pull"; m = "git switch main"; - cc = "claude --dangerously-skip-permissions"; - co = "codex --full-auto"; + cc = "claude"; + co = "codex"; }; }; @@ -60,13 +74,6 @@ in config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/.config/nvim"; home.file.".config/herdr".source = config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/.config/herdr"; - home.file.".claude/settings.json".source = - config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/.claude/settings.json"; - - home.file.".claude/CLAUDE.md".source = - config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/AGENTS.md"; - home.file.".codex/AGENTS.md".source = - config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/AGENTS.md"; - home.file.".config/opencode/AGENTS.md".source = - config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/AGENTS.md"; + home.file.".local/share/fonts/hack-nerd-font".source = + "${pkgs.nerd-fonts.hack}/share/fonts/truetype/NerdFonts/Hack"; } diff --git a/home/.config/nvim/lua/plugin.lua b/home/.config/nvim/lua/plugin.lua index e528a1c..2c0a597 100644 --- a/home/.config/nvim/lua/plugin.lua +++ b/home/.config/nvim/lua/plugin.lua @@ -1,8 +1,14 @@ local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim' -if not vim.uv.fs_stat(lazypath) then - vim.fn.system({ 'git', 'clone', '--filter=blob:none', +local lazy_init = lazypath .. '/lua/lazy/init.lua' + +if not vim.uv.fs_stat(lazy_init) then + vim.fn.delete(lazypath, 'rf') + local output = vim.fn.system({ 'git', 'clone', '--filter=blob:none', 'https://github.com/folke/lazy.nvim.git', '--branch=stable', lazypath }) + if vim.v.shell_error ~= 0 then + error('Failed to install lazy.nvim:\n' .. output) + end end + vim.opt.rtp:prepend(lazypath) require('lazy').setup('plugins') -- load every file in lua/plugins/ - diff --git a/home/.config/wezterm/wezterm.lua b/home/.config/wezterm/wezterm.lua index 8bb9ce8..6c0288f 100644 --- a/home/.config/wezterm/wezterm.lua +++ b/home/.config/wezterm/wezterm.lua @@ -1,13 +1,29 @@ local wezterm = require("wezterm") +local act = wezterm.action local config = wezterm.config_builder() config.color_scheme = "rose-pine-moon" -config.font = wezterm.font("Hack Nerd Font") +config.font_dirs = { + os.getenv("HOME") .. "/.local/share/fonts/hack-nerd-font", +} +config.font = wezterm.font("Hack Nerd Font Mono") config.font_size = 15.0 config.window_background_opacity = 0.8 config.macos_window_background_blur = 50 config.hide_tab_bar_if_only_one_tab = true config.window_decorations = "RESIZE" +config.keys = { + { + key = "d", + mods = "CMD", + action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }), + }, + { + key = "d", + mods = "CMD|SHIFT", + action = act.SplitVertical({ domain = "CurrentPaneDomain" }), + }, +} return config diff --git a/home/AGENTS.md b/home/AGENTS.md index f9145ba..aa272f7 100644 --- a/home/AGENTS.md +++ b/home/AGENTS.md @@ -1,15 +1,12 @@ -# global agent instructions - -- Never use the em dash "—". Use plain dash "-" instead -- When writing commit messages, NEVER auto-add your agent name as co-author -- Never manually modify CHANGELOG.md files or any files that are marked as auto-generated -- When making technical decisions, do not give much weight to development cost. - Instead, prefer quality, simplicity, robustness, scalability, and long term maintainability. -- When doing bug fixes, always start with reproducing the bug in an E2E setting as closely aligned with how an end user would experience it as possible. - This makes sure you find the real problem so your fix will actually solve it. -- When end-to-end testing a product, be picky about the UI you see and be obsessed with pixel perfection. - If something clearly looks off, even if it is not directly related to what you are doing, try to get it fixed along the way. -- Apply that same high standard to engineering excellence: lint, test failures, and test flakiness. - If you see one, even if it is not caused by what you are working on right now, still get it fixed. +# Global agent instructions +- Use Chinese for user-facing replies by default. +- Do not use em dashes. Use plain hyphens instead. +- When writing commit messages, never auto-add your agent name as co-author. +- Never manually modify CHANGELOG.md files or any files marked as auto-generated. +- Protect existing user changes. Do not reset, stash, overwrite, or delete unrelated work unless explicitly asked. +- Keep changes surgical. Match the existing style and touch only the files needed for the task. +- Prefer simple, robust, maintainable solutions over shortcuts chosen only to reduce development effort. +- When fixing bugs, reproduce the issue first in a setting close to how the user experiences it. +- Verify meaningful changes with focused tests, lint, type checks, or a clear manual check when automated tests are unavailable.