Initial commit
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
{pkgs, ...}: let
|
||||
configFile = "atuin/config.toml";
|
||||
toTOML = (pkgs.formats.toml {}).generate;
|
||||
in {
|
||||
users.users.someone.packages = [
|
||||
pkgs.atuin
|
||||
];
|
||||
|
||||
xdg.configFile = {
|
||||
"${configFile}".source = toTOML "config.toml" {
|
||||
auto_sync = false;
|
||||
update_check = false;
|
||||
workspaces = false;
|
||||
ctrl_n_shortcuts = true;
|
||||
dialect = "uk";
|
||||
filter_mode = "host";
|
||||
search_mode = "skim";
|
||||
filter_mode_shell_up_key_binding = "session";
|
||||
style = "compact";
|
||||
inline_height = 7;
|
||||
show_help = false;
|
||||
enter_accept = true;
|
||||
history_filter = ["shit"];
|
||||
keymap_mode = "vim-normal";
|
||||
sync = {
|
||||
records = true;
|
||||
};
|
||||
};
|
||||
|
||||
"fish/conf.d/atuin.fish".source =
|
||||
pkgs.runCommand "atuin-fish-init" {
|
||||
XDG_CONFIG_HOME = "$PWD";
|
||||
XDG_DATA_HOME = "$PWD";
|
||||
ATUIN_CONFIG_DIR = "$PWD/atuin";
|
||||
} ''
|
||||
mkdir -p atuin
|
||||
${pkgs.atuin}/bin/atuin init fish --disable-up-arrow > $out
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{pkgs, ...}: {
|
||||
users.users.someone.packages = [pkgs.autojump];
|
||||
|
||||
xdg.configFile."fish/conf.d/autojump.fish".source = "${pkgs.autojump}/share/autojump/autojump.fish";
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
configFile = "bat/config";
|
||||
|
||||
manPager = pkgs.writeShellScriptBin "manpager" ''
|
||||
${pkgs.coreutils}/bin/col -bx | ${pkgs.bat}/bin/bat -l man -p "$@"
|
||||
'';
|
||||
in {
|
||||
environment.sessionVariables = {
|
||||
MANPAGER = "${manPager}/bin/manpager";
|
||||
MANROFFOPT = "-c";
|
||||
};
|
||||
|
||||
users.users.someone.packages = with pkgs; [
|
||||
bat
|
||||
manPager
|
||||
];
|
||||
|
||||
xdg.configFile."${configFile}".text =
|
||||
lib.generators.toKeyValue {
|
||||
mkKeyValue = k: v: "--${lib.escapeShellArg k}=${lib.escapeShellArg v}";
|
||||
listsAsDuplicateKeys = true;
|
||||
} {
|
||||
pager = "less -FR";
|
||||
style = "plain";
|
||||
theme = "base16";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{pkgs, ...}: let
|
||||
configFile = "bottom/bottom.toml";
|
||||
toTOML = (pkgs.formats.toml {}).generate;
|
||||
|
||||
btopAlias = pkgs.symlinkJoin {
|
||||
name = "btop";
|
||||
paths = [pkgs.bottom];
|
||||
buildInputs = [pkgs.makeWrapper];
|
||||
postBuild = ''
|
||||
rm $out/bin/btop 2>/dev/null || true
|
||||
makeWrapper ${pkgs.bottom}/bin/btm $out/bin/btop
|
||||
'';
|
||||
};
|
||||
|
||||
htopAlias = pkgs.symlinkJoin {
|
||||
name = "htop";
|
||||
paths = [pkgs.bottom];
|
||||
buildInputs = [pkgs.makeWrapper];
|
||||
postBuild = ''
|
||||
rm $out/bin/htop 2>/dev/null || true
|
||||
makeWrapper ${pkgs.bottom}/bin/btm $out/bin/htop \
|
||||
--add-flags "-b"
|
||||
'';
|
||||
};
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
bottom
|
||||
btopAlias
|
||||
htopAlias
|
||||
];
|
||||
|
||||
xdg.configFile."${configFile}".source = toTOML "bottom.toml" {
|
||||
enable_gpu = true;
|
||||
flags.group_processes = true;
|
||||
row = [
|
||||
{
|
||||
ratio = 2;
|
||||
child = [
|
||||
{type = "cpu";}
|
||||
{type = "mem";}
|
||||
];
|
||||
}
|
||||
{
|
||||
ratio = 3;
|
||||
child = [
|
||||
{
|
||||
type = "proc";
|
||||
ratio = 1;
|
||||
default = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
_: {
|
||||
xdg.configFile."fish/functions/__fish_command_not_found_handler.fish".text = ''
|
||||
function __fish_command_not_found_handler --on-event fish_command_not_found
|
||||
/run/current-system/sw/bin/command-not-found $argv
|
||||
end
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
{pkgs, ...}: let
|
||||
configFile = "discordo/config.toml";
|
||||
toTOML = (pkgs.formats.toml {}).generate;
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
discordo
|
||||
];
|
||||
|
||||
xdg.configFile."${configFile}".source = toTOML "config.toml" {
|
||||
mouse = false;
|
||||
editor = "default";
|
||||
markdown = true;
|
||||
hide_blocked_users = true;
|
||||
show_attachment_links = true;
|
||||
autocomplete_limit = 20;
|
||||
messages_limit = 50;
|
||||
|
||||
timestamps = {
|
||||
enabled = true;
|
||||
format = "15:04";
|
||||
};
|
||||
|
||||
notifications = {
|
||||
enabled = true;
|
||||
duration = 0;
|
||||
sound = {
|
||||
enabled = true;
|
||||
only_on_ping = true;
|
||||
};
|
||||
};
|
||||
|
||||
identify = {
|
||||
status = "dnd";
|
||||
browser = "default";
|
||||
browser_version = "default";
|
||||
user_agent = "default";
|
||||
};
|
||||
|
||||
keys = {
|
||||
focus_guilds_tree = "Ctrl+G";
|
||||
focus_messages_list = "Ctrl+T";
|
||||
focus_message_input = "Ctrl+P";
|
||||
toggle_guilds_tree = "Ctrl+B";
|
||||
quit = "Ctrl+C";
|
||||
logout = "Ctrl+D";
|
||||
|
||||
guilds_tree = {
|
||||
select_previous = "Rune[k]";
|
||||
select_next = "Rune[j]";
|
||||
select_first = "Rune[g]";
|
||||
select_last = "Rune[G]";
|
||||
select_current = "Enter";
|
||||
yank_id = "Rune[i]";
|
||||
collapse_parent_node = "Rune[-]";
|
||||
move_to_parent_node = "Rune[p]";
|
||||
};
|
||||
|
||||
messages_list = {
|
||||
select_previous = "Rune[k]";
|
||||
select_next = "Rune[j]";
|
||||
select_first = "Rune[g]";
|
||||
select_last = "Rune[G]";
|
||||
select_reply = "Rune[s]";
|
||||
reply = "Rune[r]";
|
||||
reply_mention = "Rune[R]";
|
||||
cancel = "Esc";
|
||||
delete = "Rune[d]";
|
||||
open = "Rune[o]";
|
||||
yank_content = "Rune[y]";
|
||||
yank_url = "Rune[u]";
|
||||
yank_id = "Rune[i]";
|
||||
};
|
||||
|
||||
message_input = {
|
||||
send = "Enter";
|
||||
cancel = "Esc";
|
||||
tab_complete = "Tab";
|
||||
open_editor = "Ctrl+E";
|
||||
open_file_picker = "Ctrl+P";
|
||||
};
|
||||
|
||||
mentions_list = {
|
||||
up = "Up";
|
||||
down = "Down";
|
||||
};
|
||||
};
|
||||
|
||||
theme = {
|
||||
title = {
|
||||
alignment = "left";
|
||||
normal_style = {attributes = "dim";};
|
||||
active_style = {
|
||||
foreground = "purple";
|
||||
attributes = "bold";
|
||||
};
|
||||
};
|
||||
|
||||
border = {
|
||||
enabled = true;
|
||||
padding = [0 0 1 1];
|
||||
normal_style = {attributes = "dim";};
|
||||
active_style = {
|
||||
foreground = "purple";
|
||||
attributes = "bold";
|
||||
};
|
||||
normal_set = "plain";
|
||||
active_set = "plain";
|
||||
};
|
||||
|
||||
guilds_tree = {
|
||||
auto_expand_folders = false;
|
||||
graphics = true;
|
||||
graphics_color = "default";
|
||||
};
|
||||
|
||||
messages_list = {
|
||||
reply_indicator = ">";
|
||||
forwarded_indicator = "<";
|
||||
mention_style = {foreground = "blue";};
|
||||
emoji_style = {foreground = "green";};
|
||||
url_style = {foreground = "blue";};
|
||||
attachment_style = {foreground = "yellow";};
|
||||
};
|
||||
|
||||
mentions_list = {
|
||||
min_width = 20;
|
||||
max_height = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
{pkgs, ...}: let
|
||||
configFile = "fum/config.jsonc";
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
fum
|
||||
playerctl
|
||||
];
|
||||
|
||||
xdg.configFile."${configFile}".text = builtins.toJSON {
|
||||
players = [
|
||||
"zen"
|
||||
"zen-browser"
|
||||
"mozilla zen"
|
||||
"helium"
|
||||
];
|
||||
debug = false;
|
||||
keybinds = {
|
||||
"esc;q" = "quit()";
|
||||
"h" = "prev()";
|
||||
"l" = "next()";
|
||||
" " = "play_pause()";
|
||||
"-" = "volume(-5)";
|
||||
"+" = "volume(+5)";
|
||||
"left" = "backward(2500)";
|
||||
"right" = "forward(2500)";
|
||||
};
|
||||
width = 60;
|
||||
height = 8;
|
||||
direction = "horizontal";
|
||||
layout = [
|
||||
{
|
||||
type = "cover-art";
|
||||
width = 20;
|
||||
height = 20;
|
||||
}
|
||||
{
|
||||
type = "empty";
|
||||
size = 4;
|
||||
}
|
||||
{
|
||||
type = "container";
|
||||
direction = "vertical";
|
||||
children = [
|
||||
{
|
||||
type = "label";
|
||||
text = " $title";
|
||||
fg = "blue";
|
||||
}
|
||||
{
|
||||
type = "label";
|
||||
text = " $artists";
|
||||
fg = "gray";
|
||||
}
|
||||
{
|
||||
type = "label";
|
||||
text = " $album";
|
||||
fg = "gray";
|
||||
}
|
||||
{
|
||||
type = "container";
|
||||
children = [];
|
||||
}
|
||||
{
|
||||
type = "container";
|
||||
height = 1;
|
||||
align = "center";
|
||||
flex = "center";
|
||||
children = [
|
||||
{
|
||||
type = "button";
|
||||
text = "";
|
||||
action = "prev()";
|
||||
}
|
||||
{
|
||||
type = "empty";
|
||||
size = 3;
|
||||
}
|
||||
{
|
||||
type = "button";
|
||||
text = "$status-icon";
|
||||
action = "play_pause()";
|
||||
}
|
||||
{
|
||||
type = "empty";
|
||||
size = 3;
|
||||
}
|
||||
{
|
||||
type = "button";
|
||||
text = "";
|
||||
action = "next()";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "progress";
|
||||
progress = {
|
||||
char = "━";
|
||||
fg = "magenta";
|
||||
};
|
||||
empty = {
|
||||
char = "─";
|
||||
};
|
||||
}
|
||||
{
|
||||
type = "container";
|
||||
flex = "space-between";
|
||||
height = 1;
|
||||
children = [
|
||||
{
|
||||
type = "button";
|
||||
text = "$position";
|
||||
}
|
||||
{
|
||||
type = "button";
|
||||
text = "var($len-style, $length)";
|
||||
action = "toggle($len-style, $length, $remaining-length)";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{pkgs, ...}: {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
fzf
|
||||
];
|
||||
|
||||
xdg.configFile = {
|
||||
"fish/conf.d/fzf.fish".source = "${pkgs.fzf}/share/fzf/key-bindings.fish";
|
||||
|
||||
"fish/conf.d/fzf-extra.fish".text = ''
|
||||
set -gx FZF_DEFAULT_OPTS "--reverse --height 40% --border"
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{pkgs, ...}: let
|
||||
configFile = "gh/config.yml";
|
||||
hostsFile = "gh/hosts.yml";
|
||||
toYAML = (pkgs.formats.yaml {}).generate;
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
gh
|
||||
];
|
||||
|
||||
xdg.configFile."${configFile}".source = toYAML "config.yml" {
|
||||
version = 1;
|
||||
git_protocol = "https";
|
||||
editor = "nvim";
|
||||
prompt = "enabled";
|
||||
prefer_editor_prompt = "disabled";
|
||||
pager = "less -FR";
|
||||
aliases = {
|
||||
co = "pr checkout";
|
||||
};
|
||||
http_unix_socket = "";
|
||||
browser = "zen";
|
||||
};
|
||||
|
||||
xdg.configFile."${hostsFile}".text = ''
|
||||
github.com:
|
||||
git_protocol: https
|
||||
user: someone
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
configFile = "git/config";
|
||||
ignoreFile = "git/ignore";
|
||||
toINI = (pkgs.formats.ini {}).generate;
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
git
|
||||
delta
|
||||
gnupg
|
||||
git-lfs
|
||||
peco
|
||||
];
|
||||
|
||||
xdg.configFile."${configFile}".source = toINI "config" {
|
||||
alias = {
|
||||
af = "!git add $(git ls-files -m -o --exclude-standard | fzf -m)";
|
||||
br = "branch";
|
||||
ca = "commit -am";
|
||||
co = "checkout";
|
||||
d = "diff";
|
||||
df = "!git hist | peco | awk '{print $2}' | xargs -I {} git diff {}^ {}";
|
||||
"edit-unmerged" = "!f() { git ls-files --unmerged | cut -f2 | sort -u ; }; hx `f`";
|
||||
fuck = "commit --amend -m";
|
||||
hist = "log --pretty=format:\"%Cgreen%h %Creset%cd %Cblue[%cn] %Creset%s%C(yellow)%d%C(reset)\" --graph --date=relative --decorate --all";
|
||||
llog = "log --graph --name-status --pretty=format:\"%C(red)%h %C(reset)(%cd) %C(green)%an %Creset%s %C(yellow)%d%Creset\" --date=relative";
|
||||
pl = "!git pull origin $(git rev-parse --abbrev-ref HEAD)";
|
||||
ps = "!git push origin $(git rev-parse --abbrev-ref HEAD)";
|
||||
st = "status";
|
||||
};
|
||||
commit = {
|
||||
gpgSign = "true";
|
||||
};
|
||||
core = {
|
||||
editor = "nvim";
|
||||
pager = "${pkgs.delta}/bin/delta";
|
||||
whitespace = "fix,-indent-with-non-tab,trailing-space,cr-at-eol";
|
||||
excludesFile = "${config.xdg.configHome}/${ignoreFile}";
|
||||
};
|
||||
delta = {
|
||||
features = "unobtrusive-line-numbers decorations";
|
||||
navigate = "true";
|
||||
"side-by-side" = "true";
|
||||
"true-color" = "never";
|
||||
};
|
||||
"delta-decorations" = {
|
||||
"commit-decoration-style" = "bold grey box ul";
|
||||
"file-decoration-style" = "ul";
|
||||
"file-style" = "bold blue";
|
||||
"hunk-header-decoration-style" = "box";
|
||||
};
|
||||
"delta-unobtrusive-line-numbers" = {
|
||||
"line-numbers" = "true";
|
||||
"line-numbers-left-format" = "{nm:>4}│";
|
||||
"line-numbers-left-style" = "grey";
|
||||
"line-numbers-right-format" = "{np:>4}│";
|
||||
"line-numbers-right-style" = "grey";
|
||||
};
|
||||
diff = {
|
||||
colorMoved = "default";
|
||||
};
|
||||
"filter-lfs" = {
|
||||
clean = "git-lfs clean -- %f";
|
||||
process = "git-lfs filter-process";
|
||||
required = "true";
|
||||
smudge = "git-lfs smudge -- %f";
|
||||
};
|
||||
gpg = {
|
||||
format = "openpgp";
|
||||
};
|
||||
"gpg-openpgp" = {
|
||||
program = "${pkgs.gnupg}/bin/gpg";
|
||||
};
|
||||
init = {
|
||||
defaultBranch = "main";
|
||||
};
|
||||
interactive = {
|
||||
diffFilter = "${pkgs.delta}/bin/delta --color-only";
|
||||
};
|
||||
merge = {
|
||||
conflictstyle = "diff3";
|
||||
stat = "true";
|
||||
};
|
||||
pull = {
|
||||
ff = "only";
|
||||
};
|
||||
push = {
|
||||
autoSetupRemote = "true";
|
||||
default = "current";
|
||||
};
|
||||
rebase = {
|
||||
autoSquash = "true";
|
||||
autoStash = "true";
|
||||
};
|
||||
repack = {
|
||||
usedeltabaseoffset = "true";
|
||||
};
|
||||
rerere = {
|
||||
autoupdate = "true";
|
||||
enabled = "true";
|
||||
};
|
||||
tag = {
|
||||
gpgSign = "true";
|
||||
};
|
||||
user = {
|
||||
email = "jory@severijnse.eu";
|
||||
name = "Jory Severijnse";
|
||||
signingKey = "0F8835ED078FDBF2";
|
||||
};
|
||||
};
|
||||
|
||||
xdg.configFile."${ignoreFile}".text = ''
|
||||
*~
|
||||
*.swp
|
||||
*result*
|
||||
.direnv
|
||||
node_modules
|
||||
.opencode/
|
||||
.gemini/
|
||||
GEMINI.md
|
||||
AGENTS.md
|
||||
.sisyphus
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{pkgs, ...}: let
|
||||
configFile = "glow/glow.yml";
|
||||
toYAML = (pkgs.formats.yaml {}).generate;
|
||||
in {
|
||||
users.users.someone.packages = [pkgs.glow];
|
||||
xdg.configFile."${configFile}".source = toYAML "glow.yml" {
|
||||
style = "auto";
|
||||
mouse = false;
|
||||
pager = false;
|
||||
width = 80;
|
||||
all = false;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
gpgConfigFile = "gnupg/gpg.conf";
|
||||
agentConfigFile = "gnupg/gpg-agent.conf";
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
gnupg
|
||||
pinentry-gnome3
|
||||
];
|
||||
|
||||
xdg.configFile = {
|
||||
"${gpgConfigFile}".text = ''
|
||||
cert-digest-algo SHA512
|
||||
charset utf-8
|
||||
default-key 0F8835ED078FDBF2
|
||||
default-preference-list SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed
|
||||
fixed-list-mode
|
||||
keyid-format 0xlong
|
||||
list-options show-uid-validity
|
||||
no-comments
|
||||
no-emit-version
|
||||
no-symkey-cache
|
||||
personal-cipher-preferences AES256 AES192 AES
|
||||
personal-compress-preferences ZLIB BZIP2 ZIP Uncompressed
|
||||
personal-digest-preferences SHA512 SHA384 SHA256
|
||||
require-cross-certification
|
||||
s2k-cipher-algo AES256
|
||||
s2k-digest-algo SHA512
|
||||
use-agent
|
||||
verify-options show-uid-validity
|
||||
with-fingerprint
|
||||
'';
|
||||
"${agentConfigFile}".text = ''
|
||||
enable-ssh-support
|
||||
grab
|
||||
pinentry-program ${pkgs.pinentry-gnome3}/bin/pinentry-curses
|
||||
'';
|
||||
"fish/conf.d/gpg.fish".source = pkgs.writeText "gpg.fish" ''
|
||||
set -gx GPG_TTY (tty)
|
||||
${pkgs.gnupg}/bin/gpg-connect-agent --quiet updatestartuptty /bye >/dev/null
|
||||
'';
|
||||
};
|
||||
|
||||
environment.sessionVariables = {
|
||||
GPG_TTY = "$(tty)";
|
||||
SSH_AUTH_SOCK = "${config.xdg.runtimeDir}/gnupg/S.gpg-agent.ssh";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{pkgs, ...}: let
|
||||
configFile = "lazygit/config.yml";
|
||||
toYAML = (pkgs.formats.yaml {}).generate;
|
||||
in {
|
||||
users.users.someone.packages = [pkgs.lazygit];
|
||||
xdg.configFile."${configFile}".source = toYAML "config.yml" {
|
||||
disableStartupPopups = true;
|
||||
git = {
|
||||
commit = {
|
||||
signOff = true;
|
||||
};
|
||||
parseEmoji = true;
|
||||
};
|
||||
gui = {
|
||||
nerdFontsVersion = "3";
|
||||
showBottomLine = false;
|
||||
showCommandLog = false;
|
||||
showListFooter = false;
|
||||
showRandomTip = false;
|
||||
theme = {
|
||||
activeBorderColor = ["magenta" "bold"];
|
||||
inactiveBorderColor = ["black"];
|
||||
};
|
||||
};
|
||||
notARepository = "skip";
|
||||
promptToReturnFromSubprocess = false;
|
||||
update = {
|
||||
method = "never";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
{pkgs, ...}: let
|
||||
configFile = "mods/mods.yml";
|
||||
toYAML = (pkgs.formats.yaml {}).generate;
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
mods
|
||||
];
|
||||
|
||||
xdg.configFile = {
|
||||
"${configFile}".source = toYAML "mods.yml" {
|
||||
default-model = "google/gemma-3n-e4b-it:free";
|
||||
default-api = "openrouter";
|
||||
format-text = {
|
||||
markdown = "{{ index .Config.FormatText \"markdown\" }}";
|
||||
json = "{{ index .Config.FormatText \"json\" }}";
|
||||
};
|
||||
roles = {
|
||||
default = [];
|
||||
};
|
||||
format = false;
|
||||
role = "default";
|
||||
raw = false;
|
||||
quiet = false;
|
||||
temp = 1.0;
|
||||
topp = 1.0;
|
||||
topk = 50;
|
||||
no-limit = false;
|
||||
word-wrap = 80;
|
||||
include-prompt-args = false;
|
||||
include-prompt = 0;
|
||||
max-retries = 5;
|
||||
fanciness = 10;
|
||||
status-text = "Generating";
|
||||
theme = "charm";
|
||||
max-input-chars = 12250;
|
||||
max-completion-tokens = 100;
|
||||
apis = {
|
||||
openrouter = {
|
||||
base-url = "https://openrouter.ai/api/v1";
|
||||
api-key = "";
|
||||
api-key-env = "OPENROUTER_API_KEY";
|
||||
models = {
|
||||
"kwaipilot/kat-coder-pro:free" = {
|
||||
aliases = ["kat-coder"];
|
||||
max-input-chars = 256000;
|
||||
};
|
||||
"openrouter/polaris-alpha" = {
|
||||
aliases = ["polaris"];
|
||||
max-input-chars = 256000;
|
||||
};
|
||||
"deepseek/deepseek-chat-v3.1:free" = {
|
||||
aliases = ["deepseek"];
|
||||
max-input-chars = 164000;
|
||||
};
|
||||
"openai/gpt-oss-20b:free" = {
|
||||
aliases = ["gpt"];
|
||||
max-input-chars = 131000;
|
||||
};
|
||||
"qwen/qwen3-coder:free" = {
|
||||
aliases = ["qwen"];
|
||||
max-input-chars = 256000;
|
||||
};
|
||||
"google/gemma-3n-e4b-it:free" = {
|
||||
aliases = ["gemma"];
|
||||
max-input-chars = 8000;
|
||||
};
|
||||
"meta-llama/llama-4-maverick:free" = {
|
||||
aliases = ["maverick"];
|
||||
max-input-chars = 128000;
|
||||
};
|
||||
"moonshotai/kimi-k2:free" = {
|
||||
aliases = ["kimi"];
|
||||
max-input-chars = 33000;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
"fish/completions/mods.fish".source = "${pkgs.mods}/share/fish/vendor_completions.d/mods.fish";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{pkgs, ...}: {
|
||||
users.users.someone.packages = [pkgs.nix-your-shell];
|
||||
|
||||
xdg.configFile."fish/conf.d/nix-your-shell.fish".source = pkgs.runCommand "nix-your-shell-init" {} ''
|
||||
${pkgs.nix-your-shell}/bin/nix-your-shell fish > $out
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
direnvConfigFile = "direnv/direnv.toml";
|
||||
direnvRcFile = "direnv/direnvrc";
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
alejandra
|
||||
deadnix
|
||||
statix
|
||||
self.packages.${stdenv.hostPlatform.system}.repl
|
||||
direnv
|
||||
nix-direnv
|
||||
];
|
||||
|
||||
# Direnv configuration
|
||||
xdg = {
|
||||
configFile = {
|
||||
"${direnvConfigFile}".source = (pkgs.formats.toml {}).generate "direnv.toml" {
|
||||
global = {
|
||||
log_format = "-";
|
||||
log_filter = "^$";
|
||||
};
|
||||
};
|
||||
# Direnv stdlib configuration
|
||||
"${direnvRcFile}".text = ''
|
||||
# Nix integration
|
||||
source ${pkgs.nix-direnv}/share/nix-direnv/direnvrc
|
||||
'';
|
||||
|
||||
"fish/conf.d/direnv.fish".source = pkgs.runCommand "direnv-fish-hook" {} ''
|
||||
${pkgs.direnv}/bin/direnv hook fish > $out
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
environment.sessionVariables = {
|
||||
DIRENV_LOG_FORMAT = "";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
{pkgs}: let
|
||||
formatterBins = {
|
||||
alejandra = "${pkgs.alejandra}/bin/alejandra";
|
||||
biome = "${pkgs.biome}/bin/biome";
|
||||
oxfmt = "${pkgs.oxfmt}/bin/oxfmt";
|
||||
shfmt = "${pkgs.shfmt}/bin/shfmt";
|
||||
};
|
||||
|
||||
lspBins = {
|
||||
astro-ls = "${pkgs.astro-language-server}/bin/astro-ls";
|
||||
biome = "${pkgs.biome}/bin/biome";
|
||||
marksman = "${pkgs.marksman}/bin/marksman";
|
||||
nil = "${pkgs.nil}/bin/nil";
|
||||
tailwindcss = "${pkgs.tailwindcss-language-server}/bin/tailwindcss-language-server";
|
||||
volar = "${pkgs.vue-language-server}/bin/vue-language-server";
|
||||
};
|
||||
in {
|
||||
packages = with pkgs; [
|
||||
astro-language-server
|
||||
biome
|
||||
marksman
|
||||
nil
|
||||
tailwindcss-language-server
|
||||
vue-language-server
|
||||
alejandra
|
||||
oxfmt
|
||||
shfmt
|
||||
];
|
||||
|
||||
formatter = {
|
||||
shfmt = {
|
||||
command = [formatterBins.shfmt "-i" "2"];
|
||||
extensions = ["sh" "bash"];
|
||||
};
|
||||
oxfmt = {
|
||||
command = [formatterBins.oxfmt];
|
||||
extensions = ["yaml" "js" "json" "jsx" "md" "ts" "tsx" "css" "html" "vue"];
|
||||
};
|
||||
biome = {
|
||||
command = [formatterBins.biome "format" "--stdin-file-path"];
|
||||
extensions = ["astro"];
|
||||
};
|
||||
alejandra = {
|
||||
command = [formatterBins.alejandra "-q"];
|
||||
extensions = ["nix"];
|
||||
};
|
||||
};
|
||||
|
||||
lsp = {
|
||||
astro-ls = {
|
||||
command = [lspBins.astro-ls "--stdio"];
|
||||
extensions = ["astro"];
|
||||
};
|
||||
biome = {
|
||||
command = [lspBins.biome "lsp-proxy"];
|
||||
extensions = ["js" "ts" "json" "jsx" "tsx"];
|
||||
};
|
||||
nil = {
|
||||
command = [lspBins.nil];
|
||||
extensions = ["nix"];
|
||||
};
|
||||
marksman = {
|
||||
command = [lspBins.marksman];
|
||||
extensions = ["md"];
|
||||
};
|
||||
tailwindcss = {
|
||||
command = [lspBins.tailwindcss "--stdio"];
|
||||
extensions = ["css" "html"];
|
||||
};
|
||||
volar = {
|
||||
command = [lspBins.volar "--stdio"];
|
||||
extensions = ["vue"];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
{
|
||||
config = {
|
||||
google = {
|
||||
npm = "@ai-sdk/google";
|
||||
models = {
|
||||
antigravity-gemini-3-pro = {
|
||||
name = "Gemini 3 Pro (Antigravity)";
|
||||
limit = {
|
||||
context = 1048576;
|
||||
output = 65535;
|
||||
};
|
||||
modalities = {
|
||||
input = ["text" "image" "pdf"];
|
||||
output = ["text"];
|
||||
};
|
||||
variants = {
|
||||
low = {thinkingLevel = "low";};
|
||||
high = {thinkingLevel = "high";};
|
||||
};
|
||||
};
|
||||
antigravity-gemini-3-flash = {
|
||||
name = "Gemini 3 Flash (Antigravity)";
|
||||
limit = {
|
||||
context = 1048576;
|
||||
output = 65536;
|
||||
};
|
||||
modalities = {
|
||||
input = ["text" "image" "pdf"];
|
||||
output = ["text"];
|
||||
};
|
||||
variants = {
|
||||
minimal = {thinkingLevel = "minimal";};
|
||||
low = {thinkingLevel = "low";};
|
||||
medium = {thinkingLevel = "medium";};
|
||||
high = {thinkingLevel = "high";};
|
||||
};
|
||||
};
|
||||
antigravity-claude-sonnet-4-5 = {
|
||||
name = "Claude Sonnet 4.5 (Antigravity)";
|
||||
limit = {
|
||||
context = 200000;
|
||||
output = 64000;
|
||||
};
|
||||
modalities = {
|
||||
input = ["text" "image" "pdf"];
|
||||
output = ["text"];
|
||||
};
|
||||
};
|
||||
antigravity-claude-sonnet-4-5-thinking = {
|
||||
name = "Claude Sonnet 4.5 Thinking (Antigravity)";
|
||||
limit = {
|
||||
context = 200000;
|
||||
output = 64000;
|
||||
};
|
||||
modalities = {
|
||||
input = ["text" "image" "pdf"];
|
||||
output = ["text"];
|
||||
};
|
||||
variants = {
|
||||
low = {thinkingConfig = {thinkingBudget = 8192;};};
|
||||
max = {thinkingConfig = {thinkingBudget = 32768;};};
|
||||
};
|
||||
};
|
||||
antigravity-claude-opus-4-5-thinking = {
|
||||
name = "Claude Opus 4.5 Thinking (Antigravity)";
|
||||
limit = {
|
||||
context = 200000;
|
||||
output = 64000;
|
||||
};
|
||||
modalities = {
|
||||
input = ["text" "image" "pdf"];
|
||||
output = ["text"];
|
||||
};
|
||||
variants = {
|
||||
low = {thinkingConfig = {thinkingBudget = 8192;};};
|
||||
max = {thinkingConfig = {thinkingBudget = 32768;};};
|
||||
};
|
||||
};
|
||||
antigravity-claude-opus-4-6-thinking = {
|
||||
name = "Claude Opus 4.6 Thinking (Antigravity)";
|
||||
limit = {
|
||||
context = 200000;
|
||||
output = 64000;
|
||||
};
|
||||
modalities = {
|
||||
input = ["text" "image" "pdf"];
|
||||
output = ["text"];
|
||||
};
|
||||
variants = {
|
||||
low = {thinkingConfig = {thinkingBudget = 8192;};};
|
||||
max = {thinkingConfig = {thinkingBudget = 32768;};};
|
||||
};
|
||||
};
|
||||
gemini-2-5-flash = {
|
||||
name = "Gemini 2.5 Flash (Gemini CLI)";
|
||||
limit = {
|
||||
context = 1048576;
|
||||
output = 65536;
|
||||
};
|
||||
modalities = {
|
||||
input = ["text" "image" "pdf"];
|
||||
output = ["text"];
|
||||
};
|
||||
};
|
||||
gemini-2-5-pro = {
|
||||
name = "Gemini 2.5 Pro (Gemini CLI)";
|
||||
limit = {
|
||||
context = 1048576;
|
||||
output = 65536;
|
||||
};
|
||||
modalities = {
|
||||
input = ["text" "image" "pdf"];
|
||||
output = ["text"];
|
||||
};
|
||||
};
|
||||
gemini-3-flash-preview = {
|
||||
name = "Gemini 3 Flash Preview (Gemini CLI)";
|
||||
limit = {
|
||||
context = 1048576;
|
||||
output = 65536;
|
||||
};
|
||||
modalities = {
|
||||
input = ["text" "image" "pdf"];
|
||||
output = ["text"];
|
||||
};
|
||||
};
|
||||
gemini-3-pro-preview = {
|
||||
name = "Gemini 3 Pro Preview (Gemini CLI)";
|
||||
limit = {
|
||||
context = 1048576;
|
||||
output = 65535;
|
||||
};
|
||||
modalities = {
|
||||
input = ["text" "image" "pdf"];
|
||||
output = ["text"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
{pkgs}: let
|
||||
fetchSkill = {
|
||||
name,
|
||||
owner,
|
||||
repo,
|
||||
rev,
|
||||
path,
|
||||
hash,
|
||||
}:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "opencode-skill-${name}";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
inherit owner repo rev hash;
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp ${path} $out/SKILL.md
|
||||
'';
|
||||
};
|
||||
|
||||
fetchSkillDir = {
|
||||
name,
|
||||
owner,
|
||||
repo,
|
||||
rev,
|
||||
basePath,
|
||||
hash,
|
||||
}:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "opencode-skill-${name}";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
inherit owner repo rev hash;
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -r ${basePath}/* $out/
|
||||
'';
|
||||
};
|
||||
|
||||
localSkill = {
|
||||
name,
|
||||
path,
|
||||
}:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "opencode-skill-${name}";
|
||||
src = path;
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp SKILL.md $out/SKILL.md
|
||||
'';
|
||||
};
|
||||
|
||||
skills = {
|
||||
technical-writing = fetchSkill {
|
||||
name = "technical-writing";
|
||||
owner = "proffesor-for-testing";
|
||||
repo = "agentic-qe";
|
||||
rev = "990aee4a6a747f2db0ef77a2f67d58462f61e608";
|
||||
path = ".claude/skills/technical-writing/SKILL.md";
|
||||
hash = "sha256-PdIVhLp5/quigz325ZeG4NaWUgPsD3PgykSD61FFjLo=";
|
||||
};
|
||||
|
||||
blog-post-writer = fetchSkillDir {
|
||||
name = "blog-post-writer";
|
||||
owner = "nicknisi";
|
||||
repo = "dotfiles";
|
||||
rev = "f1be3f2b669c8e3401b589141f9a56651e45a1a7";
|
||||
basePath = "home/.claude/skills/blog-post-writer";
|
||||
hash = "sha256-U1GqtQMgzimGbbDJpqIGrBnu5HiSTZDETAKFhijMU9s=";
|
||||
};
|
||||
|
||||
frontend-design = fetchSkill {
|
||||
name = "frontend-design";
|
||||
owner = "anthropics";
|
||||
repo = "claude-code";
|
||||
rev = "d213a74fc8e3b6efded52729196e0c2d4c3abb3e";
|
||||
path = "plugins/frontend-design/skills/frontend-design/SKILL.md";
|
||||
hash = "sha256-SleLxTUjM7HNHc78YklikuFwix2DPaTDIACUnsSQCrA=";
|
||||
};
|
||||
|
||||
flutter-development = fetchSkill {
|
||||
name = "flutter-development";
|
||||
owner = "aj-geddes";
|
||||
repo = "useful-ai-prompts";
|
||||
rev = "ce8c39c22df0e0e64c853817a7f8d79f0ea331e2";
|
||||
path = "skills/flutter-development/SKILL.md";
|
||||
hash = "sha256-BCvO+P2URoTiUOSV8PTq62ckyxXLEHtIml0EkZGRbK8=";
|
||||
};
|
||||
|
||||
writing-documentation = fetchSkillDir {
|
||||
name = "writing-documentation";
|
||||
owner = "dhruvbaldawa";
|
||||
repo = "ccconfigs";
|
||||
rev = "451b604718d39fcc2c008d22e550bdf60c7115da";
|
||||
basePath = "essentials/skills/writing-documentation";
|
||||
hash = "sha256-7V1xG2FmzqWdnWmVV6WWKBAvY6QHWo+UKzh0Uu/Xg/w=";
|
||||
};
|
||||
|
||||
changelog-generator = fetchSkill {
|
||||
name = "changelog-generator";
|
||||
owner = "composioHQ";
|
||||
repo = "awesome-claude-skills";
|
||||
rev = "362d35428562ad05d1faa1767abaf39d6e3a8e7a";
|
||||
path = "changelog-generator/SKILL.md";
|
||||
hash = "sha256-tSEO0h9J3lPVePFoy7A7c1K6umNNE/21/2RbaJD4Abc=";
|
||||
};
|
||||
|
||||
readme-generator = fetchSkill {
|
||||
name = "readme-generator";
|
||||
owner = "Shpigford";
|
||||
repo = "skills";
|
||||
rev = "bdd6f84e38e460246079dd44755c587522ddf60e";
|
||||
path = "readme/SKILL.md";
|
||||
hash = "sha256-M6ZSxwrq9tGkxJi6BVoSRh6+fPlQPUmZVg595wldsNI=";
|
||||
};
|
||||
|
||||
memory-aware-architect = localSkill {
|
||||
name = "memory-aware-architect";
|
||||
path = ./skills/memory-aware-architect;
|
||||
};
|
||||
};
|
||||
|
||||
allSkills = pkgs.runCommand "opencode-skills" {} ''
|
||||
mkdir -p $out/skill
|
||||
|
||||
${pkgs.lib.concatStringsSep "\n" (pkgs.lib.mapAttrsToList (name: skill: ''
|
||||
mkdir -p $out/skill/${name}
|
||||
cp -r ${skill}/* $out/skill/${name}/
|
||||
'')
|
||||
skills)}
|
||||
'';
|
||||
in {
|
||||
packages = [];
|
||||
skillsSource = allSkills;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
{pkgs, ...}: let
|
||||
languages = import ./_languages.nix {inherit pkgs;};
|
||||
providers = import ./_providers.nix;
|
||||
skills = import ./_skills.nix {inherit pkgs;};
|
||||
|
||||
inherit (pkgs) opencode;
|
||||
|
||||
opencodeEnv = pkgs.buildEnv {
|
||||
name = "opencode-env";
|
||||
paths =
|
||||
languages.packages
|
||||
++ skills.packages;
|
||||
};
|
||||
opencodeInitScript = pkgs.writeShellScript "opencode-init" ''
|
||||
mkdir -p "$HOME/.local/cache/opencode/node_modules/@opencode-ai"
|
||||
mkdir -p "$HOME/.config/opencode/node_modules/@opencode-ai"
|
||||
if [ -d "$HOME/.config/opencode/node_modules/@opencode-ai/plugin" ]; then
|
||||
if [ ! -L "$HOME/.local/cache/opencode/node_modules/@opencode-ai/plugin" ]; then
|
||||
ln -sf "$HOME/.config/opencode/node_modules/@opencode-ai/plugin" \
|
||||
"$HOME/.local/cache/opencode/node_modules/@opencode-ai/plugin"
|
||||
fi
|
||||
fi
|
||||
exec ${opencode}/bin/opencode "$@"
|
||||
'';
|
||||
opencodeWrapped =
|
||||
pkgs.runCommand "opencode-wrapped" {
|
||||
buildInputs = [pkgs.makeWrapper];
|
||||
} ''
|
||||
mkdir -p $out/bin
|
||||
makeWrapper ${opencodeInitScript} $out/bin/opencode \
|
||||
--prefix PATH : ${opencodeEnv}/bin \
|
||||
--prefix LD_LIBRARY_PATH : "${pkgs.lib.makeLibraryPath [pkgs.stdenv.cc.cc.lib]}"
|
||||
'';
|
||||
configFile = "opencode/config.json";
|
||||
tuiFile = "opencode/tui.json";
|
||||
in {
|
||||
users.users.someone.packages = [
|
||||
opencodeWrapped
|
||||
];
|
||||
xdg.configFile = {
|
||||
"${configFile}".text = builtins.toJSON {
|
||||
"$schema" = "https://opencode.ai/config.json";
|
||||
plugin = [
|
||||
"opencode-antigravity-auth@latest"
|
||||
"@tarquinen/opencode-dcp@latest"
|
||||
"oh-my-openagent@latest"
|
||||
];
|
||||
small_model = "google/gemma-3n-e4b-it:free";
|
||||
autoupdate = false;
|
||||
share = "disabled";
|
||||
disabled_providers = [
|
||||
"amazon-bedrock"
|
||||
"anthropic"
|
||||
"azure-openai"
|
||||
"azure-cognitive-services"
|
||||
"baseten"
|
||||
"cerebras"
|
||||
"cloudflare-ai-gateway"
|
||||
"cortecs"
|
||||
"deep-infra"
|
||||
"fireworks-ai"
|
||||
"google-vertex-ai"
|
||||
"groq"
|
||||
"hugging-face"
|
||||
"helicone"
|
||||
"llama.cpp"
|
||||
"io-net"
|
||||
"lmstudio"
|
||||
"moonshot-ai"
|
||||
"nebius-token-factory"
|
||||
"ollama"
|
||||
"ollama-cloud"
|
||||
"openai"
|
||||
"sap-ai-core"
|
||||
"ovhcloud-ai-endpoints"
|
||||
"together-ai"
|
||||
"venice-ai"
|
||||
"xai"
|
||||
"zai"
|
||||
"zenmux"
|
||||
];
|
||||
enabled_providers = ["opencode" "google" "openrouter"];
|
||||
mcp = {
|
||||
gh_grep = {
|
||||
type = "remote";
|
||||
url = "https://mcp.grep.app/";
|
||||
enabled = true;
|
||||
timeout = 10000;
|
||||
};
|
||||
deepwiki = {
|
||||
type = "remote";
|
||||
url = "https://mcp.deepwiki.com/mcp";
|
||||
enabled = true;
|
||||
timeout = 10000;
|
||||
};
|
||||
context7 = {
|
||||
type = "remote";
|
||||
url = "https://mcp.context7.com/mcp";
|
||||
enabled = true;
|
||||
timeout = 10000;
|
||||
};
|
||||
};
|
||||
inherit (languages) formatter lsp;
|
||||
provider = providers.config;
|
||||
};
|
||||
"${tuiFile}".text = builtins.toJSON {
|
||||
"$schema" = "https://opencode.ai/tui.json";
|
||||
theme = "gruvbox";
|
||||
};
|
||||
"opencode/skill".source = skills.skillsSource + "/skill";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
---
|
||||
name: memory-aware-architect
|
||||
description: Mandatory persistent memory integration for project development. Use when working on any codebase that uses opencode-mem for context persistence. Always searches memory before planning, coding, refactoring, or debugging. Suggests adding new facts after completing significant tasks. Works with any programming language, framework, or architecture style.
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Memory-Aware Architect
|
||||
|
||||
## Core Workflow (Mandatory)
|
||||
|
||||
### 1. Search Memory First (Required at Task Start)
|
||||
|
||||
Before responding to any architecture, refactoring, feature implementation, debugging, or project-related query, execute one or more semantic searches in persistent memory using the `memory` tool.
|
||||
|
||||
Craft specific, descriptive queries based on the user's task and the project context:
|
||||
|
||||
```javascript
|
||||
// Architecture & design patterns
|
||||
memory({ mode: "search", query: "architecture pattern layers components structure" })
|
||||
|
||||
// Technology stack & frameworks
|
||||
memory({ mode: "search", query: "framework library dependencies tech stack" })
|
||||
|
||||
// Error handling & logging
|
||||
memory({ mode: "search", query: "error handling logging monitoring patterns" })
|
||||
|
||||
// Testing strategy
|
||||
memory({ mode: "search", query: "testing unit integration e2e test patterns" })
|
||||
|
||||
// Specific features or modules
|
||||
memory({ mode: "search", query: "authentication user management JWT session" })
|
||||
memory({ mode: "search", query: "database schema models relationships ORM" })
|
||||
memory({ mode: "search", query: "API endpoints routes controllers handlers" })
|
||||
```
|
||||
|
||||
**Key principles for effective searches:**
|
||||
- Include relevant technical terms from the user's request
|
||||
- Search for both broad patterns and specific implementations
|
||||
- When user mentions modules/components/features, include those exact terms
|
||||
- Run multiple searches if the task involves different aspects (e.g., frontend + backend + database)
|
||||
|
||||
### 2. Integrate Retrieved Facts
|
||||
|
||||
- Use retrieved memories to inform all planning, reasoning, and code generation
|
||||
- Never re-explain concepts, patterns, or decisions already stored in memory
|
||||
- Trust the existing memory over assumptions—the project has its own conventions
|
||||
- If critical context is missing, ask for clarification—but prioritize existing memory content
|
||||
- If no relevant memories found, mention: "No prior context found in memory for [topic]"
|
||||
|
||||
### 3. Add New Knowledge (After Significant Work)
|
||||
|
||||
After completing important tasks (refactors, new features, architectural decisions, significant fixes), identify valuable new knowledge and suggest adding it to memory:
|
||||
|
||||
```javascript
|
||||
memory({ mode: "add", content: "[concise, precise description of new decision/implementation]" })
|
||||
```
|
||||
|
||||
**What makes good memory content:**
|
||||
- Architectural decisions and their rationale
|
||||
- Established patterns and conventions
|
||||
- Technology choices and configuration details
|
||||
- Non-obvious implementation details
|
||||
- Gotchas, edge cases, or lessons learned
|
||||
- Integration patterns between components
|
||||
- Performance optimizations applied
|
||||
|
||||
**Examples across different project types:**
|
||||
|
||||
```javascript
|
||||
// Frontend project
|
||||
memory({ mode: "add", content: "Use React.memo() for all list item components to prevent unnecessary re-renders; measured 40% performance improvement" })
|
||||
|
||||
// Backend API
|
||||
memory({ mode: "add", content: "All API endpoints use middleware chain: auth → rate-limit → validation → controller; defined in src/middleware/index.js" })
|
||||
|
||||
// Database
|
||||
memory({ mode: "add", content: "User sessions table uses UUID v4 for session_id with 24-hour TTL; cleanup cron runs daily at 3 AM UTC" })
|
||||
|
||||
// DevOps
|
||||
memory({ mode: "add", content: "Deploy staging with 'npm run deploy:staging'; auto-runs migrations and health checks before traffic switch" })
|
||||
|
||||
// Architecture decision
|
||||
memory({ mode: "add", content: "Switched from REST to GraphQL for mobile API to reduce over-fetching; web still uses REST for caching benefits" })
|
||||
```
|
||||
|
||||
## Universal Best Practices
|
||||
|
||||
These guidelines apply regardless of project type, but always defer to project-specific patterns stored in memory:
|
||||
|
||||
### Memory-First Mindset
|
||||
- **Always search before assuming** - The project may have established conventions
|
||||
- **Consistency over cleverness** - Follow existing patterns even if you'd do it differently
|
||||
- **Document decisions, not just code** - Future you (or Claude) needs to understand *why*
|
||||
|
||||
### What to Search For
|
||||
- Project structure and organization
|
||||
- Naming conventions (files, functions, variables, classes)
|
||||
- Error handling and logging patterns
|
||||
- Testing approaches and tools
|
||||
- Code style preferences (formatting, comments, documentation)
|
||||
- Dependency management and versions
|
||||
- Build and deployment processes
|
||||
- Third-party integrations and API patterns
|
||||
|
||||
### What to Add to Memory
|
||||
- Deviations from framework defaults
|
||||
- Performance optimizations
|
||||
- Security considerations
|
||||
- Cross-cutting concerns (auth, logging, caching, etc.)
|
||||
- Module/component responsibilities
|
||||
- Data flow and state management
|
||||
- Configuration and environment setup
|
||||
- Team conventions and preferences
|
||||
|
||||
## Example Usage Patterns
|
||||
|
||||
### User: "Add user authentication to the app"
|
||||
|
||||
**Correct Response Flow:**
|
||||
1. Search memory: "authentication", "user management", "security patterns", "session handling"
|
||||
2. Check what auth approach is already established (JWT? Sessions? OAuth?)
|
||||
3. Apply existing security patterns from memory
|
||||
4. Implement following project conventions
|
||||
5. Suggest adding: "Implemented JWT authentication with refresh tokens; access token TTL 15min, refresh TTL 7 days; stored in httpOnly cookies"
|
||||
|
||||
### User: "Fix the bug where the dashboard loads slowly"
|
||||
|
||||
**Correct Response Flow:**
|
||||
1. Search memory: "dashboard", "performance", "loading", "caching", "data fetching"
|
||||
2. Identify existing performance patterns or known issues from memory
|
||||
3. Debug using project-specific context
|
||||
4. If you find and fix a non-obvious issue, suggest adding: "Dashboard slow load caused by N+1 query in user stats endpoint; fixed with single JOIN query and added Redis cache (5min TTL)"
|
||||
|
||||
### User: "Refactor the payment module to be more testable"
|
||||
|
||||
**Correct Response Flow:**
|
||||
1. Search memory: "payment", "testing patterns", "dependency injection", "mocking"
|
||||
2. Apply project's established testing and architecture patterns
|
||||
3. Refactor maintaining consistency with existing code structure
|
||||
4. Suggest adding: "Refactored PaymentService to use dependency injection; accepts payment gateway as constructor param for easier mocking in tests"
|
||||
|
||||
## Anti-Patterns to Avoid
|
||||
|
||||
- ❌ Skipping the initial memory search (breaks continuity)
|
||||
- ❌ Re-explaining concepts already in memory (wastes tokens)
|
||||
- ❌ Ignoring retrieved patterns when generating code (creates inconsistency)
|
||||
- ❌ Forgetting to suggest memory additions after significant work (loses knowledge)
|
||||
- ❌ Assuming standard conventions without checking memory first (may conflict with project)
|
||||
- ❌ Adding trivial or obvious information to memory (noise)
|
||||
- ❌ Writing vague memory content like "implemented feature X" (not useful later)
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**When to Search Memory:**
|
||||
- Start of any development task
|
||||
- Before making architectural decisions
|
||||
- When encountering unfamiliar parts of codebase
|
||||
- Before refactoring existing code
|
||||
- When debugging issues
|
||||
- When adding new features or modules
|
||||
|
||||
**When to Add to Memory:**
|
||||
- After implementing significant features
|
||||
- When making architectural decisions
|
||||
- After fixing non-trivial bugs
|
||||
- When establishing new patterns or conventions
|
||||
- After performance optimizations
|
||||
- When integrating external services
|
||||
- After learning project-specific gotchas
|
||||
|
||||
**Default Response Flow:**
|
||||
```
|
||||
1. memory search (1+ queries based on task)
|
||||
↓
|
||||
2. analyze retrieved facts and patterns
|
||||
↓
|
||||
3. generate solution consistent with project
|
||||
↓
|
||||
4. suggest memory add for new knowledge (if applicable)
|
||||
```
|
||||
|
||||
**Search Query Formula:**
|
||||
```
|
||||
[feature/module name] + [technical aspect] + [related patterns]
|
||||
|
||||
Examples:
|
||||
- "user profile component React state management"
|
||||
- "payment processing error handling retry logic"
|
||||
- "database migration rollback strategy"
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
{pkgs, ...}: {
|
||||
users.users.someone.packages = [pkgs.pay-respects];
|
||||
|
||||
xdg.configFile."fish/conf.d/pay-respects.fish".source = pkgs.runCommand "pay-respects-init" {} ''
|
||||
${pkgs.pay-respects}/bin/pay-respects fish --alias > $out
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{pkgs, ...}: let
|
||||
configFile = "skim/skimrc";
|
||||
|
||||
skimDefault = pkgs.symlinkJoin {
|
||||
name = "sk-default";
|
||||
paths = [pkgs.skim];
|
||||
buildInputs = [pkgs.makeWrapper];
|
||||
postBuild = ''
|
||||
wrapProgram $out/bin/sk \
|
||||
--add-flags "--cmd '${pkgs.ripgrep}/bin/rg --files --hidden'"
|
||||
'';
|
||||
};
|
||||
|
||||
skimCd = pkgs.writeShellScriptBin "sk-cd" ''
|
||||
exec ${pkgs.skim}/bin/sk \
|
||||
--preview "${pkgs.eza}/bin/eza --icons --git --color always -T -L 3 {} | head -200" \
|
||||
--exact \
|
||||
"$@"
|
||||
'';
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
skim
|
||||
ripgrep
|
||||
eza
|
||||
skimDefault
|
||||
skimCd
|
||||
];
|
||||
|
||||
xdg.configFile = {
|
||||
"${configFile}".text = ''
|
||||
preview-window: "right:60%"
|
||||
# General settings
|
||||
multi: true
|
||||
tiebreak: "index,begin,end,length"
|
||||
'';
|
||||
|
||||
"fish/conf.d/skim.fish".source = "${pkgs.skim}/share/fish/vendor_completions.d/sk.fish";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
sshConfigFile = "ssh/config";
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
openssh
|
||||
];
|
||||
|
||||
xdg.configFile."ssh/config" = {
|
||||
source = config.age.secrets.ssh_config.path;
|
||||
};
|
||||
|
||||
home.file.".ssh/config" = {
|
||||
source = config.xdg.configHome + "/ssh/config";
|
||||
mutable = false;
|
||||
};
|
||||
|
||||
environment.sessionVariables = {
|
||||
SSH_AUTH_SOCK = "${config.xdg.runtimeDir}/gnupg/S.gpg-agent.ssh";
|
||||
SSH_CONFIG = "${config.xdg.configHome}/ssh/config";
|
||||
};
|
||||
|
||||
systemd.user.services.ssh-agent = {
|
||||
description = "SSH agent service";
|
||||
wantedBy = ["default.target"];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.openssh}/bin/ssh-agent -D -a ${config.xdg.runtimeDir}/ssh-agent.socket";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{pkgs, ...}: {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
television
|
||||
nix-search-tv
|
||||
];
|
||||
|
||||
xdg.configFile = {
|
||||
"nix-search-tv/config.json".text = builtins.toJSON {
|
||||
indexes = ["nixos" "nixpkgs" "nur"];
|
||||
};
|
||||
"fish/completions/tv.fish".source = "${pkgs.television}/share/fish/vendor_completions.d/tv.fish";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
users.users.someone.packages = with pkgs;
|
||||
[
|
||||
# archives
|
||||
zip
|
||||
unzip
|
||||
unrar
|
||||
ouch
|
||||
|
||||
# misc
|
||||
mako
|
||||
fontconfig
|
||||
|
||||
# utils
|
||||
dust
|
||||
duf
|
||||
fd
|
||||
file
|
||||
killall
|
||||
jq
|
||||
ps_mem
|
||||
inshellisense
|
||||
|
||||
fum
|
||||
gtt
|
||||
meteor-git
|
||||
nix-search-tv
|
||||
scope-tui
|
||||
tuicam
|
||||
wiremix
|
||||
zfxtop
|
||||
opencode
|
||||
]
|
||||
++ (with inputs.mynixpkgs.packages.${stdenv.hostPlatform.system}; [
|
||||
dawn
|
||||
dfft
|
||||
loupe
|
||||
nekot
|
||||
omm
|
||||
prs
|
||||
]);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
{pkgs, ...}: let
|
||||
twitchHLSConfig = "twitch-hls-client/config";
|
||||
twtConfig = "twt/config.toml";
|
||||
|
||||
toINI = (pkgs.formats.ini {}).generate;
|
||||
toTOML = (pkgs.formats.toml {}).generate;
|
||||
|
||||
twitchHLSSettings = {
|
||||
General = {
|
||||
quality = "best";
|
||||
debug = false;
|
||||
};
|
||||
Player = {
|
||||
player = "${pkgs.mpv}/bin/mpv";
|
||||
player-args = "- --profile=low-latency";
|
||||
quiet = true;
|
||||
no-kill = false;
|
||||
};
|
||||
HLS = {
|
||||
servers = "https://eu.luminous.dev/live/[channel],https://eu2.luminous.dev/live/[channel],https://as.luminous.dev/live/[channel]";
|
||||
print-streams = false;
|
||||
no-low-latency = false;
|
||||
codecs = "av1,h265,h264";
|
||||
};
|
||||
HTTP = {
|
||||
force-https = true;
|
||||
force-ipv4 = false;
|
||||
user-agent = "Mozilla/5.0 (X11; Linux x86_64; rv:143.0) Gecko/20100101 Firefox/143.0";
|
||||
http-retries = 3;
|
||||
http-timeout = 10;
|
||||
};
|
||||
};
|
||||
|
||||
twtSettings = {
|
||||
twitch = {
|
||||
username = "someone";
|
||||
channel = "bunzopy";
|
||||
server = "irc.chat.twitch.tv";
|
||||
};
|
||||
terminal = {
|
||||
delay = 30;
|
||||
maximum_messages = 500;
|
||||
verbose = false;
|
||||
first_state = "Dashboard";
|
||||
};
|
||||
storage = {
|
||||
channels = true;
|
||||
mentions = false;
|
||||
};
|
||||
filters = {
|
||||
enabled = false;
|
||||
reversed = false;
|
||||
};
|
||||
frontend = {
|
||||
show_datetimes = false;
|
||||
datetime_format = "%a %b %e %T";
|
||||
username_shown = true;
|
||||
palette = "vibrant";
|
||||
title_shown = true;
|
||||
margin = 0;
|
||||
badges = false;
|
||||
theme = "dark";
|
||||
username_highlight = true;
|
||||
state_tabs = false;
|
||||
cursor_shape = "user";
|
||||
blinking_cursor = false;
|
||||
inverted_scrolling = false;
|
||||
show_scroll_offset = false;
|
||||
twitch_emotes = false;
|
||||
betterttv_emotes = false;
|
||||
seventv_emotes = false;
|
||||
frankerfacez_emotes = false;
|
||||
favorite_channels = ["oxatani" "roman_pascucci"];
|
||||
recent_channel_count = 5;
|
||||
border_type = "plain";
|
||||
hide_chat_border = false;
|
||||
right_align_usernames = false;
|
||||
show_unsupported_screen_size = true;
|
||||
};
|
||||
};
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
twitch-hls-client
|
||||
mpv
|
||||
];
|
||||
|
||||
xdg.configFile."${twitchHLSConfig}".source = toINI "config" twitchHLSSettings;
|
||||
xdg.configFile."${twtConfig}".source = toTOML "config.toml" twtSettings;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
browser = ["zen.desktop"];
|
||||
imageViewer = ["lightview.desktop"];
|
||||
videoPlayer = ["mpv.desktop"];
|
||||
audioPlayer = ["io.bassi.Amberol.desktop"];
|
||||
|
||||
xdgAssociations = type: program: list:
|
||||
builtins.listToAttrs (map (e: {
|
||||
name = "${type}/${e}";
|
||||
value = program;
|
||||
})
|
||||
list);
|
||||
|
||||
image = xdgAssociations "image" imageViewer ["png" "jpg" "jpeg" "gif" "webp" "bmp" "tiff" "tif" "ico" "svg" "avif" "heic" "heif"];
|
||||
video = xdgAssociations "video" videoPlayer ["mp4" "avi" "mkv" "mov" "wmv" "flv" "webm" "m4v" "3gp" "ogv" "ts" "mts" "m2ts"];
|
||||
audio = xdgAssociations "audio" audioPlayer ["mp3" "flac" "wav" "aac" "ogg" "oga" "opus" "m4a" "wma" "ape" "alac" "aiff"];
|
||||
|
||||
browserTypes =
|
||||
(xdgAssociations "application" browser ["json" "x-extension-htm" "x-extension-html" "x-extension-shtml" "x-extension-xht" "x-extension-xhtml"])
|
||||
// (xdgAssociations "x-scheme-handler" browser ["about" "ftp" "http" "https" "unknown"]);
|
||||
|
||||
associations =
|
||||
{
|
||||
"application/pdf" = ["org.gnome.Papers.desktop"];
|
||||
"application/zip" = ["org.gnome.FileRoller.desktop"];
|
||||
"application/x-7z-compressed" = ["org.gnome.FileRoller.desktop"];
|
||||
"application/x-rar-compressed" = ["org.gnome.FileRoller.desktop"];
|
||||
"application/x-tar" = ["org.gnome.FileRoller.desktop"];
|
||||
"application/gzip" = ["org.gnome.FileRoller.desktop"];
|
||||
"text/html" = browser;
|
||||
"text/plain" = ["org.gnome.TextEditor.desktop"];
|
||||
"text/markdown" = ["org.gnome.TextEditor.desktop"];
|
||||
"x-scheme-handler/chrome" = ["zen.desktop"];
|
||||
}
|
||||
// image // video // audio // browserTypes;
|
||||
|
||||
userDirsConfig = pkgs.writeText "user-dirs.dirs" ''
|
||||
XDG_DESKTOP_DIR="$HOME/Desktop"
|
||||
XDG_DOWNLOAD_DIR="$HOME/Downloads"
|
||||
XDG_TEMPLATES_DIR="$HOME/Templates"
|
||||
XDG_PUBLICSHARE_DIR="$HOME/Public"
|
||||
XDG_DOCUMENTS_DIR="$HOME/Documents"
|
||||
XDG_MUSIC_DIR="$HOME/Music"
|
||||
XDG_PICTURES_DIR="$HOME/Pictures"
|
||||
XDG_VIDEOS_DIR="$HOME/Videos"
|
||||
'';
|
||||
in {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
xdg-utils
|
||||
(writeShellScriptBin "xdg-terminal-exec" ''${pkgs.alacritty}/bin/alacritty'')
|
||||
];
|
||||
|
||||
xdg = {
|
||||
mime = {
|
||||
enable = true;
|
||||
defaultApplications = associations;
|
||||
};
|
||||
configFile."user-dirs.dirs".source = userDirsConfig;
|
||||
configFile."mimeapps.list".text = ''
|
||||
[Default Applications]
|
||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k}=${lib.concatStringsSep ";" v}") associations)}
|
||||
[Added Associations]
|
||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k}=${lib.concatStringsSep ";" v}") associations)}
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
configFile = "yazi/yazi.toml";
|
||||
toTOML = (pkgs.formats.toml {}).generate;
|
||||
in {
|
||||
users.users.someone.packages = [pkgs.yazi];
|
||||
xdg.configFile."${configFile}".source = toTOML "yazi.toml" {
|
||||
mgr = {
|
||||
layout = [1 4 3];
|
||||
sort_by = "alphabetical";
|
||||
sort_sensitive = true;
|
||||
sort_reverse = false;
|
||||
sort_dir_first = true;
|
||||
linemode = "none";
|
||||
show_hidden = false;
|
||||
show_symlink = true;
|
||||
};
|
||||
preview = {
|
||||
tab_size = 2;
|
||||
max_width = 600;
|
||||
max_height = 900;
|
||||
cache_dir = "${config.xdg.cacheHome}";
|
||||
};
|
||||
flavor = {
|
||||
dark = "noctalia";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
{pkgs, ...}: let
|
||||
configFile = "yazi/theme.toml";
|
||||
toTOML = (pkgs.formats.toml {}).generate;
|
||||
in {
|
||||
users.users.someone.packages = [pkgs.yazi];
|
||||
xdg.configFile."${configFile}".source = toTOML "theme.toml" {
|
||||
icons = {
|
||||
"*" = "";
|
||||
"*.7z" = "";
|
||||
"*.HEIC" = "";
|
||||
"*.aac" = "";
|
||||
"*.avi" = "";
|
||||
"*.avif" = "";
|
||||
"*.bin" = "";
|
||||
"*.bmp" = "";
|
||||
"*.bz2" = "";
|
||||
"*.c" = "";
|
||||
"*.conf" = "";
|
||||
"*.cpp" = "";
|
||||
"*.css" = "";
|
||||
"*.csv" = "";
|
||||
"*.doc" = "";
|
||||
"*.doct" = "";
|
||||
"*.docx" = "";
|
||||
"*.dot" = "";
|
||||
"*.exe" = "";
|
||||
"*.fish" = "";
|
||||
"*.flac" = "";
|
||||
"*.gif" = "";
|
||||
"*.go" = "";
|
||||
"*.gz" = "";
|
||||
"*.h" = "";
|
||||
"*.hpp" = "";
|
||||
"*.hs" = "";
|
||||
"*.html" = "";
|
||||
"*.ico" = "";
|
||||
"*.ini" = "";
|
||||
"*.java" = "";
|
||||
"*.jpeg" = "";
|
||||
"*.jpg" = "";
|
||||
"*.js" = "";
|
||||
"*.json" = "";
|
||||
"*.jsx" = "";
|
||||
"*.lock" = "";
|
||||
"*.lua" = "";
|
||||
"*.m4a" = "";
|
||||
"*.md" = "";
|
||||
"*.mkv" = "";
|
||||
"*.mov" = "";
|
||||
"*.mp2" = "";
|
||||
"*.mp3" = "";
|
||||
"*.mp4" = "";
|
||||
"*.nix" = "";
|
||||
"*.ods" = "";
|
||||
"*.ogg" = "";
|
||||
"*.ots" = "";
|
||||
"*.pdf" = "";
|
||||
"*.php" = "";
|
||||
"*.pkg" = "";
|
||||
"*.png" = "";
|
||||
"*.pom" = "";
|
||||
"*.pot" = "";
|
||||
"*.potx" = "";
|
||||
"*.ppm" = "";
|
||||
"*.ppmx" = "";
|
||||
"*.pps" = "";
|
||||
"*.ppsx" = "";
|
||||
"*.ppt" = "";
|
||||
"*.pptx" = "";
|
||||
"*.py" = "";
|
||||
"*.rb" = "";
|
||||
"*.rs" = "";
|
||||
"*.rst" = "";
|
||||
"*.sass" = "";
|
||||
"*.scss" = "";
|
||||
"*.sh" = "";
|
||||
"*.svg" = "";
|
||||
"*.swift" = "";
|
||||
"*.tar" = "";
|
||||
"*.toml" = "";
|
||||
"*.ts" = "";
|
||||
"*.tsx" = "";
|
||||
"*.txt" = "";
|
||||
"*.vim" = "";
|
||||
"*.wav" = "";
|
||||
"*.webm" = "";
|
||||
"*.webp" = "";
|
||||
"*.xcf" = "";
|
||||
"*.xlc" = "";
|
||||
"*.xlm" = "";
|
||||
"*.xls" = "";
|
||||
"*.xlsm" = "";
|
||||
"*.xlsx" = "";
|
||||
"*.xlt" = "";
|
||||
"*.xz" = "";
|
||||
"*.yaml" = "";
|
||||
"*.yml" = "";
|
||||
"*.zip" = "";
|
||||
"*/" = "";
|
||||
".DS_Store" = "";
|
||||
".bashprofile" = "";
|
||||
".bashrc" = "";
|
||||
".config/" = "";
|
||||
".git/" = "";
|
||||
".gitattributes" = "";
|
||||
".gitignore" = "";
|
||||
".gitmodules" = "";
|
||||
".ssh/" = "";
|
||||
".vimrc" = "";
|
||||
".zprofile" = "";
|
||||
".zshenv" = "";
|
||||
".zshrc" = "";
|
||||
COPYING = "";
|
||||
Containerfile = "";
|
||||
"Desktop/" = "";
|
||||
"Development/" = "";
|
||||
Dockerfile = "";
|
||||
"Documents/" = "";
|
||||
"Downloads/" = "";
|
||||
LICENSE = "";
|
||||
"Library/" = "";
|
||||
"Movies/" = "";
|
||||
"Music/" = "";
|
||||
"Pictures/" = "";
|
||||
"Public/" = "";
|
||||
"Videos/" = "";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{pkgs, ...}: {
|
||||
users.users.someone.packages = with pkgs; [
|
||||
zoxide
|
||||
];
|
||||
|
||||
xdg.configFile."fish/conf.d/zoxide.fish".source = pkgs.runCommand "zoxide-fish-init" {} ''
|
||||
${pkgs.zoxide}/bin/zoxide init fish > $out
|
||||
'';
|
||||
}
|
||||
Reference in New Issue
Block a user