Compare commits

..

13 Commits

Author SHA1 Message Date
09cbb308d2 up
Signed-off-by: Christoph Schmatzler <christoph@schmatzler.com>
2026-02-09 17:31:21 +00:00
c120b3d4d2 opencode: add Cog memory skill 2026-02-09 17:28:35 +00:00
3381945cea opencode: add Cog MCP server 2026-02-09 17:18:36 +00:00
d12aabdccc opencode: disable oh-my-opencode commit footer and co-author 2026-02-09 17:16:58 +00:00
d38a348a06 add openusage
Signed-off-by: Christoph Schmatzler <christoph@schmatzler.com>
2026-02-09 17:15:10 +00:00
42873f4d2d opencode: add oh-my-opencode config, remove custom oracle agent 2026-02-09 15:00:24 +00:00
c1bb006292 Remove mindy host and orphaned derek secret 2026-02-09 09:26:34 +00:00
9bdaaeb295 flake
Signed-off-by: Christoph Schmatzler <christoph@schmatzler.com>
2026-02-09 09:17:45 +00:00
6596ec2d9b opencode: add oracle research tools, spec-planner question tool, deny mcp-auth read 2026-02-08 17:46:29 +00:00
0103aa8c16 Remove watchman package and file watcher config 2026-02-08 08:45:17 +00:00
37b13cfd6a flake
Signed-off-by: Christoph Schmatzler <christoph@schmatzler.com>
2026-02-08 08:41:54 +00:00
29d27dccfb nushell: Remove deprecated use_ls_colors config option 2026-02-08 08:39:13 +00:00
cca27aa971 Replace fish with nushell 2026-02-08 08:37:09 +00:00
28 changed files with 900 additions and 251 deletions

View File

@@ -1,7 +1,6 @@
keys: keys:
- &host_tahani age1njjegjjdqzfnrr54f536yl4lduqgna3wuv7ef6vtl9jw5cju0grsgy62tm - &host_tahani age1njjegjjdqzfnrr54f536yl4lduqgna3wuv7ef6vtl9jw5cju0grsgy62tm
- &host_michael age187jl7e4k9n4guygkmpuqzeh0wenefwrfkpvuyhvwjrjwxqpzassqq3x67j - &host_michael age187jl7e4k9n4guygkmpuqzeh0wenefwrfkpvuyhvwjrjwxqpzassqq3x67j
- &host_mindy age1dqt3znmzcgghsjjzzax0pf0eyu95h0p7kaf5v988ysjv7fl7lumsatl048
- &host_jason age1ez6j3r5wdp0tjy7n5qzv5vfakdc2nh2zeu388zu7a80l0thv052syxq5e2 - &host_jason age1ez6j3r5wdp0tjy7n5qzv5vfakdc2nh2zeu388zu7a80l0thv052syxq5e2
- &host_chidi age1tlymdmaukhwupzrhszspp26lgd8s64rw4vu9lwc7gsgrjm78095s9fe9l3 - &host_chidi age1tlymdmaukhwupzrhszspp26lgd8s64rw4vu9lwc7gsgrjm78095s9fe9l3
creation_rules: creation_rules:
@@ -10,6 +9,5 @@ creation_rules:
- age: - age:
- *host_tahani - *host_tahani
- *host_michael - *host_michael
- *host_mindy
- *host_jason - *host_jason
- *host_chidi - *host_chidi

View File

@@ -5,7 +5,7 @@
### Local Development ### Local Development
```bash ```bash
nix run .#build # Build current host config nix run .#build # Build current host config
nix run .#build -- <hostname> # Build specific host (chidi, jason, michael, mindy, tahani) nix run .#build -- <hostname> # Build specific host (chidi, jason, michael, tahani)
nix run .#apply # Build and apply locally (darwin-rebuild/nixos-rebuild switch) nix run .#apply # Build and apply locally (darwin-rebuild/nixos-rebuild switch)
nix flake check # Validate flake nix flake check # Validate flake
``` ```
@@ -13,7 +13,7 @@ nix flake check # Validate flake
### Remote Deployment (NixOS only) ### Remote Deployment (NixOS only)
```bash ```bash
colmena build # Build all NixOS hosts colmena build # Build all NixOS hosts
colmena apply --on <host> # Deploy to specific NixOS host (michael, mindy, tahani) colmena apply --on <host> # Deploy to specific NixOS host (michael, tahani)
colmena apply # Deploy to all NixOS hosts colmena apply # Deploy to all NixOS hosts
``` ```

78
flake.lock generated
View File

@@ -254,11 +254,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1770318660, "lastModified": 1770586272,
"narHash": "sha256-yFVde8QZK7Dc0Xa8eQDsmxLX4NJNfL1NKfctSyiQgMY=", "narHash": "sha256-Ucci8mu8QfxwzyfER2DQDbvW9t1BnTUJhBmY7ybralo=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "471e6a065f9efed51488d7c51a9abbd387df91b8", "rev": "b1f916ba052341edc1f80d4b2399f1092a4873ca",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -270,11 +270,11 @@
"homebrew-cask": { "homebrew-cask": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1770393771, "lastModified": 1770623639,
"narHash": "sha256-yNaIsOtVX83L83O/2BHS9WVpAqZ7IzDs2yZhEb4umyg=", "narHash": "sha256-LNLzbnhp5IEizTMMapF2FtLVD21sFzBfVgXcwNz7fKU=",
"owner": "homebrew", "owner": "homebrew",
"repo": "homebrew-cask", "repo": "homebrew-cask",
"rev": "c16ebafbe5cb55c51e9b0ec46ed3f11b73d93604", "rev": "c3bb7aedf0881187cbeb55ad2873240feba21603",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -286,11 +286,11 @@
"homebrew-core": { "homebrew-core": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1770391396, "lastModified": 1770627860,
"narHash": "sha256-WH8DSpgT0P93MdblM7z9qS2U9VhG0j99VZ/wberbmT8=", "narHash": "sha256-ihOndNFECGtZhkrtynP8nDJ8fbSxhNd2zWcq3CLDnQA=",
"owner": "homebrew", "owner": "homebrew",
"repo": "homebrew-core", "repo": "homebrew-core",
"rev": "de9367dc2858d3add0dd79be5ca79ad62f8186e0", "rev": "a12e59e6d202fc64aee013f8574c043a4c00a271",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -306,11 +306,11 @@
"treefmt-nix": "treefmt-nix" "treefmt-nix": "treefmt-nix"
}, },
"locked": { "locked": {
"lastModified": 1770388146, "lastModified": 1770616720,
"narHash": "sha256-tjCUAiXibkgKMJxiTXak+VwYbWyxY2at7hRCPykrTbc=", "narHash": "sha256-NY7yFg3ZG0fzseC4SK/TQjgaODczuvCDtJZNsBmN2QU=",
"owner": "numtide", "owner": "numtide",
"repo": "llm-agents.nix", "repo": "llm-agents.nix",
"rev": "2c5791cc2667f20fe75fa6a5ea9335c23bea538d", "rev": "09019dadd541051fc11f5008b56f4e8a14d2df4c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -382,11 +382,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1770169770, "lastModified": 1770537093,
"narHash": "sha256-awR8qIwJxJJiOmcEGgP2KUqYmHG4v/z8XpL9z8FnT1A=", "narHash": "sha256-pF1quXG5wsgtyuPOHcLfYg/ft/QMr8NnX0i6tW2187s=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "aa290c9891fa4ebe88f8889e59633d20cc06a5f2", "rev": "fef9403a3e4d31b0a23f0bacebbec52c248fbb51",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -413,11 +413,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1770393649, "lastModified": 1770627848,
"narHash": "sha256-agO684FuNJrJSm0EOxlCotu2AnKO0JKU8nu2Z3QfplQ=", "narHash": "sha256-pWVT4wjh+HKIdvGhph0vU1Kh48OSaSutPGpXxGNxSxw=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "a123db84a6aff9e37716dc856ad09cfe885a0ce4", "rev": "fe776c9fe2c37f51546bb50ced285ea2a365e7d9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -429,11 +429,11 @@
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1770169770, "lastModified": 1770380644,
"narHash": "sha256-awR8qIwJxJJiOmcEGgP2KUqYmHG4v/z8XpL9z8FnT1A=", "narHash": "sha256-P7dWMHRUWG5m4G+06jDyThXO7kwSk46C1kgjEWcybkE=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "aa290c9891fa4ebe88f8889e59633d20cc06a5f2", "rev": "ae67888ff7ef9dff69b3cf0cc0fbfbcd3a722abe",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -466,11 +466,11 @@
"systems": "systems_3" "systems": "systems_3"
}, },
"locked": { "locked": {
"lastModified": 1770388595, "lastModified": 1770627083,
"narHash": "sha256-0NvpmDqFcJAtRFJE3RDZWnN7PDJBZutoDtN+Cl8a3DY=", "narHash": "sha256-Js8WrUwQ3lLRjWb8jGGE5npRN96E4mtPwyuNDuCDkcg=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nixvim", "repo": "nixvim",
"rev": "51abc532525e486176f9a7b24b17908c60017b54", "rev": "d354487c4692de3d0918170c45bde05175b12e30",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -482,11 +482,11 @@
"nono": { "nono": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1770230267, "lastModified": 1770553882,
"narHash": "sha256-EUSXFyhPBkffuukLvr4Q3LythNds2ca5wJotW0APSY8=", "narHash": "sha256-yEXw+rtuhoZvx1eO2Q+qPeGpvVbyASh7D9YEVAteoo8=",
"owner": "lukehinds", "owner": "lukehinds",
"repo": "nono", "repo": "nono",
"rev": "42df275918579adeb3243a9f9e085f052e19199c", "rev": "e80983bb6a4058335e96e02eeabe17314f771a9c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -495,6 +495,23 @@
"type": "github" "type": "github"
} }
}, },
"openusage": {
"flake": false,
"locked": {
"lastModified": 1770543295,
"narHash": "sha256-DvgEPZhFm06igalUPgnQ8VLkl0gk/3rm+lbEJ2/s7gM=",
"owner": "robinebers",
"repo": "openusage",
"rev": "22a7bd5f7856397400e60dd787ad82b23c763969",
"type": "github"
},
"original": {
"owner": "robinebers",
"ref": "v0.5.1",
"repo": "openusage",
"type": "github"
}
},
"overseer": { "overseer": {
"flake": false, "flake": false,
"locked": { "locked": {
@@ -526,6 +543,7 @@
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs_2",
"nixvim": "nixvim", "nixvim": "nixvim",
"nono": "nono", "nono": "nono",
"openusage": "openusage",
"overseer": "overseer", "overseer": "overseer",
"sops-nix": "sops-nix", "sops-nix": "sops-nix",
"zjstatus": "zjstatus" "zjstatus": "zjstatus"
@@ -576,11 +594,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1770145881, "lastModified": 1770526836,
"narHash": "sha256-ktjWTq+D5MTXQcL9N6cDZXUf9kX8JBLLBLT0ZyOTSYY=", "narHash": "sha256-xbvX5Ik+0inJcLJtJ/AajAt7xCk6FOCrm5ogpwwvVDg=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "17eea6f3816ba6568b8c81db8a4e6ca438b30b7c", "rev": "d6e0e666048a5395d6ea4283143b7c9ac704720d",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -48,6 +48,10 @@
url = "github:dmmulroy/overseer"; url = "github:dmmulroy/overseer";
flake = false; flake = false;
}; };
openusage = {
url = "github:robinebers/openusage/v0.5.1";
flake = false;
};
}; };
outputs = inputs @ {flake-parts, ...}: outputs = inputs @ {flake-parts, ...}:

View File

@@ -25,8 +25,7 @@
../../profiles/bash.nix ../../profiles/bash.nix
../../profiles/bat.nix ../../profiles/bat.nix
../../profiles/direnv.nix ../../profiles/direnv.nix
../../profiles/eza.nix ../../profiles/nushell.nix
../../profiles/fish.nix
../../profiles/fzf.nix ../../profiles/fzf.nix
../../profiles/ghostty.nix ../../profiles/ghostty.nix
../../profiles/git.nix ../../profiles/git.nix

View File

@@ -24,8 +24,7 @@
../../profiles/bash.nix ../../profiles/bash.nix
../../profiles/bat.nix ../../profiles/bat.nix
../../profiles/direnv.nix ../../profiles/direnv.nix
../../profiles/eza.nix ../../profiles/nushell.nix
../../profiles/fish.nix
../../profiles/fzf.nix ../../profiles/fzf.nix
../../profiles/ghostty.nix ../../profiles/ghostty.nix
../../profiles/git.nix ../../profiles/git.nix

View File

@@ -39,7 +39,7 @@
home-manager.users.${user} = { home-manager.users.${user} = {
imports = [ imports = [
../../profiles/fish.nix ../../profiles/nushell.nix
../../profiles/home.nix ../../profiles/home.nix
../../profiles/ssh.nix ../../profiles/ssh.nix
inputs.nixvim.homeModules.nixvim inputs.nixvim.homeModules.nixvim

View File

@@ -26,8 +26,7 @@
../../profiles/bash.nix ../../profiles/bash.nix
../../profiles/bat.nix ../../profiles/bat.nix
../../profiles/direnv.nix ../../profiles/direnv.nix
../../profiles/eza.nix ../../profiles/nushell.nix
../../profiles/fish.nix
../../profiles/fzf.nix ../../profiles/fzf.nix
../../profiles/git.nix ../../profiles/git.nix
../../profiles/home.nix ../../profiles/home.nix

132
overlays/openusage.nix Normal file
View File

@@ -0,0 +1,132 @@
{inputs}: final: prev: let
version = "0.5.1";
in {
openusage =
prev.rustPlatform.buildRustPackage (finalAttrs: {
pname = "openusage";
inherit version;
src = inputs.openusage;
cargoRoot = "src-tauri";
cargoLock = {
lockFile = "${inputs.openusage}/src-tauri/Cargo.lock";
outputHashes = {
"tauri-nspanel-2.1.0" = "sha256-PLACEHOLDER";
"tauri-plugin-aptabase-1.0.0" = "sha256-PLACEHOLDER";
};
};
buildAndTestSubdir = finalAttrs.cargoRoot;
node_modules =
prev.stdenv.mkDerivation {
inherit (finalAttrs) src version;
pname = "${finalAttrs.pname}-node_modules";
impureEnvVars =
prev.lib.fetchers.proxyImpureEnvVars
++ [
"GIT_PROXY_COMMAND"
"SOCKS_SERVER"
];
nativeBuildInputs = [
prev.bun
prev.writableTmpDirAsHomeHook
];
dontConfigure = true;
dontFixup = true;
dontPatchShebangs = true;
buildPhase = ''
runHook preBuild
export BUN_INSTALL_CACHE_DIR=$(mktemp -d)
bun install \
--no-progress \
--frozen-lockfile \
--ignore-scripts
runHook postBuild
'';
installPhase = ''
runHook preInstall
cp -R ./node_modules $out
runHook postInstall
'';
outputHash = "sha256-PLACEHOLDER";
outputHashMode = "recursive";
};
nativeBuildInputs = [
prev.cargo-tauri.hook
prev.rustPlatform.bindgenHook
prev.bun
prev.nodejs
prev.pkg-config
prev.makeBinaryWrapper
];
buildInputs =
prev.lib.optionals prev.stdenv.isDarwin (
with prev.darwin.apple_sdk.frameworks; [
AppKit
CoreFoundation
CoreServices
Security
WebKit
]
);
# Disable updater artifact generation — we don't have signing keys.
tauriConf = builtins.toJSON {bundle.createUpdaterArtifacts = false;};
passAsFile = ["tauriConf"];
preBuild = ''
tauriBuildFlags+=(
"--config"
"$tauriConfPath"
)
'';
configurePhase = ''
runHook preConfigure
# Copy pre-fetched node_modules
cp -R ${finalAttrs.node_modules} node_modules/
chmod -R u+rw node_modules
chmod -R u+x node_modules/.bin
patchShebangs node_modules
export HOME=$TMPDIR
export PATH="$PWD/node_modules/.bin:$PATH"
# Bundle plugins (copy from plugins/ to src-tauri/resources/bundled_plugins/)
${prev.nodejs}/bin/node copy-bundled.cjs
runHook postConfigure
'';
env = {
OPENSSL_NO_VENDOR = true;
};
doCheck = false;
postInstall =
prev.lib.optionalString prev.stdenv.isDarwin ''
makeWrapper $out/Applications/OpenUsage.app/Contents/MacOS/OpenUsage $out/bin/openusage
'';
meta = {
description = "Track all your AI coding subscriptions in one place";
homepage = "https://github.com/robinebers/openusage";
license = prev.lib.licenses.mit;
platforms = prev.lib.platforms.darwin;
mainProgram = "openusage";
};
});
}

View File

@@ -1,7 +1,7 @@
{ {
programs.atuin = { programs.atuin = {
enable = true; enable = true;
enableFishIntegration = true; enableNushellIntegration = true;
flags = [ flags = [
"--disable-up-arrow" "--disable-up-arrow"
]; ];

View File

@@ -1,5 +1,6 @@
{pkgs, ...}: { {pkgs, ...}: {
programs.fish.enable = true; programs.fish.enable = true;
environment.shells = [pkgs.nushell];
nixpkgs = { nixpkgs = {
config = { config = {

View File

@@ -118,7 +118,7 @@
name = user; name = user;
home = "/Users/${user}"; home = "/Users/${user}";
isHidden = false; isHidden = false;
shell = pkgs.fish; shell = pkgs.nushell;
}; };
home-manager.useGlobalPkgs = true; home-manager.useGlobalPkgs = true;

View File

@@ -1,6 +0,0 @@
{
programs.eza = {
enable = true;
enableFishIntegration = true;
};
}

View File

@@ -1,54 +0,0 @@
{
programs.fish = {
enable = true;
functions = {
open_project = ''
set -l base "$HOME/Projects"
set -l choice (fd -t d -d 1 -a . "$base/Personal" "$base/Work" \
| string replace -r -- "^$base/" "" \
| fzf --prompt "project > ")
test -n "$choice"; and cd "$base/$choice"
'';
};
interactiveShellInit = ''
set fish_greeting
set fish_color_normal 4c4f69
set fish_color_command 1e66f5
set fish_color_param dd7878
set fish_color_keyword d20f39
set fish_color_quote 40a02b
set fish_color_redirection ea76cb
set fish_color_end fe640b
set fish_color_comment 8c8fa1
set fish_color_error d20f39
set fish_color_gray 9ca0b0
set fish_color_selection --background=ccd0da
set fish_color_search_match --background=ccd0da
set fish_color_option 40a02b
set fish_color_operator ea76cb
set fish_color_escape e64553
set fish_color_autosuggestion 9ca0b0
set fish_color_cancel d20f39
set fish_color_cwd df8e1d
set fish_color_user 179299
set fish_color_host 1e66f5
set fish_color_host_remote 40a02b
set fish_color_status d20f39
set fish_pager_color_progress 9ca0b0
set fish_pager_color_prefix ea76cb
set fish_pager_color_completion 4c4f69
set fish_pager_color_description 9ca0b0
set -gx LS_COLORS "$(vivid generate catppuccin-latte)"
set -gx COLORTERM truecolor
set -gx COLORFGBG "15;0"
set -gx TERM_BACKGROUND light
for mode in default insert
bind --mode $mode \cp open_project
end
'';
};
}

View File

@@ -1,7 +1,6 @@
{ {
programs.fzf = { programs.fzf = {
enable = true; enable = true;
enableFishIntegration = true;
}; };
home.sessionVariables = { home.sessionVariables = {

View File

@@ -1,6 +1,6 @@
{pkgs, ...}: { {pkgs, ...}: {
xdg.configFile."ghostty/config".text = '' xdg.configFile."ghostty/config".text = ''
command = ${pkgs.fish}/bin/fish command = ${pkgs.nushell}/bin/nu
theme = Catppuccin Latte theme = Catppuccin Latte
window-padding-x = 12 window-padding-x = 12
window-padding-y = 3 window-padding-y = 3
@@ -10,7 +10,7 @@
cursor-style = block cursor-style = block
mouse-hide-while-typing = true mouse-hide-while-typing = true
mouse-scroll-multiplier = 1.25 mouse-scroll-multiplier = 1.25
shell-integration = fish shell-integration = none
shell-integration-features = no-cursor shell-integration-features = no-cursor
clipboard-read = allow clipboard-read = allow
clipboard-write = allow clipboard-write = allow

View File

@@ -95,15 +95,10 @@ in {
gf = "git fetch"; gf = "git fetch";
gfa = "git fetch --all --tags --prune"; gfa = "git fetch --all --tags --prune";
gfo = "git fetch origin"; gfo = "git fetch origin";
gfg = "git ls-files | grep";
gg = "git gui citool"; gg = "git gui citool";
gga = "git gui citool --amend"; gga = "git gui citool --amend";
ggpull = "git pull origin \"$(git branch --show-current)\"";
ggpush = "git push origin \"$(git branch --show-current)\"";
ggsup = "git branch --set-upstream-to=origin/$(git branch --show-current)";
ghh = "git help"; ghh = "git help";
gignore = "git update-index --assume-unchanged"; gignore = "git update-index --assume-unchanged";
gignored = "git ls-files -v | grep \"^[[:lower:]]\"";
gl = "git pull"; gl = "git pull";
glg = "git log --stat"; glg = "git log --stat";
glgp = "git log --stat --patch"; glgp = "git log --stat --patch";
@@ -118,7 +113,6 @@ in {
glols = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset\" --stat"; glols = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset\" --stat";
glod = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset\""; glod = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset\"";
glods = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset\" --date=short"; glods = "git log --graph --pretty=\"%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset\" --date=short";
gluc = "git pull upstream $(git branch --show-current)";
glum = "git pull upstream main"; glum = "git pull upstream main";
gm = "git merge"; gm = "git merge";
gma = "git merge --abort"; gma = "git merge --abort";
@@ -133,7 +127,6 @@ in {
gpd = "git push --dry-run"; gpd = "git push --dry-run";
gpf = "git push --force-with-lease"; gpf = "git push --force-with-lease";
gpod = "git push origin --delete"; gpod = "git push origin --delete";
gpoat = "git push origin --all && git push origin --tags";
gpr = "git pull --rebase"; gpr = "git pull --rebase";
gpra = "git pull --rebase --autostash"; gpra = "git pull --rebase --autostash";
gprav = "git pull --rebase --autostash -v"; gprav = "git pull --rebase --autostash -v";
@@ -142,8 +135,6 @@ in {
gprv = "git pull --rebase -v"; gprv = "git pull --rebase -v";
gprum = "git pull --rebase upstream main"; gprum = "git pull --rebase upstream main";
gprumi = "git pull --rebase=interactive upstream main"; gprumi = "git pull --rebase=interactive upstream main";
gpsup = "git push --set-upstream origin $(git branch --show-current)";
gpsupf = "git push --set-upstream origin $(git branch --show-current) --force-with-lease";
gpv = "git push --verbose"; gpv = "git push --verbose";
gpu = "git push upstream"; gpu = "git push upstream";
gr = "git remote"; gr = "git remote";
@@ -169,13 +160,11 @@ in {
grm = "git rm"; grm = "git rm";
grmc = "git rm --cached"; grmc = "git rm --cached";
grmv = "git remote rename"; grmv = "git remote rename";
groh = "git reset origin/$(git branch --show-current) --hard";
grrm = "git remote remove"; grrm = "git remote remove";
grs = "git restore"; grs = "git restore";
grset = "git remote set-url"; grset = "git remote set-url";
grss = "git restore --source"; grss = "git restore --source";
grst = "git restore --staged"; grst = "git restore --staged";
grt = "cd \"$(git rev-parse --show-toplevel || echo .)\"";
gru = "git reset --"; gru = "git reset --";
grup = "git remote update"; grup = "git remote update";
grv = "git remote --verbose"; grv = "git remote --verbose";
@@ -201,16 +190,43 @@ in {
gswm = "git switch main"; gswm = "git switch main";
gta = "git tag --annotate"; gta = "git tag --annotate";
gts = "git tag --sign"; gts = "git tag --sign";
gtv = "git tag | sort -V";
gunignore = "git update-index --no-assume-unchanged"; gunignore = "git update-index --no-assume-unchanged";
gunwip = "git rev-list --max-count=1 --format=\"%s\" HEAD | grep -q \"\\--wip--\" && git reset HEAD~1";
gwch = "git whatchanged -p --abbrev-commit --pretty=medium"; gwch = "git whatchanged -p --abbrev-commit --pretty=medium";
gwipe = "git reset --hard && git clean --force -df";
gwt = "git worktree"; gwt = "git worktree";
gwta = "git worktree add"; gwta = "git worktree add";
gwtls = "git worktree list"; gwtls = "git worktree list";
gwtmv = "git worktree move"; gwtmv = "git worktree move";
gwtrm = "git worktree remove"; gwtrm = "git worktree remove";
gwip = "git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message \"--wip-- [skip ci]\"";
}; };
# Complex git aliases that require pipes/subshells — nushell `alias` can't
# handle these, so they're defined as custom commands instead.
programs.nushell.extraConfig = ''
def ggpull [] { git pull origin (git branch --show-current | str trim) }
def ggpush [] { git push origin (git branch --show-current | str trim) }
def ggsup [] { git branch $"--set-upstream-to=origin/(git branch --show-current | str trim)" }
def gluc [] { git pull upstream (git branch --show-current | str trim) }
def gpsup [] { git push --set-upstream origin (git branch --show-current | str trim) }
def gpsupf [] { git push --set-upstream origin (git branch --show-current | str trim) --force-with-lease }
def groh [] { git reset $"origin/(git branch --show-current | str trim)" --hard }
def --env grt [] {
let toplevel = (do { git rev-parse --show-toplevel } | complete | get stdout | str trim)
if ($toplevel | is-not-empty) { cd $toplevel } else { cd . }
}
def gfg [...pattern: string] { git ls-files | lines | where {|f| $f =~ ($pattern | str join ".*") } }
def gignored [] { git ls-files -v | lines | where {|l| ($l | str substring 0..1) =~ "[a-z]" } }
def gpoat [] { git push origin --all; git push origin --tags }
def gtv [] { git tag | lines | sort }
def gwipe [] { git reset --hard; git clean --force -df }
def gunwip [] {
let msg = (git rev-list --max-count=1 --format="%s" HEAD | lines | get 1)
if ($msg | str contains "--wip--") { git reset HEAD~1 }
}
def gwip [] {
git add -A
let deleted = (git ls-files --deleted | lines)
if ($deleted | is-not-empty) { git rm ...$deleted }
git commit --no-verify --no-gpg-sign --message "--wip-- [skip ci]"
}
'';
} }

View File

@@ -1,7 +1,7 @@
{ {
programs.mise = { programs.mise = {
enable = true; enable = true;
enableFishIntegration = true; enableNushellIntegration = true;
globalConfig.settings = { globalConfig.settings = {
auto_install = false; auto_install = false;
}; };

View File

@@ -66,7 +66,7 @@
"network" "network"
"systemd-journal" "systemd-journal"
]; ];
shell = pkgs.fish; shell = pkgs.nushell;
openssh.authorizedKeys.keys = constants.sshKeys; openssh.authorizedKeys.keys = constants.sshKeys;
}; };

225
profiles/nushell.nix Normal file
View File

@@ -0,0 +1,225 @@
{pkgs, ...}: {
programs.nushell = {
enable = true;
settings = {
show_banner = false;
completions = {
algorithm = "fuzzy";
case_sensitive = false;
};
history = {
file_format = "sqlite";
};
};
environmentVariables = {
COLORTERM = "truecolor";
COLORFGBG = "15;0";
TERM_BACKGROUND = "light";
};
extraEnv = ''
$env.LS_COLORS = (${pkgs.vivid}/bin/vivid generate catppuccin-latte)
'';
extraConfig = ''
# --- Catppuccin Latte Theme ---
let theme = {
rosewater: "#dc8a78"
flamingo: "#dd7878"
pink: "#ea76cb"
mauve: "#8839ef"
red: "#d20f39"
maroon: "#e64553"
peach: "#fe640b"
yellow: "#df8e1d"
green: "#40a02b"
teal: "#179299"
sky: "#04a5e5"
sapphire: "#209fb5"
blue: "#1e66f5"
lavender: "#7287fd"
text: "#4c4f69"
subtext1: "#5c5f77"
subtext0: "#6c6f85"
overlay2: "#7c7f93"
overlay1: "#8c8fa1"
overlay0: "#9ca0b0"
surface2: "#acb0be"
surface1: "#bcc0cc"
surface0: "#ccd0da"
base: "#eff1f5"
mantle: "#e6e9ef"
crust: "#dce0e8"
}
let scheme = {
recognized_command: $theme.blue
unrecognized_command: $theme.text
constant: $theme.peach
punctuation: $theme.overlay2
operator: $theme.sky
string: $theme.green
virtual_text: $theme.surface2
variable: { fg: $theme.flamingo attr: i }
filepath: $theme.yellow
}
$env.config.color_config = {
separator: { fg: $theme.surface2 attr: b }
leading_trailing_space_bg: { fg: $theme.lavender attr: u }
header: { fg: $theme.text attr: b }
row_index: $scheme.virtual_text
record: $theme.text
list: $theme.text
hints: $scheme.virtual_text
search_result: { fg: $theme.base bg: $theme.yellow }
shape_closure: $theme.teal
closure: $theme.teal
shape_flag: { fg: $theme.maroon attr: i }
shape_matching_brackets: { attr: u }
shape_garbage: $theme.red
shape_keyword: $theme.mauve
shape_match_pattern: $theme.green
shape_signature: $theme.teal
shape_table: $scheme.punctuation
cell-path: $scheme.punctuation
shape_list: $scheme.punctuation
shape_record: $scheme.punctuation
shape_vardecl: $scheme.variable
shape_variable: $scheme.variable
empty: { attr: n }
filesize: {||
if $in < 1kb {
$theme.teal
} else if $in < 10kb {
$theme.green
} else if $in < 100kb {
$theme.yellow
} else if $in < 10mb {
$theme.peach
} else if $in < 100mb {
$theme.maroon
} else if $in < 1gb {
$theme.red
} else {
$theme.mauve
}
}
duration: {||
if $in < 1day {
$theme.teal
} else if $in < 1wk {
$theme.green
} else if $in < 4wk {
$theme.yellow
} else if $in < 12wk {
$theme.peach
} else if $in < 24wk {
$theme.maroon
} else if $in < 52wk {
$theme.red
} else {
$theme.mauve
}
}
datetime: {|| (date now) - $in |
if $in < 1day {
$theme.teal
} else if $in < 1wk {
$theme.green
} else if $in < 4wk {
$theme.yellow
} else if $in < 12wk {
$theme.peach
} else if $in < 24wk {
$theme.maroon
} else if $in < 52wk {
$theme.red
} else {
$theme.mauve
}
}
shape_external: $scheme.unrecognized_command
shape_internalcall: $scheme.recognized_command
shape_external_resolved: $scheme.recognized_command
shape_block: $scheme.recognized_command
block: $scheme.recognized_command
shape_custom: $theme.pink
custom: $theme.pink
background: $theme.base
foreground: $theme.text
cursor: { bg: $theme.rosewater fg: $theme.base }
shape_range: $scheme.operator
range: $scheme.operator
shape_pipe: $scheme.operator
shape_operator: $scheme.operator
shape_redirection: $scheme.operator
glob: $scheme.filepath
shape_directory: $scheme.filepath
shape_filepath: $scheme.filepath
shape_glob_interpolation: $scheme.filepath
shape_globpattern: $scheme.filepath
shape_int: $scheme.constant
int: $scheme.constant
bool: $scheme.constant
float: $scheme.constant
nothing: $scheme.constant
binary: $scheme.constant
shape_nothing: $scheme.constant
shape_bool: $scheme.constant
shape_float: $scheme.constant
shape_binary: $scheme.constant
shape_datetime: $scheme.constant
shape_literal: $scheme.constant
string: $scheme.string
shape_string: $scheme.string
shape_string_interpolation: $theme.flamingo
shape_raw_string: $scheme.string
shape_externalarg: $scheme.string
}
$env.config.highlight_resolved_externals = true
$env.config.explore = {
status_bar_background: { fg: $theme.text, bg: $theme.mantle },
command_bar_text: { fg: $theme.text },
highlight: { fg: $theme.base, bg: $theme.yellow },
status: {
error: $theme.red,
warn: $theme.yellow,
info: $theme.blue,
},
selected_cell: { bg: $theme.blue fg: $theme.base },
}
# --- Custom Commands ---
def --env open_project [] {
let base = ($env.HOME | path join "Projects")
let choice = (
${pkgs.fd}/bin/fd -t d -d 1 -a . ($base | path join "Personal") ($base | path join "Work")
| lines
| each {|p| $p | str replace $"($base)/" "" }
| str join "\n"
| ${pkgs.fzf}/bin/fzf --prompt "project > "
)
if ($choice | str trim | is-not-empty) {
cd ($base | path join ($choice | str trim))
}
}
# --- Keybinding: Ctrl+O for open_project ---
$env.config.keybindings = ($env.config.keybindings | append [
{
name: open_project
modifier: control
keycode: char_o
mode: [emacs vi_insert vi_normal]
event: {
send: executehostcommand
cmd: "open_project"
}
}
])
'';
};
}

View File

@@ -8,7 +8,6 @@
OPENCODE_EXPERIMENTAL_LSP_TOOL = 1; OPENCODE_EXPERIMENTAL_LSP_TOOL = 1;
OPENCODE_EXPERIMENTAL_MARKDOWN = 1; OPENCODE_EXPERIMENTAL_MARKDOWN = 1;
OPENCODE_EXPERIMENTAL_PLAN_MODE = 1; OPENCODE_EXPERIMENTAL_PLAN_MODE = 1;
OPENCODE_EXPERIMENTAL_FILE_WATCHER = 1;
}; };
programs.opencode = { programs.opencode = {
@@ -18,7 +17,7 @@
model = "anthropic/claude-opus-4-6"; model = "anthropic/claude-opus-4-6";
small_model = "opencode/minimax-m2.1"; small_model = "opencode/minimax-m2.1";
theme = "catppuccin"; theme = "catppuccin";
plugin = ["opencode-anthropic-auth"]; plugin = ["oh-my-opencode" "opencode-anthropic-auth"];
keybinds = { keybinds = {
leader = "ctrl+o"; leader = "ctrl+o";
}; };
@@ -29,6 +28,7 @@
"*.env.*" = "deny"; "*.env.*" = "deny";
"*.envrc" = "deny"; "*.envrc" = "deny";
"secrets/*" = "deny"; "secrets/*" = "deny";
"~/.local/share/opencode/mcp-auth.json" = "deny";
}; };
}; };
agent = { agent = {
@@ -36,7 +36,7 @@
model = "anthropic/claude-opus-4-6"; model = "anthropic/claude-opus-4-6";
}; };
explore = { explore = {
model = "opencode/minimax-m2.1"; model = "anthropic/claude-haiku-4-5";
}; };
}; };
instructions = [ instructions = [
@@ -50,6 +50,14 @@
}; };
}; };
mcp = { mcp = {
cog = {
enabled = true;
type = "remote";
url = "https://trycog.ai/mcp";
headers = {
Authorization = "Bearer {env:COG_API_TOKEN}";
};
};
context7 = { context7 = {
enabled = true; enabled = true;
type = "remote"; type = "remote";
@@ -66,7 +74,7 @@
command = ["bunx" "opensrc-mcp"]; command = ["bunx" "opensrc-mcp"];
}; };
overseer = { overseer = {
enabled = true; enabled = false;
type = "local"; type = "local";
command = ["${pkgs.overseer}/bin/os" "mcp"]; command = ["${pkgs.overseer}/bin/os" "mcp"];
}; };
@@ -91,5 +99,14 @@
source = ./opencode/tool; source = ./opencode/tool;
recursive = true; recursive = true;
}; };
"opencode/oh-my-opencode.json".text =
builtins.toJSON {
"$schema" = "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json";
disabled_mcps = ["websearch" "context7" "grep_app"];
git_master = {
commit_footer = false;
include_co_authored_by = false;
};
};
}; };
} }

View File

@@ -1,86 +0,0 @@
---
description: Senior engineering advisor for code reviews, architecture decisions, complex debugging, and planning. Invoke when you need deeper analysis before acting — reviews, trade-offs, debugging race conditions, planning refactors. Prompt with precise problem + files. Ask for concrete outcomes.
mode: subagent
model: opencode/gpt-5.2-codex
options:
thinking:
type: enabled
budgetTokens: 31999
permission:
"*": deny
read: allow
grep: allow
glob: allow
webfetch: allow
lsp: allow
---
You are the Oracle - an expert AI advisor with advanced reasoning capabilities.
Your role is to provide high-quality technical guidance, code reviews, architectural advice, and strategic planning for software engineering tasks.
You are a subagent inside an AI coding system, called when the main agent needs a smarter, more capable model. You are invoked in a zero-shot manner - no one can ask you follow-up questions or provide follow-up answers.
## Key Responsibilities
- Analyze code and architecture patterns
- Provide specific, actionable technical recommendations
- Plan implementations and refactoring strategies
- Answer deep technical questions with clear reasoning
- Suggest best practices and improvements
- Identify potential issues and propose solutions
## Operating Principles (Simplicity-First)
1. **Default to simplest viable solution** that meets stated requirements
2. **Prefer minimal, incremental changes** that reuse existing code, patterns, and dependencies
3. **Optimize for maintainability and developer time** over theoretical scalability
4. **Apply YAGNI and KISS** - avoid premature optimization
5. **One primary recommendation** - offer alternatives only if trade-offs are materially different
6. **Calibrate depth to scope** - brief for small tasks, deep only when required
7. **Stop when "good enough"** - note signals that would justify revisiting
## Effort Estimates
Include rough effort signal when proposing changes:
- **S** (<1 hour) - trivial, single-location change
- **M** (1-3 hours) - moderate, few files
- **L** (1-2 days) - significant, cross-cutting
- **XL** (>2 days) - major refactor or new system
## Response Format
Keep responses concise and action-oriented. For straightforward questions, collapse sections as appropriate:
### 1. TL;DR
1-3 sentences with the recommended simple approach.
### 2. Recommendation
Numbered steps or short checklist. Include minimal diffs/snippets only as needed.
### 3. Rationale
Brief justification. Mention why alternatives are unnecessary now.
### 4. Risks & Guardrails
Key caveats and mitigations.
### 5. When to Reconsider
Concrete triggers that justify a more complex design.
### 6. Advanced Path (optional)
Brief outline only if relevant and trade-offs are significant.
## Tool Usage
You have read-only access: read, grep, glob, LSP, webfetch.
Use them freely to verify assumptions and gather context. Your extended thinking enables deep analysis - leverage it fully.
## Guidelines
- Investigate thoroughly; report concisely - focus on highest-leverage insights
- For planning tasks, break down into minimal steps that achieve the goal incrementally
- Justify recommendations briefly - avoid long speculative exploration
- If the request is ambiguous, state your interpretation explicitly before answering
- If unanswerable from available context, say so directly
**IMPORTANT:** Only your last message is returned to the main agent and displayed to the user. Make it comprehensive yet focused, with a clear, simple recommendation that enables immediate action.

View File

@@ -0,0 +1,406 @@
---
name: cog
description: Persistent knowledge graph memory via Cog MCP. Use when recording insights, querying prior knowledge, or managing memory consolidation.
metadata:
author: trycog
version: "1.0.0"
---
# Cog Memory System
Persistent knowledge graph for teams. Concepts (engrams) linked via relationships (synapses). Spreading activation surfaces connected knowledge.
## Core Workflow
```
1. UNDERSTAND task (read files, parse request)
2. QUERY Cog with specific keywords <- MANDATORY, no exceptions
3. WAIT for results
4. EXPLORE/IMPLEMENT guided by Cog knowledge
5. RECORD insights as short-term memories during work
6. CONSOLIDATE memories after work (reinforce valid, flush invalid)
```
**Hierarchy of truth:** Current code > User statements > Cog knowledge
---
## Visual Indicators (MANDATORY)
Print before EVERY Cog tool call:
| Tool | Print |
|------|-------|
| `cog_recall` | `Querying Cog...` |
| `cog_learn` | `Recording to Cog...` |
| `cog_associate` | `Linking concepts...` |
| `cog_update` | `Updating engram...` |
| `cog_trace` | `Tracing connections...` |
| `cog_connections` | `Exploring connections...` |
| `cog_unlink` | `Removing link...` |
| `cog_list_short_term` | `Listing short-term memories...` |
| `cog_reinforce` | `Reinforcing memory...` |
| `cog_flush` | `Flushing invalid memory...` |
| `cog_verify` | `Verifying synapse...` |
| `cog_stale` | `Listing stale synapses...` |
---
## Tools Reference
| Tool | Purpose |
|------|---------|
| `cog_recall` | Search with spreading activation |
| `cog_learn` | Create memory with **chains** (sequential) or associations (hub) |
| `cog_get` | Retrieve engram by ID |
| `cog_associate` | Link two existing concepts |
| `cog_trace` | Find paths between concepts |
| `cog_update` | Modify engram term/definition |
| `cog_unlink` | Remove synapse |
| `cog_connections` | List engram connections |
| `cog_bootstrap` | Exploration prompt for empty brains |
| `cog_list_short_term` | List pending consolidations |
| `cog_reinforce` | Convert short-term to long-term |
| `cog_flush` | Delete invalid short-term memory |
| `cog_verify` | Confirm synapse is still accurate |
| `cog_stale` | List synapses needing verification |
---
## Querying Rules
### Before exploring code, ALWAYS query Cog first
Even for "trivial" tasks. The 2-second query may reveal gotchas, prior solutions, or context that changes your approach.
### Query Reformulation (Critical for Recall)
Before calling `cog_recall`, **transform your query from question-style to definition-style**. You are an LLM -- use that capability to bridge the vocabulary gap between how users ask questions and how knowledge is stored.
#### Think like a definition, not a question
| User Intent | Don't Query | Do Query |
|-------------|-------------|----------|
| "How do I handle stale data?" | `"handle stale data"` | `"cache invalidation event-driven TTL expiration data freshness"` |
| "Why does auth break after a while?" | `"auth breaks"` | `"token expiration refresh timing session timeout JWT lifecycle"` |
| "Where should validation go?" | `"where validation"` | `"input validation system boundaries sanitization defense in depth"` |
#### The reformulation process
1. **Identify the concept** -- What is the user actually asking about?
2. **Generate canonical terms** -- What would an engram about this be titled?
3. **Add related terminology** -- What words would the DEFINITION use?
4. **Include synonyms** -- What other terms describe the same thing?
#### Example transformation
```
User asks: "Why is the payment service sometimes charging twice?"
Your thinking:
- Concept: duplicate charges, idempotency
- Canonical terms: "idempotency", "duplicate prevention", "payment race condition"
- Definition words: "idempotent", "transaction", "mutex", "lock", "retry"
- Synonyms: "double charge", "duplicate transaction"
Query: "payment idempotency duplicate transaction race condition mutex retry"
```
### Query with specific keywords
| Task Type | Understand First | Then Query With |
|-----------|------------------|-----------------|
| Bug fix | Error message, symptoms | `"canonical error name component pattern race condition"` |
| Feature | User's description | `"domain terms design patterns architectural concepts"` |
| Test fix | Read the test file | `"API names assertion patterns test utilities"` |
| Architecture | System area | `"component relationships boundaries dependencies"` |
**Bad:** `"authentication"` (too vague)
**Good:** `"JWT refresh token expiration session lifecycle OAuth flow"` (definition-style)
### Use Cog results
- Follow paths Cog reveals
- Read components Cog mentions first
- Heed gotchas Cog warns about
- If Cog is wrong, correct it immediately with `cog_update`
---
## Recording Rules
### CRITICAL: Chains vs Associations
**Before recording, ask: Is this sequential or hub-shaped?**
| Structure | Use | Example |
|-----------|-----|---------|
| **Sequential** (A -> B -> C) | `chain_to` | Technology enables Pattern enables Feature |
| **Hub** (A, B, C all connect to X) | `associations` | Meeting connects to Participants, Outcomes |
**Default to chains** for:
- Technology dependencies (DB -> ORM -> API)
- Causal sequences (Cause -> Effect -> Consequence)
- Architectural decisions (ADR -> Technology -> Feature)
- Enabling relationships (Infrastructure -> enables -> Capability)
- Reasoning paths (Premise -> implies -> Conclusion)
**Use associations** for:
- Hub/star patterns (one thing connects to many unrelated things)
- Linking to existing concepts in the graph
- Multi-party contexts (meetings, decisions with stakeholders)
### Chain Example (PREFERRED for dependencies)
```
cog_learn({
"term": "PostgreSQL",
"definition": "Relational database with ACID guarantees",
"chain_to": [
{"term": "Ecto ORM", "definition": "Elixir database wrapper with changesets", "predicate": "enables"},
{"term": "Phoenix Contexts", "definition": "Business logic boundaries in Phoenix", "predicate": "enables"}
]
})
```
Creates: PostgreSQL ->[enables]-> Ecto ORM ->[enables]-> Phoenix Contexts
### Association Example (for hubs)
```
cog_learn({
"term": "Auth Review 2024-01-20",
"definition": "Decided JWT with refresh tokens. Rejected session cookies.",
"associations": [
{"target": "JWT Pattern", "predicate": "leads_to"},
{"target": "Session Cookies", "predicate": "contradicts"},
{"target": "Mobile Team", "predicate": "is_component_of"}
]
})
```
Creates hub: JWT Pattern <-[leads_to]<- Auth Review ->[contradicts]-> Session Cookies
---
### When to record (during work)
At these checkpoints, ask: *"What did I just learn that I didn't know 5 minutes ago?"*
| Checkpoint | Record |
|------------|--------|
| After identifying root cause | Why it was broken |
| After reading surprising code | The non-obvious behavior |
| After a failed attempt | Why it didn't work |
| Before implementing fix | The insight (freshest now) |
| After discovering connection | The relationship |
| After a meeting or decision | The context hub linking participants and outcomes |
| After researching/exploring architecture | System limits, configuration points, component boundaries |
**Record immediately.** Don't wait until task end -- you'll forget details.
### Before calling `cog_learn`
1. **Decide: chain or hub?** (see above)
2. **For chains**: Build the sequence of steps with `chain_to`
3. **For hubs**: Identify association targets from source material or Cog query
**Skip the query when:**
- Source material explicitly names related concepts (ADRs, documentation, structured data)
- You already know target terms from conversation context
- The insight references specific concepts by name
**Query first when:**
- Recording an insight and unsure what it relates to
- Source is vague about connections
- Exploring a new domain with unknown existing concepts
### After calling `cog_learn`
The operation is complete. **Do NOT verify your work by:**
- Calling `cog_recall` to check the engram exists
- Calling `cog_connections` to verify associations were created
- Calling `cog_trace` to see if paths formed
Trust the response confirmation. Verification wastes turns and adds no value -- if the operation failed, you'll see an error.
### Recording Efficiency
**One operation = one tool call.** Use `chain_to` for sequences, `associations` for hubs.
**Never** follow `cog_learn` with separate `cog_associate` calls -- put all relationships in the original call.
### Writing good engrams
**Terms (2-5 words):**
- "Session Token Refresh Timing"
- "Why We Chose PostgreSQL"
- NOT "Architecture" (too broad)
- NOT "Project Overview" (super-hub)
**Definitions (1-3 sentences):**
1. What it is
2. Why it matters / consequences
3. Related keywords for search
**Never create super-hubs** -- engrams so generic everything connects to them (e.g., "Overview", "Main System"). They pollute search results.
### Relationship predicates
| Predicate | Meaning | Best for | Use in |
|-----------|---------|----------|--------|
| `enables` | A makes B possible | Tech dependencies | **chain_to** |
| `requires` | A is prerequisite for B | Dependencies | **chain_to** |
| `implies` | If A then B | Logical consequences | **chain_to** |
| `leads_to` | A flows to B | Outcomes, consequences | **chain_to** |
| `precedes` | A comes before B | Sequencing, timelines | **chain_to** |
| `derived_from` | A is based on B | Origins | **chain_to** |
| `contradicts` | A and B mutually exclusive | Rejected alternatives | associations |
| `is_component_of` | A is part of B | Parts to whole | associations |
| `contains` | A includes B | Whole to parts | associations |
| `example_of` | A demonstrates pattern B | Instances of patterns | associations |
| `generalizes` | A is broader than B | Abstract concepts | associations |
| `supersedes` | A replaces B | Deprecations | associations |
| `similar_to` | A and B are closely related | Related approaches | associations |
| `contrasts_with` | A is alternative to B | Different approaches | associations |
| `related_to` | General link (use sparingly) | When nothing else fits | associations |
**Chain predicates** (`enables`, `requires`, `implies`, `leads_to`, `precedes`, `derived_from`) express **flow** -- use them in `chain_to` to build traversable paths.
### Modeling Complex Contexts (Hub Node Pattern)
Synapses are binary (one source, one target). For multi-party relationships, use a **hub engram** connecting all participants.
#### When to use hub nodes
| Scenario | Hub Example | Connected Concepts |
|----------|-------------|-------------------|
| Meeting with outcomes | "Q1 Planning 2024-01" | Participants, decisions |
| Decision with stakeholders | "Decision: Adopt GraphQL" | Pros, cons, voters |
| Feature with components | "User Auth Feature" | OAuth, session, UI |
| Incident with timeline | "2024-01 Payment Outage" | Cause, systems, fix |
---
## Consolidation (MANDATORY)
**Every task must end with consolidation.** Short-term memories decay in 24 hours.
### After work is complete:
```
cog_list_short_term({"limit": 20})
```
For each memory:
- **Valid and useful?** -> `cog_reinforce` (makes permanent)
- **Wrong or not useful?** -> `cog_flush` (deletes)
### When to reinforce immediately
- Insights from code you just wrote (you know it's correct)
- Gotchas you just hit and fixed
- Patterns you just applied successfully
### When to wait for validation
- Hypotheses about why something is broken
- Assumptions about unfamiliar code
- Solutions you haven't tested
---
## Verification (Prevents Staleness)
Synapses decay if not verified as still semantically accurate.
### When to verify
- After using `cog_trace` and confirming paths are correct
- When reviewing `cog_connections` and relationships hold
- After successfully using knowledge from a synapse
### Staleness levels
| Level | Months Unverified | Score | Behavior |
|-------|-------------------|-------|----------|
| Fresh | < 3 | 0.0-0.49 | Normal |
| Warning | 3-6 | 0.5-0.79 | Appears in `cog_stale` |
| Critical | 6+ | 0.8-0.99 | Penalty in path scoring |
| Deprecated | 12+ | 1.0 | Excluded from spreading activation |
### Periodic maintenance
Run `cog_stale({"level": "all"})` periodically to review relationships that may have become outdated. For each stale synapse:
- **Still accurate?** -> `cog_verify` to reset staleness
- **No longer true?** -> `cog_unlink` to remove
---
## Validation & Correction
### Cog is hints, not truth
Always verify against current code. If Cog is wrong:
| Scenario | Action |
|----------|--------|
| Minor inaccuracy | `cog_update` to fix |
| Pattern changed significantly | Unlink old, create new engram |
| Completely obsolete | Update to note "DEPRECATED: [reason]" |
---
## Subagents
Subagents MUST query Cog before exploring. Same rules apply:
1. Understand task
2. **Reformulate query to definition-style**
3. Query Cog with reformulated keywords
4. Wait for results
5. Then explore
---
## Summary Reporting
Only mention Cog when relevant:
| Condition | Include |
|-----------|---------|
| Cog helped | `**Cog helped by:** [specific value]` |
| Memories created | `**Recorded to Cog:** [term names]` |
| Cog not used | Nothing (don't mention Cog) |
| Cog queried but unhelpful | Don't mention the empty query, but **still record** new knowledge you discovered through exploration |
---
## Never Store
- Passwords, API keys, tokens, secrets
- SSH/PGP keys, certificates
- Connection strings with credentials
- PII (emails, SSNs, credit cards)
- `.env` file contents
Server auto-rejects sensitive content.
---
## Limitations
- **No engram deletion** -- use `cog_update` or `cog_unlink`
- **No multi-query** -- chain manually
- **One synapse per direction** -- repeat calls strengthen existing link
---
## Spreading Activation
`cog_recall` returns:
1. **Seeds** -- direct matches
2. **Paths** -- engrams connecting seeds (built from chains!)
3. **Synapses** -- relationships along paths
This surfaces the "connective tissue" between results. **Chains create these traversable paths.**

View File

@@ -38,6 +38,23 @@ Phase: CLARIFY | Waiting for: answers to questions 1-4
3. Ask 3-5 pointed questions that would change the approach. USE YOUR QUESTION TOOL. 3. Ask 3-5 pointed questions that would change the approach. USE YOUR QUESTION TOOL.
4. **Wait for responses** 4. **Wait for responses**
**IMPORTANT: Always use the `question` tool to ask clarifying questions.** Do NOT output questions as freeform text. The question tool provides structured options and better UX. Example:
```
question({
questions: [{
header: "Scope",
question: "Which subsystems need detailed specs?",
options: [
{ label: "VCS layer", description: "jj-lib + gix unified interface" },
{ label: "Review workflow", description: "GitHub PR-style local review" },
{ label: "Event system", description: "pub/sub + persistence" }
],
multiple: true
}]
})
```
| Category | Example | | Category | Example |
|----------|---------| |----------|---------|
| Scope | "Share where? Social media? Direct link? Embed?" | | Scope | "Share where? Social media? Direct link? Embed?" |

View File

@@ -45,7 +45,6 @@ with pkgs;
tree-sitter tree-sitter
unzip unzip
vivid vivid
watchman
zip zip
] ]
++ lib.optionals stdenv.isDarwin [ ++ lib.optionals stdenv.isDarwin [
@@ -53,6 +52,7 @@ with pkgs;
alcove alcove
dockutil dockutil
mas mas
openusage
raycast raycast
tailscale tailscale
xcodes xcodes

View File

@@ -1,7 +1,7 @@
{ {
programs.starship = { programs.starship = {
enable = true; enable = true;
enableFishIntegration = true; enableNushellIntegration = true;
settings = { settings = {
add_newline = true; add_newline = true;
command_timeout = 2000; command_timeout = 2000;

View File

@@ -1,6 +1,6 @@
{ {
programs.zoxide = { programs.zoxide = {
enable = true; enable = true;
enableFishIntegration = true; enableNushellIntegration = true;
}; };
} }

View File

@@ -1,35 +0,0 @@
{
"data": "ENC[AES256_GCM,data:l7jYCSQE0BwYOoIMHgGOmMrWz5s=,iv:4TugFnfmzoeroq6SfRLD36gSSBHGVT6CxQE4Pyp1Ibc=,tag:HOTLlXGab05u+qREtyxAeg==,type:str]",
"sops": {
"age": [
{
"recipient": "age1njjegjjdqzfnrr54f536yl4lduqgna3wuv7ef6vtl9jw5cju0grsgy62tm",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFTmVlZmxIMGFBbE1RYkNN\nbTh1NG5BK1JCTlZ1MzBtSS9NRXRVM3phN3lrCm9qSlpEQjFGZTBsME9ndXhYdHZv\ncW1oek5hU1pjQXhzT0cvTks3VEozdHcKLS0tIG1TUWJKSE1KRVlXMVdydjBhY1ZS\nWXRhNFA2aHZTT2pud0ZXOFpjVldKYjgKYyH7k0BW/sf3vDQLPaZoB2VHoyKmCkWy\nwTolEp4vkuzZld4KPdDW4jYL8kt8Fwa8TNlPKMUOvY0gt82pbJ1MAA==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age187jl7e4k9n4guygkmpuqzeh0wenefwrfkpvuyhvwjrjwxqpzassqq3x67j",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5Y2ZpWlhXUll4WUxheENj\nRjlwK2dJUjBOU1lhV1dKWFhiMlJiQ0Q2Q0VrCnJac0ppdm9URW14TUwrVUdwN2x4\ncUgxSGRTM09ORUk0VXhUcVBxS1Z2a0EKLS0tIGhOSmc2L3FKOXdqdG5Da210aXF4\nZ2h0dW45K2dlZGJQMmxneE1IbXMvWmsKkBfh09E6o2uvNegq5pZgUBWOYjREDDyg\nHEgV7G4cWJBPpBFwS1gLGyRZ0TWrmoXCqF8I22BMG6tq94AGrKqFzg==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1dqt3znmzcgghsjjzzax0pf0eyu95h0p7kaf5v988ysjv7fl7lumsatl048",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCc1B0Ylo5K1poUXpkcFZk\neGJSQmNBVU00RTdLcTNBRUN2N3cySFE0cUdVCjNmZlpGM0VUOWdvbVQ3U1BoRWJ1\na3kwK3JxQ0IrZ0NUaW5sTmZlWmd4MncKLS0tIHozZ29UbTNPZDBjTUl3WlB2YmFs\nS0IrN3lLK2YyM0ROTERtQlppbjVOdWMKtpLveHYL4RfEpCBLt4c4R/NVg1QF+if1\nz26bWNQseIsPtlIk4GImJZhUhbr3sDY81gcl7sd8XGpze7EAVM262g==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1ez6j3r5wdp0tjy7n5qzv5vfakdc2nh2zeu388zu7a80l0thv052syxq5e2",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBySmdCaVRYV2RjOFR4dFVx\nYmd1VlRzQmUwR1RwcTNJdTlxQnFFZXVscnlFCnRVOWQwa3VVUUlHQTF0WHBXb0FL\nMEViVXVDeWJLZnBLdWlUZTZFQVFqYlUKLS0tIHBGdXdPM2tOdzR0Qm5UT2F6dnNF\nTytWcXNYMEJSTU8xOExMK1MwQUNhdk0KVBbrhhwh+Yup+CW3Y+q9RoQ3XFjBfTLb\nzDbCZBhNx9HP7Q8mlndYPkJc3aGfpKxHpaniBLqzDKNKJ5OE4kzY3Q==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1tlymdmaukhwupzrhszspp26lgd8s64rw4vu9lwc7gsgrjm78095s9fe9l3",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtVnl0ckE1REtQbW8ybEtF\nWG1VNkFtMUVlNk04SnIySVFvM2pkV1dTMTNNCkV6R2NzQzM4WXRIdzJrVEo4L2FX\nQ1dmV2YwNHdMMVJUNmZWRktvK2s1dUUKLS0tIE5nUXNack5meUFzcWxhOTNGLzdG\naGlVYURRK2hLK0lNNm4wYTUrdXptLzAKZgN1tY1G3Jso1+CT0LQQ4I49CgdCECpe\n1wRdgaWI8P4ep2S7QO3Vu+MuoyOgVgGJdG/HzsEAAqJ0XMSBWpeFXg==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1h537hhl5qgew5sswjp7xf7d4j4aq0gg9s5flnr8twm2smnqyudhqmum8uy",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3YnVBeGl5akg2b3BidW5m\nMjBnWWxReTFoNTBYVm83ZkhtSHUvTmtNSGxzCk5XcmVJZ0hpRURIT09teHFzOURt\nK25JSFJCNU5mb2k4ZHBTU0Q0emFtYWMKLS0tIEtqMlFNckZmQk15Z0xoT1BrUWgv\nN0VJT1RjOG1ZOVU1UklKTm5TUEhLQmsKP03juyke7ZmLGx+BHE596d18TWVLFuUV\nP1pK0QlwtRL0l/6r7l4hXN9gJ8JU+zO5NTcLtvvHdSL188q3TX//UQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2026-01-07T19:19:41Z",
"mac": "ENC[AES256_GCM,data:SnMD9+jpySE35ylbHInXfsIQ/Nq6FBpunlhgJSOnYCQLE9vGc5Rtkg8cYlqFBz82Ukjk2EJafKcjDgBgTx6+JcYC8idM7yCpqyJaTx9p0nr6+p46ozqrL8lm4qF+yJRK997RjfRStLE2JsLN0SRSBFTDL0yPB6mFc/BncywVVZ0=,iv:fJ0kpgysw8eHbIIrtdyUXwWYvHyOa6kJ1wW+6NvBTxY=,tag:cqyY6qmEa0HF6u61v9VZJw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.11.0"
}
}