diff --git a/caesium.nixos.nix b/caesium.nixos.nix index fb547e3..2fbc6aa 100644 --- a/caesium.nixos.nix +++ b/caesium.nixos.nix @@ -186,7 +186,6 @@ python3 nodejs_26 home-manager - fastfetch ]; programs.appimage = { diff --git a/cleo.darwin.nix b/cleo.darwin.nix index ae13a23..25c9757 100644 --- a/cleo.darwin.nix +++ b/cleo.darwin.nix @@ -1,30 +1,77 @@ -{ pkgs, inputs, ... }: { - nixpkgs.config.allowUnfree = true; - nixpkgs.overlays = [ - inputs.nix-vscode-extensions.overlays.default - # ==== Temp workaround for VSCODE - ## https://github.com/nixos/nixpkgs/issues/543690 as of 2026-07-20 - (final: prev: { - vscode = prev.vscode.overrideAttrs (oldAttrs: { - postPatch = builtins.replaceStrings - [ "Contents/Resources/app/node_modules/@vscode/ripgrep-universal" ] - [ "Contents/Resources/app/node_modules.asar.unpacked/@vscode/ripgrep-universal" ] - (oldAttrs.postPatch or ""); - }); - }) - ]; +{ pkgs, lib, inputs, ... }: +let + ansibleRequired = { + taps = [ + "fwdcloudsec/granted" # aws sso utility + "felipeelias/tap" # claude-statusline + "f1bonacc1/tap" # process-compose + "oven-sh/bun" # bun + "sst/tap" # opencode + ]; + brews = [ + "allure" + "aws-sso-util" + "awscli" + "ccusage" + "fd" + "f1bonacc1/tap/process-compose" + "felipeelias/tap/claude-statusline" + "oven-sh/bun/bun" + "fwdcloudsec/granted/granted" + "gdal" + "gh" + "jq" + "maven" + "rg" + "snyk-cli" + "sst/tap/opencode" + + ## Excluded intentionally + # "libpq@17" + # "node@22" + ]; + casks = [ + "1password-cli" + "aws-vpn-client" + "chromedriver" + "claude-code" # stable channel; playbook can opt into claude-code@latest + "copilot-cli" + "docker-desktop" + "expo-orbit" + "zulu@17" + "ngrok" + + ## Excluded intentionally + # "visual-studio-code" # app installed by brew; home-manager owns settings + extensions + # "jetbrains-toolbox" + ]; + }; +in { ids.gids.nixbld = 350; security.pam.services.sudo_local.touchIdAuth = true; - # 1Password SSH Socket - environment.variables.SSH_AUTH_SOCK = "~/Library/Group Containers/2BU8OCWD5C.com.1password/t/agent.sock"; - # Set vim as default editor environment.variables.EDITOR = "vim"; environment.variables.VISUAL = "vim"; environment.variables.GIT_EDITOR = "vim"; environment.variables.HOMEBREW_NO_ANALYTICS = "1"; + environment.systemPackages = with pkgs; [ + vim + git + wget + curl + python3 + postgresql_17 + home-manager + ttyd + xcodes + xz + # node 22 pinned to the exact version cleo-app requires (nixpkgs-nodejs in flake.nix) + pinnedNode.nodejs_22 + pinnedNode.yarn + ]; + # Add Homebrew to PATH environment.systemPath = [ "/opt/homebrew/bin" "/opt/homebrew/sbin" "/Users/matthew.bessette/.local/bin" ]; @@ -43,47 +90,45 @@ onActivation.cleanup = "uninstall"; onActivation.autoUpdate = true; onActivation.upgrade = true; - onActivation.extraFlags = [ "--force" ]; # global.autoUpdate = true; - taps = [ - "f1bonacc1/tap" - ]; - brews = [ + # Each list is (ansible-managed set) ++ (nix-only extras), deduped. With + # cleanup = "uninstall" above, anything NOT listed here gets removed on + # activation — so ansibleRequired must be merged in or nix would clobber it. + taps = lib.unique (ansibleRequired.taps ++ [ + # nix-only taps go here + ]); + brews = lib.unique (ansibleRequired.brews ++ [ "biome" - - # CLEO APP - "ccache" - "rbenv" - "ruby-build" - - "f1bonacc1/tap/process-compose" - - # DEV - "mise" - ]; - casks = [ - - # CLEO APP - "zulu@17" + "jira-cli" + "treehouse" + ]); + # visual-studio-code is installed by Homebrew (in ansibleRequired.casks) so + # Homebrew owns the .app; home-manager (cleo.home.nix) owns settings + + # extensions only (programs.vscode with package = null) — no second copy. + casks = lib.unique (ansibleRequired.casks ++ [ "android-commandlinetools" "android-platform-tools" - ### - - "1password-cli" - "bruno" + "bruno" "claude" - "claude-code" - "docker-desktop" + "figma" "super-productivity" - "kopiaui" - "libreoffice" + "kopiaui" + "libreoffice" "obsidian" "postico" "sublime-text" "spotify" "yubico-yubikey-manager" "zoom" - ]; + ]); + + masApps = { + BetterSnapTool = 417375580; + HiddenBar = 1452453066; + # "Jamf Trust" = 1608041266; + MeetingBar = 1518425043; + Wireguard = 1451685025; + }; }; nix.settings.experimental-features = "nix-command flakes"; diff --git a/cleo.home.nix b/cleo.home.nix index cc90020..0ee1dfd 100644 --- a/cleo.home.nix +++ b/cleo.home.nix @@ -1,4 +1,4 @@ -{ config, pkgs, inputs, ... }: +{ config, lib, pkgs, inputs, ... }: let oldPkgs = import inputs.nixpkgs-nodejs { system = pkgs.stdenv.hostPlatform.system; @@ -6,47 +6,14 @@ let }; in { - home.stateVersion = "23.11"; - home.username = "matthew.bessette"; home.homeDirectory = "/Users/matthew.bessette"; - home.packages = with pkgs; [ - # Dev Specs - python3 - pipenv + home.packages = with pkgs; []; - opencode - github-copilot-cli - gh - jira-cli-go - - # DB - postgresql_16 # pgdump/restore - - # CLI Tools from your Brewfile - xz - ffmpeg - earthly - awscli2 - buf - - # pkg managers - uv - xcodes - - ## Tooling - fd - granted - ttyd - ] ++ [ - oldPkgs.nodejs_22 - oldPkgs.yarn - ]; - - # Managed VS Code Extensions (The "Clean" Way) programs.vscode = { enable = true; + mutableExtensionsDir = false; profiles.default = { userSettings = builtins.fromJSON (builtins.readFile ./config.vscode.settings.json); extensions = ( @@ -70,59 +37,19 @@ in }; }; - programs.starship = { + # mise runtime manager — installed by nix. Zsh integration is disabled + # because `mise activate zsh` registers a precmd hook that re-evaluates the + # environment before every prompt, causing a per-command shell delay. + # Tools still resolve via shims on PATH (see home.sessionPath below); this + # trades away mise's per-directory env-var auto-loading for prompt speed. + programs.mise = { enable = true; - enableZshIntegration = true; - - settings = { - add_newline = false; - character = { - success_symbol = "[❯](bold green)"; - error_symbol = "[❯](bold red)"; - }; - }; + enableZshIntegration = false; }; - # Automatically load the 1Password agent in your shell - programs.zsh = { - enable = true; - enableCompletion = true; - autosuggestion.enable = true; - syntaxHighlighting.enable = true; - profileExtra = '' - eval "$(/opt/homebrew/bin/brew shellenv)" - ''; - - initContent = '' - export JIRA_API_TOKEN=$(security find-generic-password -a "$USER" -s "jira-token" -w 2>/dev/null) - export SSH_AUTH_SOCK=~/Library/Group\ Containers/2BUA8C4S2C.com.1password/t/agent.sock - - # Auto-allow direnv for directories with flake.nix - auto_allow_direnv() { - if [[ -f flake.nix ]] && [[ ! -f .envrc ]]; then - echo "use flake" > .envrc - direnv allow - elif [[ -f flake.nix ]] && [[ -f .envrc ]]; then - direnv allow - fi - } - - # Run auto-allow when changing directories - chpwd_functions+=(auto_allow_direnv) - - eval "$(uv generate-shell-completion zsh)" - eval "$(uvx --generate-shell-completion zsh)" - ''; - - shellAliases = { - ll = "ls -l"; - gst = "git status"; - update = "sudo darwin-rebuild switch --flake ~/nixos#cleo-darwin"; - laws = "aws --endpoint=http://localhost:4566"; - dev = "nix develop -c $SHELL"; - nixos = "code ~/nixos"; - assume = "source assume"; - }; + programs.zsh.shellAliases = { + laws = "aws --endpoint=http://localhost:4566"; + assume = "source $(brew --prefix)/bin/assume"; }; home.sessionVariables = { @@ -134,90 +61,101 @@ in # Stub SDK root so tools that require ANDROID_HOME/platform-tools/adb work # even though adb is managed by Homebrew (android-platform-tools cask). ANDROID_HOME = "${config.home.homeDirectory}/android-sdk"; + # Runtime lookup from Apple Keychain — only the command, not the token, is in the store. + JIRA_API_TOKEN = ''$(security find-generic-password -a "$USER" -s jira-token -w 2>/dev/null)''; + + # Parity with the ANSIBLE MANAGED BLOCKs the playbook writes to ~/.zshrc. + DOCKER_CLI_HINTS = "false"; + GRANTED_ENABLE_AUTO_REASSUME = "true"; + COPILOT_OTEL_ENABLED = "true"; + COPILOT_OTEL_EXPORTER_TYPE = "file"; + # Timestamped per session, like the ansible line (command substitution is intentional). + COPILOT_OTEL_FILE_EXPORTER_PATH = ''$HOME/.copilot/otel/copilot-otel-$(date +%Y%m%d-%H%M%S).jsonl''; }; home.sessionPath = [ "${config.home.homeDirectory}/.npm-global/bin" + "${config.home.homeDirectory}/.local/share/mise/shims" ]; + # git credential.helper=osxkeychain (parity with tasks/git.yml). Darwin-only, so + # it lives here rather than in the cross-platform home.shared.nix. + programs.git.settings.credential.helper = "osxkeychain"; + home.file.".npmrc".text = '' prefix=${config.home.homeDirectory}/.npm-global '' ; - programs.ghostty = { - enable = true; - - # Automatically hooks shell history, title updates, and cwd tracking - enableBashIntegration = true; - enableZshIntegration = true; - enableFishIntegration = true; - - settings = { - # Visuals & Theme - theme = "catppuccin-mocha"; - font-family = "JetBrainsMono Nerd Font"; - font-size = 12; - - # Window Spacing - window-padding-x = 12; - window-padding-y = 12; - window-padding-balance = true; - - # UI Preferences - window-decoration = true; # Set to false if using a tiling window manager (Hyprland/i3) - gtk-single-instance = true; - confirm-close-surface = false; # Don't prompt when closing a pane - - # Cursor Customization - cursor-style = "block"; - cursor-style-blink = false; - - # Mouse & Scrolling - mouse-hide-while-typing = true; - scrollback-limit = 10000; - - # Keybindings (Alt/Super splits & tabs) - keybind = [ - "alt+shift+e=new_split:right" - "alt+shift+o=new_split:down" - "alt+w=close_surface" - "alt+t=new_tab" - "alt+1=goto_tab:1" - "alt+2=goto_tab:2" - "alt+3=goto_tab:3" - ]; - }; - }; - - home.file.".config/1Password/ssh/agent.toml".source = ./config.agent.toml; # Stub Android SDK directory so ANDROID_HOME/platform-tools/adb resolves to # the adb binary installed by the android-platform-tools Homebrew cask. home.file."android-sdk/platform-tools/adb".source = config.lib.file.mkOutOfStoreSymlink "/opt/homebrew/bin/adb"; home.file."android-sdk/cmdline-tools/latest/bin/sdkmanager".source = config.lib.file.mkOutOfStoreSymlink "/opt/homebrew/bin/sdkmanager"; - xdg.configFile."opencode/opencode.jsonc".source = config.lib.file.mkOutOfStoreSymlink "/Users/matthew.bessette/nixos/config.opencode.jsonc"; xdg.configFile."oxlint/oxlintrc.json".source = config.lib.file.mkOutOfStoreSymlink "/Users/matthew.bessette/nixos/config.oxlintrc.json"; xdg.configFile."biome/biome.json".source = config.lib.file.mkOutOfStoreSymlink "/Users/matthew.bessette/nixos/config.biome.json"; - programs.tmux.enable = true; + # --- Tool config parity with local-dev-ansible (tasks/config/*) --- + # Note: ~/.aws/config is intentionally NOT managed here — `aws-sso-util configure + # populate` must rewrite it at runtime, which a read-only nix symlink would block. + # Run once after switch: + # aws-sso-util configure populate \ + # --sso-start-url https://d-9067516d20.awsapps.com/start \ + # --sso-region us-east-1 --region us-east-1 --config-default output=json - programs.git = { - enable = true; - - settings.user = { - name = "Matthew Bessette"; - email = "matthew.bessette@hicleo.com"; + # GitHub Copilot CLI (tasks/config/copilot.yml) + home.file.".copilot/settings.json".text = builtins.toJSON { + footer = { + showModelEffort = true; + showBranch = true; + showDirectory = true; + showContextWindow = true; + showQuota = true; + showAgent = true; }; - - settings.init.defaultBranch = "main"; - - # This creates ~/.config/git/ignore and sets core.excludesFile - ignores = [ - "biome.json" - "flake.lock" - "flake.nix" - ".DS_Store" - ".direnv" - ".envrc" - ]; }; + + # opencode (tasks/config/opencode.yml) + xdg.configFile."opencode/opencode.json".text = builtins.toJSON { + "$schema" = "https://opencode.ai/config.json"; + model = "github-copilot/gpt-5.4"; + plugin = [ "@slkiser/opencode-quota" ]; + autoupdate = false; + }; + xdg.configFile."opencode/tui.json".text = builtins.toJSON { + "$schema" = "https://opencode.ai/tui.json"; + plugin = [ "@slkiser/opencode-quota" ]; + }; + xdg.configFile."opencode/opencode-quota/quota-toast.json".text = builtins.toJSON { + enabledProviders = "auto"; + percentDisplayMode = "used"; + enableToast = false; + tuiCompactStatus.enabled = false; + tuiSidebarPanel.enabled = true; + maintainerAnnouncements = { enabled = false; home = false; }; + }; + + # Claude Code settings (tasks/config/claude-code.yml) — cleo-scoped override of the + # shared config.claude.json, since claude-statusline is only installed on cleo. + # mkForce wins over home.shared.nix's `.source = ./config.claude.json`. + xdg.configFile."claude/settings.json".source = lib.mkForce (pkgs.writeText "claude-settings.json" (builtins.toJSON { + "$schema" = "https://json.schemastore.org/claude-code-settings.json"; + theme = "dark"; + agent = "plan"; + denyCommands = [ "code --install-extension*" ]; + additionalDirectories = [ "/tmp" ]; + autoMemoryEnabled = false; + effortLevel = "medium"; + fastModePerSessionOptIn = true; + feedbackSurveyRate = 0; + model = "opusplan"; + showClearContextOnPlanAccept = false; + statusLine = { type = "command"; command = "claude-statusline prompt"; }; + })); + xdg.configFile."claude-statusline/config.toml".text = '' + format = "$directory | $git_branch | $model | $cost | $context | $usage" + preset = "default" + + [usage] + disabled = false + format = 'S: {{printf "%.0f" .BlockPct}}% ({{.BlockResets}}) | W: {{printf "%.0f" .WeeklyPct}}%' + ''; } \ No newline at end of file diff --git a/config.opencode.jsonc b/config.opencode.jsonc deleted file mode 100644 index 38cbb2e..0000000 --- a/config.opencode.jsonc +++ /dev/null @@ -1,57 +0,0 @@ -{ - "$schema": "https://opencode.ai/config.json", - "model": "github-copilot/claude-sonnet-4.6", - "instructions": [], - "plugin": ["opencode-copilot-1m"], - "provider": {}, - "lsp": true, - "permission": { - "external_directory": { - "~/Projects/**": "allow", - "/tmp": "allow" - } - }, - "agent": { - "plan": { - "mode": "primary", - "model": "github-copilot/claude-opus-4.8-1m", - "prompt": "Architect agent. Analyzes codebase and outputs a hyper-specific, step-by-step technical blueprint into .opencode_blueprint.md. Does NOT write feature code.", - "permission": { "edit": "allow", "bash": "allow" } - }, - "execute": { - "model": "github-copilot/claude-sonnet-4.6-1m", - "temperature": 0.2, - "prompt": "Orchestrator agent. Reads .opencode_blueprint.md, breaks tasks into micro-steps, and delegates individual file edits/terminal tasks to subagents. Your primary job is delegation and verification.", - "permission": { "edit": "allow", "bash": "allow" } - }, - "build": { - "model": "github-copilot/claude-sonnet-4.6-1m", - "temperature": 0.2, - "permission": { "edit": "allow", "bash": "allow" } - }, - "general": { - "mode": "subagent", - "model": "github-copilot/claude-haiku-4.5", - "temperature": 0.1, - "prompt": "Execution subagent. Takes a single, isolated task and explicit file paths provided by the Build orchestrator. Do not blind-search; rely strictly on paths given.", - "permission": { "edit": "allow", "bash": "allow" } - }, - "explore": { - "model": "github-copilot/claude-haiku-4.5" - } - }, - "autoupdate": false, - "server": { - "port": 4096 - }, - "mcp": { - "figma": { - "type": "remote", - "url": "http://127.0.0.1:3845/mcp" - }, - "ios-simulator": { - "type": "local", - "command": ["npx", "-y", "ios-simulator-mcp"] - } - } -} diff --git a/flake.nix b/flake.nix index b629a58..30b7b53 100644 --- a/flake.nix +++ b/flake.nix @@ -59,6 +59,7 @@ linuxSystem = "x86_64-linux"; darwinSystem = "aarch64-darwin"; mkOverlays = sys: [ + inputs.nix-vscode-extensions.overlays.default (final: prev: { unstable = import nixpkgsUnstable { system = sys; diff --git a/home.shared.nix b/home.shared.nix index 3c75e2b..d222597 100644 --- a/home.shared.nix +++ b/home.shared.nix @@ -6,6 +6,9 @@ let ghosttyPkg = if pkgs.stdenv.isDarwin then pkgs."ghostty-bin" else pkgs.ghostty; + rebuildCmd = if pkgs.stdenv.isDarwin + then "darwin-rebuild" + else "nixos-rebuild"; in { home.stateVersion = lib.mkDefault "26.05"; home.username = userConfig.username; @@ -22,6 +25,9 @@ in { vault = "${userConfig._1PassKeyVault}" ''; + programs.tmux.enable = true; + programs.fastfetch.enable = true; + programs.zsh = { enable = true; enableCompletion = true; @@ -31,7 +37,7 @@ in { shellAliases = { ll = "ls -l"; gst = "git status"; - nix-update = "sudo nixos-rebuild switch --flake ~/nixos#${hostname}"; + nix-update = "sudo ${rebuildCmd} switch --flake ~/nixos#${hostname}"; home-update = "home-manager switch --flake ~/nixos#${userConfig.username}@${hostname}"; }; }; @@ -43,7 +49,7 @@ in { # Optional custom settings (translates to ~/.config/starship.toml) settings = { # Line 1: ➜ folder git:(branch) [status] - format = "$character$directory$git_branch\${custom.git_dirty} "; + format = "$character$directory$git_branch"; # Show current directory name only directory = { @@ -54,7 +60,7 @@ in { # git:(branch) styling git_branch = { - format = "[git:\\([$branch](red)\\)](bold blue)"; + format = "[git:\\([$branch](red)\\)](bold blue) "; }; # Bottom line prompt arrow @@ -64,9 +70,8 @@ in { vicmd_symbol = "[➜](bold yellow)"; }; - custom.git_dirty = { - when = "test -n \"$(git status --porcelain 2>/dev/null)\""; - format = " [✘](yellow)"; + git_status = { + disabled = false; }; # Nix shell indicator module configuration @@ -85,6 +90,7 @@ in { "*" = { ControlMaster = "auto"; ControlPath = "~/.ssh/master-%r@%h:%p"; + ControlPersist = "10m"; IdentityAgent = "\"${onePassPath}\""; }; }; @@ -106,5 +112,13 @@ in { package = ghosttyPkg; enableBashIntegration = true; enableZshIntegration = true; + settings = { + macos-icon = "chalkboard"; + keybind = [ + "home=text:\\x01" # Ctrl-A -> beginning of line + "end=text:\\x05" # Ctrl-E -> end of line + "delete=text:\\x7f" + ]; + }; }; } diff --git a/hydrogen.darwin.nix b/hydrogen.darwin.nix index 113942a..3396566 100644 --- a/hydrogen.darwin.nix +++ b/hydrogen.darwin.nix @@ -1,6 +1,5 @@ { pkgs, inputs, ... }: { nixpkgs.config.allowUnfree = true; - nixpkgs.overlays = [ inputs.nix-vscode-extensions.overlays.default ]; ids.gids.nixbld = 350; security.pam.services.sudo_local.touchIdAuth = true; @@ -19,7 +18,6 @@ python3 nodejs_26 home-manager - fastfetch ]; homebrew = {