switch default shell to zsh and adopt catppuccin mocha
This commit is contained in:
parent
418f0701bc
commit
a58e842817
15 changed files with 391 additions and 160 deletions
|
|
@ -7,8 +7,8 @@ So far, the dotfiles only used for my macOS configuration, maybe in the future I
|
||||||
## Core System
|
## Core System
|
||||||
|
|
||||||
- OS: macOS (nix-darwin)
|
- OS: macOS (nix-darwin)
|
||||||
- Shell: nushell with starship prompt
|
- Shell: Zsh with Oh My Zsh and Starship; Nushell is available through `nu`
|
||||||
- Terminal: kitty with gruvbox theme
|
- Terminal: Kitty with Catppuccin Mocha theme
|
||||||
- Package Management: mix of nix and homebrew
|
- Package Management: mix of nix and homebrew
|
||||||
|
|
||||||
## Developer Tools
|
## Developer Tools
|
||||||
|
|
@ -22,7 +22,7 @@ So far, the dotfiles only used for my macOS configuration, maybe in the future I
|
||||||
|
|
||||||
## AI Tools
|
## AI Tools
|
||||||
|
|
||||||
- CLI-based tools: codex, crush, opencode, claude code
|
- CLI-based tools: codex, crush, claude code
|
||||||
- Custom z.ai gateway wrapper for claude code
|
- Custom z.ai gateway wrapper for claude code
|
||||||
- Secret management with SOPS-nix
|
- Secret management with SOPS-nix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,26 +4,49 @@
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
let
|
||||||
|
globalEnvironmentSecretNames = [
|
||||||
|
"ANTHROPIC_API_KEY"
|
||||||
|
"BRAVE_SEARCH_API_KEY"
|
||||||
|
"CROF_API_KEY"
|
||||||
|
"EXA_API_KEY"
|
||||||
|
"FAL_API_KEY"
|
||||||
|
"FIRECRAWL_API_KEY"
|
||||||
|
"GROQ_API_KEY"
|
||||||
|
"KIMI_API_KEY"
|
||||||
|
"MOONSHOT_API_KEY"
|
||||||
|
"OPENAI_API_KEY"
|
||||||
|
"OPENROUTER_API_KEY"
|
||||||
|
"ZAI_API_KEY"
|
||||||
|
];
|
||||||
|
in
|
||||||
{
|
{
|
||||||
# Import shared cross-platform home configuration
|
# Import shared cross-platform home configuration
|
||||||
imports = [
|
imports = [
|
||||||
../../home/base.nix
|
../../home/base.nix
|
||||||
../../home/shell/nushell.nix
|
../../home/shell/nushell.nix
|
||||||
|
../../home/shell/zsh.nix
|
||||||
./programs/aerospace
|
./programs/aerospace
|
||||||
./programs/kitty.nix
|
./programs/kitty.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# Darwin-specific secrets configuration.
|
# Decrypt each global environment variable to a separate runtime file.
|
||||||
# Materialize the whole encrypted env map once, then let Nushell load it.
|
# Zsh and Nushell load the files without evaluating shell source text.
|
||||||
rsydn.secrets = {
|
rsydn.secrets = {
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
defaultSopsFile = ../../../secrets/global-env.sops.yaml;
|
defaultSopsFile = ../../../secrets/global-env.sops.yaml;
|
||||||
secrets = {
|
secrets = lib.genAttrs globalEnvironmentSecretNames (name: {
|
||||||
"global-env" = {
|
|
||||||
format = "yaml";
|
format = "yaml";
|
||||||
key = "";
|
key = name;
|
||||||
path = "${config.xdg.configHome}/secrets/global-env.yaml";
|
path = "${config.xdg.configHome}/secrets/global-env/${name}";
|
||||||
};
|
});
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
home.activation.ensureGlobalEnvironmentSecretDir =
|
||||||
|
lib.hm.dag.entryBetween [ "sops-nix" ] [ "writeBoundary" ]
|
||||||
|
''
|
||||||
|
rm -f "${config.xdg.configHome}/secrets/global-env.yaml"
|
||||||
|
mkdir -p "${config.xdg.configHome}/secrets/global-env"
|
||||||
|
chmod 700 "${config.xdg.configHome}/secrets/global-env"
|
||||||
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,34 +4,49 @@
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
|
# JetBrainsMono Nerd Font renders the Starship powerline icons.
|
||||||
|
font_family = "JetBrainsMono Nerd Font";
|
||||||
|
font_size = 13.0;
|
||||||
|
|
||||||
background_opacity = "0.9";
|
background_opacity = "0.9";
|
||||||
confirm_os_window_close = 0;
|
confirm_os_window_close = 0;
|
||||||
enabled_layouts = "splits,stack";
|
enabled_layouts = "splits,stack";
|
||||||
|
|
||||||
# Gruvbox colors
|
# Catppuccin Mocha colors (catppuccin/kitty themes/mocha.conf)
|
||||||
background = "#282828";
|
background = "#1e1e2e";
|
||||||
foreground = "#ebdbb2";
|
foreground = "#cdd6f4";
|
||||||
cursor = "#ebdbb2";
|
cursor = "#f5e0dc";
|
||||||
cursor_text_color = "#282828";
|
cursor_text_color = "#1e1e2e";
|
||||||
selection_background = "#ebdbb2";
|
selection_background = "#f5e0dc";
|
||||||
selection_foreground = "#282828";
|
selection_foreground = "#1e1e2e";
|
||||||
|
|
||||||
color0 = "#282828";
|
# Kitty window border colors
|
||||||
color1 = "#cc241d";
|
active_border_color = "#b4befe";
|
||||||
color2 = "#98971a";
|
inactive_border_color = "#6c7086";
|
||||||
color3 = "#d79921";
|
|
||||||
color4 = "#458588";
|
# Tab bar colors
|
||||||
color5 = "#b16286";
|
active_tab_foreground = "#11111b";
|
||||||
color6 = "#689d6a";
|
active_tab_background = "#cba6f7";
|
||||||
color7 = "#a89984";
|
inactive_tab_foreground = "#cdd6f4";
|
||||||
color8 = "#928374";
|
inactive_tab_background = "#181825";
|
||||||
color9 = "#fb4934";
|
tab_bar_background = "#11111b";
|
||||||
color10 = "#b8bb26";
|
|
||||||
color11 = "#fabd2f";
|
color0 = "#45475a";
|
||||||
color12 = "#83a598";
|
color1 = "#f38ba8";
|
||||||
color13 = "#d3869b";
|
color2 = "#a6e3a1";
|
||||||
color14 = "#8ec07c";
|
color3 = "#f9e2af";
|
||||||
color15 = "#ebdbb2";
|
color4 = "#89b4fa";
|
||||||
|
color5 = "#f5c2e7";
|
||||||
|
color6 = "#94e2d5";
|
||||||
|
color7 = "#bac2de";
|
||||||
|
color8 = "#585b70";
|
||||||
|
color9 = "#f38ba8";
|
||||||
|
color10 = "#a6e3a1";
|
||||||
|
color11 = "#f9e2af";
|
||||||
|
color12 = "#89b4fa";
|
||||||
|
color13 = "#f5c2e7";
|
||||||
|
color14 = "#94e2d5";
|
||||||
|
color15 = "#a6adc8";
|
||||||
};
|
};
|
||||||
|
|
||||||
keybindings = {
|
keybindings = {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ in
|
||||||
default = [
|
default = [
|
||||||
"bitwarden"
|
"bitwarden"
|
||||||
"brave-browser"
|
"brave-browser"
|
||||||
"font-jetbrains-mono"
|
"font-jetbrains-mono-nerd-font"
|
||||||
"pgadmin4"
|
"pgadmin4"
|
||||||
"spotify"
|
"spotify"
|
||||||
"vesktop"
|
"vesktop"
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,8 @@
|
||||||
|
|
||||||
users.users.${user} = {
|
users.users.${user} = {
|
||||||
home = lib.mkDefault "/Users/${user}";
|
home = lib.mkDefault "/Users/${user}";
|
||||||
# Use the Home Manager nushell which has proper config setup
|
# Use the macOS system Zsh as the login shell. Nushell remains available as `nu`.
|
||||||
shell = "/etc/profiles/per-user/${user}/bin/nu";
|
shell = "/bin/zsh";
|
||||||
};
|
};
|
||||||
|
|
||||||
system = {
|
system = {
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
|
|
||||||
rsydn.devTools = {
|
rsydn.devTools = {
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
# Note: jetbrains-mono removed - installed via Homebrew cask (font-jetbrains-mono)
|
# Note: jetbrains-mono removed - installed via Homebrew cask (font-jetbrains-mono-nerd-font)
|
||||||
# due to nixpkgs-unstable syrupy test failures breaking the font's Python build deps
|
# due to nixpkgs-unstable syrupy test failures breaking the font's Python build deps
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
age
|
age
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ in
|
||||||
programs.direnv = {
|
programs.direnv = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableNushellIntegration = true;
|
enableNushellIntegration = true;
|
||||||
|
enableZshIntegration = true;
|
||||||
nix-direnv.enable = true;
|
nix-direnv.enable = true;
|
||||||
silent = cfg.silent;
|
silent = cfg.silent;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ require("lazy").setup({
|
||||||
version = false,
|
version = false,
|
||||||
},
|
},
|
||||||
|
|
||||||
install = { colorscheme = { "gruvbox", "habamax" } },
|
install = { colorscheme = { "catppuccin-mocha", "habamax" } },
|
||||||
|
|
||||||
checker = { enabled = false },
|
checker = { enabled = false },
|
||||||
change_detection = { notify = false },
|
change_detection = { notify = false },
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,8 @@ return {
|
||||||
-- gruvbox
|
-- gruvbox
|
||||||
{
|
{
|
||||||
"ellisonleao/gruvbox.nvim",
|
"ellisonleao/gruvbox.nvim",
|
||||||
lazy = false,
|
lazy = true,
|
||||||
priority = 1000,
|
|
||||||
opts = {},
|
opts = {},
|
||||||
config = function()
|
|
||||||
require("gruvbox").setup({})
|
|
||||||
vim.cmd.colorscheme("gruvbox")
|
|
||||||
end,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
-- tokyonight
|
-- tokyonight
|
||||||
|
|
@ -21,10 +16,12 @@ return {
|
||||||
-- catppuccin
|
-- catppuccin
|
||||||
{
|
{
|
||||||
"catppuccin/nvim",
|
"catppuccin/nvim",
|
||||||
lazy = true,
|
lazy = false,
|
||||||
priority = 1000,
|
priority = 1000,
|
||||||
name = "catppuccin",
|
name = "catppuccin",
|
||||||
opts = {
|
opts = {
|
||||||
|
flavour = "mocha",
|
||||||
|
term_colors = true,
|
||||||
lsp_styles = {
|
lsp_styles = {
|
||||||
underlines = {
|
underlines = {
|
||||||
errors = { "undercurl" },
|
errors = { "undercurl" },
|
||||||
|
|
@ -60,6 +57,10 @@ return {
|
||||||
-- which_key = true,
|
-- which_key = true,
|
||||||
-- },
|
-- },
|
||||||
},
|
},
|
||||||
|
config = function(_, opts)
|
||||||
|
require("catppuccin").setup(opts)
|
||||||
|
vim.cmd.colorscheme("catppuccin-mocha")
|
||||||
|
end,
|
||||||
-- specs = {
|
-- specs = {
|
||||||
-- {
|
-- {
|
||||||
-- "akinsho/bufferline.nvim",
|
-- "akinsho/bufferline.nvim",
|
||||||
|
|
|
||||||
|
|
@ -181,22 +181,24 @@ in
|
||||||
|
|
||||||
$env.NIX_PROFILES = "/run/current-system/sw ${config.home.profileDirectory}"
|
$env.NIX_PROFILES = "/run/current-system/sw ${config.home.profileDirectory}"
|
||||||
|
|
||||||
# Load globally scoped sops-managed environment variables.
|
# Load each globally scoped sops-managed environment variable.
|
||||||
let global_secrets_file = "${config.xdg.configHome}/secrets/global-env.yaml"
|
let global_secrets_dir = "${config.xdg.configHome}/secrets/global-env"
|
||||||
|
|
||||||
def --env load-global-secrets [secret_file: string] {
|
def --env load-global-secrets [secret_dir: string] {
|
||||||
if ($secret_file | path exists) {
|
if ($secret_dir | path exists) {
|
||||||
let secret_values = (open $secret_file)
|
let secret_values = (
|
||||||
|
ls $secret_dir
|
||||||
$secret_values
|
|
||||||
| transpose name value
|
|
||||||
| reduce -f {} {|entry, acc|
|
| reduce -f {} {|entry, acc|
|
||||||
$acc | upsert $entry.name ($entry.value | into string)
|
let name = ($entry.name | path basename)
|
||||||
|
let value = (open --raw $entry.name | str trim)
|
||||||
|
$acc | upsert $name $value
|
||||||
}
|
}
|
||||||
| load-env
|
)
|
||||||
|
|
||||||
|
$secret_values | load-env
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
load-global-secrets $global_secrets_file
|
load-global-secrets $global_secrets_dir
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
enableFishIntegration = true;
|
enableFishIntegration = true;
|
||||||
enableNushellIntegration = true;
|
enableNushellIntegration = true;
|
||||||
|
enableZshIntegration = true;
|
||||||
settings = lib.importTOML ./starship.toml;
|
settings = lib.importTOML ./starship.toml;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
"$schema" = "https://starship.rs/config-schema.json"
|
"$schema" = "https://starship.rs/config-schema.json"
|
||||||
|
|
||||||
format = """
|
format = """
|
||||||
[](color_orange)\
|
[](peach)\
|
||||||
$os\
|
$os\
|
||||||
$username\
|
$username\
|
||||||
[](bg:color_yellow fg:color_orange)\
|
[](bg:yellow fg:peach)\
|
||||||
$directory\
|
$directory\
|
||||||
[](fg:color_yellow bg:color_aqua)\
|
[](fg:yellow bg:teal)\
|
||||||
$git_branch\
|
$git_branch\
|
||||||
$git_status\
|
$git_status\
|
||||||
[](fg:color_aqua bg:color_blue)\
|
[](fg:teal bg:blue)\
|
||||||
$c\
|
$c\
|
||||||
$cpp\
|
$cpp\
|
||||||
$rust\
|
$rust\
|
||||||
|
|
@ -20,32 +20,49 @@ $java\
|
||||||
$kotlin\
|
$kotlin\
|
||||||
$haskell\
|
$haskell\
|
||||||
$python\
|
$python\
|
||||||
[](fg:color_blue bg:color_bg3)\
|
[](fg:blue bg:surface0)\
|
||||||
$docker_context\
|
$docker_context\
|
||||||
$conda\
|
$conda\
|
||||||
$pixi\
|
$pixi\
|
||||||
[](fg:color_bg3 bg:color_bg1)\
|
[](fg:surface0 bg:base)\
|
||||||
$time\
|
$time\
|
||||||
[ ](fg:color_bg1)\
|
[ ](fg:base)\
|
||||||
$line_break$character"""
|
$line_break$character"""
|
||||||
|
|
||||||
palette = "gruvbox_dark"
|
palette = "catppuccin_mocha"
|
||||||
|
|
||||||
[palettes.gruvbox_dark]
|
# Official Catppuccin Mocha palette (catppuccin/starship themes/mocha.toml)
|
||||||
color_fg0 = "#fbf1c7"
|
[palettes.catppuccin_mocha]
|
||||||
color_bg1 = "#3c3836"
|
rosewater = "#f5e0dc"
|
||||||
color_bg3 = "#665c54"
|
flamingo = "#f2cdcd"
|
||||||
color_blue = "#458588"
|
pink = "#f5c2e7"
|
||||||
color_aqua = "#689d6a"
|
mauve = "#cba6f7"
|
||||||
color_green = "#98971a"
|
red = "#f38ba8"
|
||||||
color_orange = "#d65d0e"
|
maroon = "#eba0ac"
|
||||||
color_purple = "#b16286"
|
peach = "#fab387"
|
||||||
color_red = "#cc241d"
|
yellow = "#f9e2af"
|
||||||
color_yellow = "#d79921"
|
green = "#a6e3a1"
|
||||||
|
teal = "#94e2d5"
|
||||||
|
sky = "#89dceb"
|
||||||
|
sapphire = "#74c7ec"
|
||||||
|
blue = "#89b4fa"
|
||||||
|
lavender = "#b4befe"
|
||||||
|
text = "#cdd6f4"
|
||||||
|
subtext1 = "#bac2de"
|
||||||
|
subtext0 = "#a6adc8"
|
||||||
|
overlay2 = "#9399b2"
|
||||||
|
overlay1 = "#7f849c"
|
||||||
|
overlay0 = "#6c7086"
|
||||||
|
surface2 = "#585b70"
|
||||||
|
surface1 = "#45475a"
|
||||||
|
surface0 = "#313244"
|
||||||
|
base = "#1e1e2e"
|
||||||
|
mantle = "#181825"
|
||||||
|
crust = "#11111b"
|
||||||
|
|
||||||
[os]
|
[os]
|
||||||
disabled = false
|
disabled = false
|
||||||
style = "bg:color_orange fg:color_fg0"
|
style = "bg:peach fg:crust"
|
||||||
|
|
||||||
[os.symbols]
|
[os.symbols]
|
||||||
Windows = ""
|
Windows = ""
|
||||||
|
|
@ -72,12 +89,12 @@ Pop = ""
|
||||||
|
|
||||||
[username]
|
[username]
|
||||||
show_always = true
|
show_always = true
|
||||||
style_user = "bg:color_orange fg:color_fg0"
|
style_user = "bg:peach fg:crust"
|
||||||
style_root = "bg:color_orange fg:color_fg0"
|
style_root = "bg:peach fg:crust"
|
||||||
format = "[ $user ]($style)"
|
format = "[ $user ]($style)"
|
||||||
|
|
||||||
[directory]
|
[directory]
|
||||||
style = "fg:color_fg0 bg:color_yellow"
|
style = "fg:crust bg:yellow"
|
||||||
format = "[ $path ]($style)"
|
format = "[ $path ]($style)"
|
||||||
truncation_length = 3
|
truncation_length = 3
|
||||||
truncation_symbol = "…/"
|
truncation_symbol = "…/"
|
||||||
|
|
@ -91,90 +108,90 @@ Developer = " "
|
||||||
|
|
||||||
[git_branch]
|
[git_branch]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_aqua"
|
style = "bg:teal"
|
||||||
format = "[[ $symbol $branch ](fg:color_fg0 bg:color_aqua)]($style)"
|
format = "[[ $symbol $branch ](fg:crust bg:teal)]($style)"
|
||||||
|
|
||||||
[git_status]
|
[git_status]
|
||||||
style = "bg:color_aqua"
|
style = "bg:teal"
|
||||||
format = "[[($all_status$ahead_behind )](fg:color_fg0 bg:color_aqua)]($style)"
|
format = "[[($all_status$ahead_behind )](fg:crust bg:teal)]($style)"
|
||||||
|
|
||||||
[nodejs]
|
[nodejs]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_blue"
|
style = "bg:blue"
|
||||||
format = "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)"
|
format = "[[ $symbol( $version) ](fg:crust bg:blue)]($style)"
|
||||||
|
|
||||||
[c]
|
[c]
|
||||||
symbol = " "
|
symbol = " "
|
||||||
style = "bg:color_blue"
|
style = "bg:blue"
|
||||||
format = "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)"
|
format = "[[ $symbol( $version) ](fg:crust bg:blue)]($style)"
|
||||||
|
|
||||||
[cpp]
|
[cpp]
|
||||||
symbol = " "
|
symbol = " "
|
||||||
style = "bg:color_blue"
|
style = "bg:blue"
|
||||||
format = "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)"
|
format = "[[ $symbol( $version) ](fg:crust bg:blue)]($style)"
|
||||||
|
|
||||||
[rust]
|
[rust]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_blue"
|
style = "bg:blue"
|
||||||
format = "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)"
|
format = "[[ $symbol( $version) ](fg:crust bg:blue)]($style)"
|
||||||
|
|
||||||
[golang]
|
[golang]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_blue"
|
style = "bg:blue"
|
||||||
format = "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)"
|
format = "[[ $symbol( $version) ](fg:crust bg:blue)]($style)"
|
||||||
|
|
||||||
[php]
|
[php]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_blue"
|
style = "bg:blue"
|
||||||
format = "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)"
|
format = "[[ $symbol( $version) ](fg:crust bg:blue)]($style)"
|
||||||
|
|
||||||
[java]
|
[java]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_blue"
|
style = "bg:blue"
|
||||||
format = "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)"
|
format = "[[ $symbol( $version) ](fg:crust bg:blue)]($style)"
|
||||||
|
|
||||||
[kotlin]
|
[kotlin]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_blue"
|
style = "bg:blue"
|
||||||
format = "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)"
|
format = "[[ $symbol( $version) ](fg:crust bg:blue)]($style)"
|
||||||
|
|
||||||
[haskell]
|
[haskell]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_blue"
|
style = "bg:blue"
|
||||||
format = "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)"
|
format = "[[ $symbol( $version) ](fg:crust bg:blue)]($style)"
|
||||||
|
|
||||||
[python]
|
[python]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_blue"
|
style = "bg:blue"
|
||||||
format = "[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)"
|
format = "[[ $symbol( $version) ](fg:crust bg:blue)]($style)"
|
||||||
|
|
||||||
[docker_context]
|
[docker_context]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_bg3"
|
style = "bg:surface0"
|
||||||
format = "[[ $symbol( $context) ](fg:#83a598 bg:color_bg3)]($style)"
|
format = "[[ $symbol( $context) ](fg:teal bg:surface0)]($style)"
|
||||||
|
|
||||||
[conda]
|
[conda]
|
||||||
style = "bg:color_bg3"
|
style = "bg:surface0"
|
||||||
format = "[[ $symbol( $environment) ](fg:#83a598 bg:color_bg3)]($style)"
|
format = "[[ $symbol( $environment) ](fg:teal bg:surface0)]($style)"
|
||||||
|
|
||||||
[pixi]
|
[pixi]
|
||||||
style = "bg:color_bg3"
|
style = "bg:surface0"
|
||||||
format = "[[ $symbol( $version)( $environment) ](fg:color_fg0 bg:color_bg3)]($style)"
|
format = "[[ $symbol( $version)( $environment) ](fg:text bg:surface0)]($style)"
|
||||||
|
|
||||||
[time]
|
[time]
|
||||||
disabled = false
|
disabled = false
|
||||||
time_format = "%R"
|
time_format = "%R"
|
||||||
style = "bg:color_bg1"
|
style = "bg:base"
|
||||||
format = "[[ $time ](fg:color_fg0 bg:color_bg1)]($style)"
|
format = "[[ $time ](fg:text bg:base)]($style)"
|
||||||
|
|
||||||
[line_break]
|
[line_break]
|
||||||
disabled = false
|
disabled = false
|
||||||
|
|
||||||
[character]
|
[character]
|
||||||
disabled = false
|
disabled = false
|
||||||
success_symbol = "[](bold fg:color_green)"
|
success_symbol = "[](bold fg:green)"
|
||||||
error_symbol = "[](bold fg:color_red)"
|
error_symbol = "[](bold fg:red)"
|
||||||
vimcmd_symbol = "[](bold fg:color_green)"
|
vimcmd_symbol = "[](bold fg:green)"
|
||||||
vimcmd_replace_one_symbol = "[](bold fg:color_purple)"
|
vimcmd_replace_one_symbol = "[](bold fg:mauve)"
|
||||||
vimcmd_replace_symbol = "[](bold fg:color_purple)"
|
vimcmd_replace_symbol = "[](bold fg:mauve)"
|
||||||
vimcmd_visual_symbol = "[](bold fg:color_yellow)"
|
vimcmd_visual_symbol = "[](bold fg:yellow)"
|
||||||
|
|
@ -14,7 +14,15 @@
|
||||||
prefix = "C-a";
|
prefix = "C-a";
|
||||||
escapeTime = 0;
|
escapeTime = 0;
|
||||||
aggressiveResize = true;
|
aggressiveResize = true;
|
||||||
plugins = [ { plugin = pkgs.tmuxPlugins.gruvbox; } ];
|
plugins = [
|
||||||
|
{
|
||||||
|
plugin = pkgs.tmuxPlugins.catppuccin;
|
||||||
|
extraConfig = ''
|
||||||
|
set -g @catppuccin_flavor "mocha"
|
||||||
|
set -g @catppuccin_window_status_style "rounded"
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
# Terminal configuration for proper colors and features
|
# Terminal configuration for proper colors and features
|
||||||
set-option -g default-terminal "screen-256color"
|
set-option -g default-terminal "screen-256color"
|
||||||
|
|
@ -50,9 +58,10 @@
|
||||||
bind J resize-pane -D 5
|
bind J resize-pane -D 5
|
||||||
bind K resize-pane -U 5
|
bind K resize-pane -U 5
|
||||||
bind L resize-pane -R 5
|
bind L resize-pane -R 5
|
||||||
# Ensure tmux panes spawn login nu so Starship integration runs
|
# Start Zsh by default and keep Nushell available on prefix + C-n.
|
||||||
set -g default-shell "${config.home.profileDirectory}/bin/nu"
|
set -g default-shell "/bin/zsh"
|
||||||
set -g default-command "${config.home.profileDirectory}/bin/nu --login"
|
set -g default-command "/bin/zsh --login"
|
||||||
|
bind-key C-n new-window -n nushell "${config.home.profileDirectory}/bin/nu --login"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
136
modules/home/shell/zsh.nix
Normal file
136
modules/home/shell/zsh.nix
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
programs.zsh = {
|
||||||
|
enable = true;
|
||||||
|
enableCompletion = true;
|
||||||
|
dotDir = config.home.homeDirectory;
|
||||||
|
|
||||||
|
oh-my-zsh = {
|
||||||
|
enable = true;
|
||||||
|
plugins = [
|
||||||
|
"git"
|
||||||
|
"sudo"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
shellAliases.ssh = "kitten ssh";
|
||||||
|
|
||||||
|
profileExtra = ''
|
||||||
|
if [[ -x /opt/homebrew/bin/brew ]]; then
|
||||||
|
eval "$(/opt/homebrew/bin/brew shellenv)"
|
||||||
|
elif [[ -x /usr/local/bin/brew ]]; then
|
||||||
|
eval "$(/usr/local/bin/brew shellenv)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -r "$HOME/.orbstack/shell/init.zsh" ]] && source "$HOME/.orbstack/shell/init.zsh"
|
||||||
|
'';
|
||||||
|
|
||||||
|
initContent = ''
|
||||||
|
typeset -U path PATH
|
||||||
|
path=(
|
||||||
|
"$HOME/.cache/.bun/bin"
|
||||||
|
"$HOME/.local/bin"
|
||||||
|
$path
|
||||||
|
"$HOME/.lmstudio/bin"
|
||||||
|
)
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
_load_global_secrets() {
|
||||||
|
local secret_dir="''${XDG_CONFIG_HOME:-$HOME/.config}/secrets/global-env"
|
||||||
|
local secret_file name value
|
||||||
|
|
||||||
|
[[ -d "$secret_dir" ]] || return 0
|
||||||
|
|
||||||
|
for secret_file in "$secret_dir"/*(N.); do
|
||||||
|
name="''${secret_file:t}"
|
||||||
|
[[ "$name" =~ '^[A-Za-z_][A-Za-z0-9_]*$' ]] || continue
|
||||||
|
value="$(<"$secret_file")"
|
||||||
|
export "$name=$value"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
_load_global_secrets
|
||||||
|
unfunction _load_global_secrets
|
||||||
|
|
||||||
|
dotfiles-qa() (
|
||||||
|
local dotfiles_dir="${config.home.homeDirectory}/Development/dotfiles"
|
||||||
|
|
||||||
|
print -P "%F{green}Running dotfiles QA validation...%f"
|
||||||
|
cd "$dotfiles_dir" || return 1
|
||||||
|
|
||||||
|
print -P "%F{blue}1. Formatting Nix files...%f"
|
||||||
|
nix fmt . || {
|
||||||
|
print -P "%F{red}Formatting failed.%f"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
print -P "%F{blue}2. Running flake checks...%f"
|
||||||
|
XDG_CACHE_HOME="$dotfiles_dir/.cache" nix flake check || {
|
||||||
|
print -P "%F{red}Flake checks failed.%f"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
print -P "%F{blue}3. Building the Darwin configuration...%f"
|
||||||
|
darwin-rebuild build --flake "$dotfiles_dir#macbook-pro" || {
|
||||||
|
print -P "%F{red}Darwin build failed.%f"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
print -P "%F{green}Core QA checks passed.%f"
|
||||||
|
)
|
||||||
|
|
||||||
|
bd-init() {
|
||||||
|
if [[ ! -d .git && ! -f .git ]]; then
|
||||||
|
print -P "%F{red}Error: not in a Git repository.%f"
|
||||||
|
print "Initialize one with: git init"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -e .beads ]]; then
|
||||||
|
print -P "%F{yellow}Beads is already initialized in this project.%f"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
bd init || return
|
||||||
|
print -P "%F{green}Beads initialized.%f"
|
||||||
|
print "Next steps:"
|
||||||
|
print ' bd create --title "Your task" --type feature'
|
||||||
|
print " bd ready"
|
||||||
|
}
|
||||||
|
|
||||||
|
bd-ready() {
|
||||||
|
if [[ ! -e .beads ]]; then
|
||||||
|
print -P "%F{red}Not a Beads project. Run bd-init first.%f"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local ready_tasks
|
||||||
|
ready_tasks="$(bd ready --json)" || return
|
||||||
|
|
||||||
|
if [[ "$(print -r -- "$ready_tasks" | jq 'length')" == 0 ]]; then
|
||||||
|
print -P "%F{yellow}No ready tasks.%f"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
print -P "%F{green}Ready tasks:%f"
|
||||||
|
print -r -- "$ready_tasks" | jq -r '
|
||||||
|
.[] |
|
||||||
|
"[\(.id)] \(.title)\n Type: \(.type) | Priority: \(.priority) | Status: \(.status)" +
|
||||||
|
(if ((.description // "") | length) > 0 then "\n \(.description)" else "" end) +
|
||||||
|
"\n"
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
bd-sync() {
|
||||||
|
if [[ ! -e .beads ]]; then
|
||||||
|
print -P "%F{red}Not a Beads project.%f"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
print -P "%F{blue}Syncing Beads database...%f"
|
||||||
|
bd sync || return
|
||||||
|
print -P "%F{green}Sync complete.%f"
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,41 +1,46 @@
|
||||||
# Secrets with sops-nix
|
# Secrets with sops-nix
|
||||||
|
|
||||||
This repo wires [`sops-nix`](https://github.com/Mic92/sops-nix) into the Home Manager profile so secrets are decrypted on-demand into `~/.config/secrets`. The module is enabled by default and auto-generates an Age key if one does not already exist. Only the *encrypted* payloads under `secrets/*.sops.yaml` are meant to live in git; decrypted files never leave your machine.
|
This repository uses [`sops-nix`](https://github.com/Mic92/sops-nix) with Home Manager. SOPS keeps encrypted values in Git. Home Manager decrypts each global environment variable to a separate runtime file under `~/.config/secrets/global-env/`.
|
||||||
|
|
||||||
## One-time setup
|
## One-time setup
|
||||||
1. Ensure `age` and `sops` are available (e.g. `nix develop` or `nix profile install nixpkgs#age nixpkgs#sops`).
|
|
||||||
2. Generate or import an Age key. Either let Home Manager create one automatically on first activation or run `age-keygen -o ~/.config/sops/age/keys.txt` yourself.
|
|
||||||
3. Capture the public half with `age-keygen -y -f ~/.config/sops/age/keys.txt` and add it to the `recipients` list in each encrypted file (`age1…`). Commit the public key under version control or share it through your password manager so other hosts can decrypt.
|
|
||||||
4. (Optional) Store the private key securely in macOS Keychain or 1Password (`security add-generic-password …`) so rebuilds work without manual prompts.
|
|
||||||
|
|
||||||
## Managing secrets
|
1. Enter `nix develop` so `age` and `sops` are available.
|
||||||
- Global shell env vars live in one encrypted YAML file: `secrets/global-env.sops.yaml`.
|
2. Generate or import an Age key. Home Manager can generate one during activation. You can also run:
|
||||||
- Home Manager decrypts that file to `~/.config/secrets/global-env.yaml` during activation.
|
|
||||||
- Nushell reads `global-env.yaml` on startup and exports each top-level key as an environment variable.
|
|
||||||
- Only the encrypted file is tracked in git; plaintext stays local.
|
|
||||||
|
|
||||||
Example Darwin configuration:
|
```bash
|
||||||
|
age-keygen -o ~/.config/sops/age/keys.txt
|
||||||
|
```
|
||||||
|
|
||||||
```nix
|
3. Get the public key:
|
||||||
rsydn.secrets = {
|
|
||||||
enable = true;
|
```bash
|
||||||
defaultSopsFile = ../../../secrets/global-env.sops.yaml;
|
age-keygen -y -f ~/.config/sops/age/keys.txt
|
||||||
secrets."global-env" = {
|
```
|
||||||
format = "yaml";
|
|
||||||
key = "";
|
4. Add the public key as a recipient in each encrypted SOPS file.
|
||||||
path = "${config.xdg.configHome}/secrets/global-env.yaml";
|
5. Store the private key in a secure backup such as 1Password or macOS Keychain.
|
||||||
};
|
|
||||||
};
|
## Global environment secrets
|
||||||
|
|
||||||
|
The encrypted source is `secrets/global-env.sops.yaml`. It contains a flat map of environment variable names and encrypted values.
|
||||||
|
|
||||||
|
Home Manager declares each key in `modules/darwin/home/default.nix`. During activation, sops-nix writes one mode `0400` file per key:
|
||||||
|
|
||||||
|
```text
|
||||||
|
~/.config/secrets/global-env/OPENAI_API_KEY
|
||||||
|
~/.config/secrets/global-env/ANTHROPIC_API_KEY
|
||||||
```
|
```
|
||||||
|
|
||||||
Create or update global env vars by running:
|
Zsh and Nushell read these files and export each filename as an environment variable. The loaders do not evaluate secret values as shell code.
|
||||||
|
|
||||||
|
Edit the encrypted source with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
SOPS_AGE_KEY_FILE=$HOME/.config/sops/age/keys.txt \
|
SOPS_AGE_KEY_FILE=$HOME/.config/sops/age/keys.txt \
|
||||||
sops secrets/global-env.sops.yaml
|
sops secrets/global-env.sops.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
Add entries like:
|
Use a flat YAML structure:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
OPENAI_API_KEY: sk-...
|
OPENAI_API_KEY: sk-...
|
||||||
|
|
@ -43,21 +48,42 @@ ANTHROPIC_API_KEY: sk-ant-...
|
||||||
GITHUB_TOKEN: ghp_...
|
GITHUB_TOKEN: ghp_...
|
||||||
```
|
```
|
||||||
|
|
||||||
After `darwin-rebuild switch --flake .#macbook-pro`, the decrypted file is refreshed and every new Nushell session automatically gets:
|
When you add or remove a key, also update `globalEnvironmentSecretNames` in `modules/darwin/home/default.nix`. Then apply the configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
darwin-rebuild switch --flake .#macbook-pro
|
||||||
|
```
|
||||||
|
|
||||||
|
Open a new Zsh or Nushell session after activation. Access values as follows:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
print -r -- "$OPENAI_API_KEY"
|
||||||
|
```
|
||||||
|
|
||||||
```nu
|
```nu
|
||||||
$env.OPENAI_API_KEY
|
$env.OPENAI_API_KEY
|
||||||
$env.ANTHROPIC_API_KEY
|
|
||||||
$env.GITHUB_TOKEN
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For secrets that should stay file-based instead of being auto-exported, you can still declare extra entries under `rsydn.secrets.secrets` with their own `path`, `format`, and `key`.
|
Do not print real secret values during routine validation. Test only whether a variable exists.
|
||||||
|
|
||||||
|
## File-based secrets
|
||||||
|
|
||||||
|
Secrets that applications consume as files should stay file-based. Declare each entry under `rsydn.secrets.secrets` with its own `path`, `format`, and `key`.
|
||||||
|
|
||||||
|
For project-specific environment variables, use an encrypted project file with `sops exec-env` through direnv. Do not add project secrets to the global shell environment.
|
||||||
|
|
||||||
## Rotating keys
|
## Rotating keys
|
||||||
If you regenerate your Age key, re-encrypt the file with the new recipient (`sops updatekeys secrets/global-env.sops.yaml`) and re-run `darwin-rebuild --dry-run --flake .#macbook-pro` to verify the deployment. Remember to remove old recipients so machines without access can no longer decrypt.
|
|
||||||
|
|
||||||
## Frequently asked questions
|
If you replace an Age key, update the recipients:
|
||||||
- **Where do encrypted files live?** In this repo under `secrets/*.sops.yaml`; they are safe to commit.
|
|
||||||
- **Where does plaintext live?** At runtime under `~/.config/secrets/*` (managed by Home Manager). Keep permissions tight and never add these paths to git.
|
```bash
|
||||||
- **How do I share secrets with another machine?** Copy the Age public key from that machine into the `recipients` list, re-run `sops updatekeys`, commit, then pull and rebuild on the other host.
|
sops updatekeys secrets/global-env.sops.yaml
|
||||||
- **Can I keep using `.env`?** Yes—encrypt it (e.g. `secrets/project.env.sops`) and load it with `sops exec-env` inside `direnv` so per-project shells receive the decrypted variables without storing them on disk.
|
```
|
||||||
|
|
||||||
|
Remove old recipients, then validate the configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
darwin-rebuild --dry-run --flake .#macbook-pro
|
||||||
|
```
|
||||||
|
|
||||||
|
Only encrypted SOPS files belong in Git. Never add decrypted files from `~/.config/secrets/`.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue