refactor: reorganize, add package (opencode, osgrep, beads), add ai agent shell
This commit is contained in:
parent
7e0a207778
commit
a0f0f39399
58 changed files with 7867 additions and 42 deletions
16
AGENTS.md
16
AGENTS.md
|
|
@ -1,19 +1,31 @@
|
|||
# Repository Guidelines
|
||||
|
||||
## Project Structure & Module Organization
|
||||
Shared logic lives in `flake.nix`, with inputs pinned in `flake.lock`. Platform modules sit under `modules/darwin/` and `modules/nixos/`; Linux hosts compose `modules/nixos/system.nix` plus `users.nix`, `network.nix`, `ssh.nix`, and `containerization.nix`. Host-specific overlays like `modules/nixos/hosts/dev-vm.nix` supply virtualization packages, while macOS tweaks belong in `modules/darwin/hosts/`. Home Manager layers for `rsydn` are under `modules/home/rsydn/` with `programs/`, `shell/`, and `devtools/`. Secrets stay encrypted in `secrets/*.sops.yaml` and surface at runtime in `~/.config/secrets/`.
|
||||
|
||||
Shared logic lives in `flake.nix`, with inputs pinned in `flake.lock`. Platform modules sit under `modules/darwin/` and `modules/nixos/`; Linux hosts compose `modules/nixos/system.nix` plus `users.nix`, `network.nix`, `ssh.nix`, and `containerization.nix`. Host-specific configs live at root level in `hosts/` (e.g. `hosts/dev-vm.nix`, `hosts/desktop.nix`). Home Manager layers are under `modules/home/` with `programs/`, `shell/`, and `devtools/`. Secrets stay encrypted in `secrets/*.sops.yaml` and surface at runtime in `~/.config/secrets/`.
|
||||
|
||||
Custom packages live in `packages/` and are exported via `packages/default.nix`. Each package has its own derivation file (e.g. `packages/osgrep.nix`). Packages are exported in the flake's `packages` output and can be built individually with `nix build .#osgrep`. The `checks` output ensures all packages build during `nix flake check`. To reference the current system in package definitions, use `pkgs.stdenv.hostPlatform.system` instead of the deprecated `pkgs.system`. Development shells in `shells/` receive custom packages through the `customPkgs` argument.
|
||||
|
||||
## Build, Test, and Development Commands
|
||||
|
||||
Use `nix develop` to enter the project shell with `git`, `nixfmt-classic`, and SOPS ready. Run `nix fmt` before committing to format all Nix sources. `XDG_CACHE_HOME=$PWD/.cache nix flake check` validates every host without polluting the global cache. For macOS changes, run `darwin-rebuild --dry-run --flake .#macbook-pro` and follow with `darwin-rebuild switch --flake .#macbook-pro`. Validate the Linux VM closure via `nix build .#nixosConfigurations.dev-vm.config.system.build.toplevel`.
|
||||
|
||||
## AI Agent Workflow with Beads
|
||||
|
||||
Beads provides persistent memory for AI coding agents through git-backed issue tracking. Enter the AI agent shell with `nix develop .#ai-agent` to access Beads (`bd`) and helper tools. Initialize in any git repository with `bd-init` (Nushell) or `bd init`. Create tasks via `bd create --title "Task name" --type feature --priority high`, track dependencies with `--blocks <id>` or `--parent <id>`, and query ready work using `bd-ready` or `bd ready --json`. The `.beads/issues.jsonl` file must be committed to git to preserve context across sessions. Claude Code can directly use `bd` commands via the Bash tool to maintain work continuity between conversations. Sync the SQLite cache after git operations with `bd-sync` or `bd sync`.
|
||||
|
||||
## Coding Style & Naming Conventions
|
||||
Indent with two spaces and keep trailing commas in attribute sets. Prefer lower-kebab filenames (e.g. `shell/nushell.nix`), and expose custom options under the `rsydn.*` namespace. Format Nix with `nix fmt`; avoid ad-hoc host tweaks when a shared module fits.
|
||||
|
||||
Indent with two spaces and keep trailing commas in attribute sets. Prefer lower-kebab filenames (e.g. `package/nushell.nix`), and expose custom options under the `rsydn.*` namespace. Format Nix with `nix fmt`; avoid ad-hoc host tweaks when a shared module fits.
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
Treat `nix flake check` as the minimum gate; capture its output for reviews. When adjusting host builds, keep dry-run transcripts (`darwin-rebuild --dry-run`, `nix build .#nixosConfigurations.dev-vm…`) to share in PRs. Co-locate regression tests next to their modules using the `<option-name>.nix` pattern.
|
||||
|
||||
## Commit & Pull Request Guidelines
|
||||
|
||||
Write imperative commit subjects such as `add dev-vm virtualization module`, and keep each commit narrowly scoped. PRs should list validation commands run, link related issues or TODOs, and attach screenshots or terminal snippets when touching prompts, Tailscale, or SSH flows.
|
||||
|
||||
## Security & Configuration Tips
|
||||
|
||||
Age keys live at `~/.config/sops/age/keys.txt`; regenerate via Home Manager if missing. Access secrets with `open ~/.config/secrets/<name> | str trim` and scope them using `with-env`. Audit `services.tailscale.extraUpFlags` before enabling exit nodes, and rotate SSH/Tailscale keys regularly.
|
||||
|
|
|
|||
59
flake.lock
generated
59
flake.lock
generated
|
|
@ -1,12 +1,33 @@
|
|||
{
|
||||
"nodes": {
|
||||
"beads": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1765103675,
|
||||
"narHash": "sha256-PCsU2GwrPYFAE2KTCdk60E6ZTPRtgNdbPF+bzf8qi3Q=",
|
||||
"owner": "steveyegge",
|
||||
"repo": "beads",
|
||||
"rev": "08d8353619777dfdd4119477ca029689597cec60",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "steveyegge",
|
||||
"repo": "beads",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"blueprint": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nix-ai-tools",
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": "systems_2"
|
||||
"systems": "systems_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1763308703,
|
||||
|
|
@ -131,10 +152,28 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"ghostty": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
|
|
@ -325,6 +364,7 @@
|
|||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"beads": "beads",
|
||||
"chaotic": "chaotic",
|
||||
"darwin": "darwin",
|
||||
"ghostty": "ghostty",
|
||||
|
|
@ -406,6 +446,21 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_3": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
|
|
|||
49
flake.nix
49
flake.nix
|
|
@ -22,10 +22,13 @@
|
|||
|
||||
try.url = "github:tobi/try";
|
||||
try.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
beads.url = "github:steveyegge/beads";
|
||||
beads.inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, darwin, home-manager, ghostty, nix-ai-tools
|
||||
, sops-nix, chaotic, try, ... }:
|
||||
, sops-nix, chaotic, try, beads, ... }:
|
||||
let
|
||||
inherit (nixpkgs.lib) genAttrs;
|
||||
lib = nixpkgs.lib;
|
||||
|
|
@ -53,7 +56,9 @@
|
|||
|
||||
mkDarwin = { system ? "aarch64-darwin", extraModules ? [ ]
|
||||
, homeFile ? ./modules/darwin/home/default.nix, }:
|
||||
let pkgs = mkPkgs system;
|
||||
let
|
||||
pkgs = mkPkgs system;
|
||||
customPkgs = import ./packages { inherit pkgs lib beads; };
|
||||
in darwin.lib.darwinSystem {
|
||||
inherit system pkgs;
|
||||
specialArgs = { inherit inputs overlaysList user; };
|
||||
|
|
@ -66,14 +71,18 @@
|
|||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
home-manager.backupFileExtension = "backup";
|
||||
home-manager.extraSpecialArgs = { inherit inputs user try; };
|
||||
home-manager.extraSpecialArgs = {
|
||||
inherit inputs user try customPkgs;
|
||||
};
|
||||
home-manager.users.${user} = import homeFile;
|
||||
}
|
||||
];
|
||||
};
|
||||
mkNixos = { system ? "x86_64-linux", extraModules ? [ ]
|
||||
, homeFile ? ./modules/nixos/home/default.nix, }:
|
||||
let pkgs = mkPkgs system;
|
||||
let
|
||||
pkgs = mkPkgs system;
|
||||
customPkgs = import ./packages { inherit pkgs lib beads; };
|
||||
in lib.nixosSystem {
|
||||
inherit system pkgs;
|
||||
specialArgs = { inherit inputs overlaysList user; };
|
||||
|
|
@ -85,7 +94,9 @@
|
|||
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
home-manager.extraSpecialArgs = { inherit inputs user try; };
|
||||
home-manager.extraSpecialArgs = {
|
||||
inherit inputs user try customPkgs;
|
||||
};
|
||||
home-manager.users.${user} = import homeFile;
|
||||
}
|
||||
];
|
||||
|
|
@ -95,12 +106,12 @@
|
|||
nixosConfigurations = {
|
||||
dev-vm = mkNixos {
|
||||
system = "x86_64-linux";
|
||||
extraModules = [ ./modules/nixos/hosts/dev-vm.nix ];
|
||||
extraModules = [ ./hosts/dev-vm.nix ];
|
||||
# Uses default homeFile: ./modules/nixos/home/default.nix
|
||||
};
|
||||
desktop = mkNixos {
|
||||
system = "x86_64-linux";
|
||||
extraModules = [ ./modules/nixos/hosts/desktop.nix ];
|
||||
extraModules = [ ./hosts/desktop.nix ];
|
||||
# Home Manager configs are imported directly in desktop modules
|
||||
# No homeFile needed - using inline home-manager.users.${user}
|
||||
homeFile = ./modules/nixos/home/default.nix;
|
||||
|
|
@ -115,11 +126,14 @@
|
|||
else
|
||||
pkgs.python3;
|
||||
|
||||
# Common arguments passed to all devshell imports
|
||||
shellArgs = { inherit pkgs lib python; };
|
||||
# Custom packages (osgrep, beads, etc.)
|
||||
customPkgs = import ./packages { inherit pkgs lib beads; };
|
||||
|
||||
# Import all devshells from devshells/ directory
|
||||
importShell = name: import (./devshells + "/${name}.nix") shellArgs;
|
||||
# Common arguments passed to all devshell imports
|
||||
shellArgs = { inherit pkgs lib python customPkgs; };
|
||||
|
||||
# Import all shells from shells/ directory
|
||||
importShell = name: import (./shells + "/${name}.nix") shellArgs;
|
||||
|
||||
in {
|
||||
default = importShell "default";
|
||||
|
|
@ -129,10 +143,21 @@
|
|||
go = importShell "go";
|
||||
web-bun = importShell "web-bun";
|
||||
rust = importShell "rust";
|
||||
ai-agent = importShell "ai-agent";
|
||||
});
|
||||
|
||||
formatter = forEachSystem (system: (mkPkgs system).nixfmt-classic);
|
||||
|
||||
packages = forEachSystem (system: { inherit (mkPkgs system) git; });
|
||||
packages = forEachSystem (system:
|
||||
let
|
||||
pkgs = mkPkgs system;
|
||||
customPkgs = import ./packages { inherit pkgs lib beads; };
|
||||
in customPkgs // { inherit (pkgs) git; });
|
||||
|
||||
checks = forEachSystem (system:
|
||||
let
|
||||
pkgs = mkPkgs system;
|
||||
customPkgs = import ./packages { inherit pkgs lib beads; };
|
||||
in { inherit (customPkgs) osgrep opencode beads; });
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{ lib, pkgs, ... }:
|
||||
let
|
||||
hardwareConfigPath = builtins.toString ./.
|
||||
+ "/../desktops/hardware-configuration.nix";
|
||||
+ "/../modules/nixos/desktops/hardware-configuration.nix";
|
||||
hardwareModule = if builtins.pathExists hardwareConfigPath then
|
||||
import hardwareConfigPath
|
||||
else
|
||||
|
|
@ -16,21 +16,21 @@ in {
|
|||
hardwareModule
|
||||
|
||||
# Audio & Graphics
|
||||
../audio.nix
|
||||
../graphics.nix
|
||||
../modules/nixos/audio.nix
|
||||
../modules/nixos/graphics.nix
|
||||
|
||||
# Desktop Environments
|
||||
../desktops/plasma.nix # KDE Plasma (for gaming)
|
||||
../desktops/hyprland # Hyprland (for development)
|
||||
../modules/nixos/desktops/plasma.nix # KDE Plasma (for gaming)
|
||||
../modules/nixos/desktops/hyprland # Hyprland (for development)
|
||||
|
||||
# Desktop Apps & Theme
|
||||
../desktops/apps/browsers.nix
|
||||
../desktops/apps/terminals.nix
|
||||
../desktops/themes/catppuccin.nix # Or use themes/default.nix for Adwaita
|
||||
../modules/nixos/desktops/apps/browsers.nix
|
||||
../modules/nixos/desktops/apps/terminals.nix
|
||||
../modules/nixos/desktops/themes/catppuccin.nix # Or use themes/default.nix for Adwaita
|
||||
|
||||
# Gaming & Features
|
||||
../desktops/gaming.nix
|
||||
../bluetooth.nix
|
||||
../modules/nixos/desktops/gaming.nix
|
||||
../modules/nixos/bluetooth.nix
|
||||
];
|
||||
|
||||
# Boot configuration with CachyOS LTS kernel
|
||||
|
|
@ -47,5 +47,5 @@
|
|||
interfaces."tailscale0".allowedTCPPorts = [ 22 ];
|
||||
};
|
||||
|
||||
imports = [ ../virtualization.nix ];
|
||||
imports = [ ../modules/nixos/virtualization.nix ];
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
{ config, pkgs, lib, ... }: {
|
||||
# Import shared cross-platform home configuration
|
||||
imports = [
|
||||
../../home/rsydn/base.nix
|
||||
../../home/rsydn/shell/nushell.nix
|
||||
../../home/base.nix
|
||||
../../home/shell/nushell.nix
|
||||
./programs/aerospace
|
||||
./programs/ghostty.nix
|
||||
];
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
./devtools/languages.nix
|
||||
./devtools/default.nix
|
||||
./devtools/try.nix
|
||||
./devtools/opencode.nix
|
||||
./secrets.nix
|
||||
];
|
||||
|
||||
|
|
@ -34,6 +35,13 @@
|
|||
path = "~/src/tries";
|
||||
};
|
||||
|
||||
rsydn.opencode = {
|
||||
enable = lib.mkDefault true;
|
||||
theme = "catppuccin";
|
||||
model = "anthropic/claude-sonnet-4-5";
|
||||
smallModel = "anthropic/claude-haiku-3-5";
|
||||
};
|
||||
|
||||
rsydn.devTools = {
|
||||
enable = lib.mkDefault true;
|
||||
packages = with pkgs; [
|
||||
|
|
@ -10,8 +10,6 @@ let
|
|||
|
||||
crushDefault = getPkgsPackage "crush";
|
||||
|
||||
opencodeDefault = getPkgsPackage "opencode";
|
||||
|
||||
claudeDefault = getPkgsPackage "claude-code";
|
||||
|
||||
toolOption = { name, description, defaultPackage, extraOptions ? { }
|
||||
|
|
@ -61,10 +59,6 @@ let
|
|||
name = "crush";
|
||||
cfg = cfg.crush;
|
||||
}
|
||||
{
|
||||
name = "opencode";
|
||||
cfg = cfg.opencode;
|
||||
}
|
||||
{
|
||||
name = "claude";
|
||||
cfg = cfg.claude;
|
||||
|
|
@ -121,11 +115,7 @@ in {
|
|||
defaultPackage = crushDefault;
|
||||
};
|
||||
|
||||
opencode = toolOption {
|
||||
name = "OpenCode";
|
||||
description = "OpenCode AI collaborative CLI packaged in nixpkgs.";
|
||||
defaultPackage = opencodeDefault;
|
||||
};
|
||||
# Note: OpenCode is now managed by its own module at ./opencode.nix
|
||||
|
||||
claude = toolOption {
|
||||
name = "Claude Code";
|
||||
107
modules/home/devtools/opencode.nix
Normal file
107
modules/home/devtools/opencode.nix
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
{ config, lib, pkgs, customPkgs, ... }:
|
||||
let
|
||||
inherit (lib) mkEnableOption mkOption types mkIf;
|
||||
cfg = config.rsydn.opencode;
|
||||
|
||||
# Build the config JSON, filtering out null/empty values
|
||||
opencodeConfig = lib.filterAttrs (_: v: v != null && v != { }) {
|
||||
"$schema" = "https://opencode.ai/config.json";
|
||||
theme = cfg.theme;
|
||||
model = cfg.model;
|
||||
small_model = cfg.smallModel;
|
||||
autoupdate = false; # Nix manages updates
|
||||
mcp = if cfg.mcpServers != { } then cfg.mcpServers else null;
|
||||
keybinds = if cfg.keybinds != { } then cfg.keybinds else null;
|
||||
};
|
||||
in {
|
||||
options.rsydn.opencode = {
|
||||
enable = mkEnableOption "OpenCode CLI with managed configuration";
|
||||
|
||||
package = mkOption {
|
||||
type = types.nullOr types.package;
|
||||
default = customPkgs.opencode;
|
||||
description = ''
|
||||
OpenCode package to use. Defaults to the custom-built package
|
||||
from packages/opencode.nix via customPkgs.
|
||||
'';
|
||||
};
|
||||
|
||||
theme = mkOption {
|
||||
type = types.str;
|
||||
default = "catppuccin";
|
||||
description = "UI theme for OpenCode TUI";
|
||||
};
|
||||
|
||||
model = mkOption {
|
||||
type = types.str;
|
||||
default = "anthropic/claude-sonnet-4-5";
|
||||
description = "Primary LLM model identifier";
|
||||
};
|
||||
|
||||
smallModel = mkOption {
|
||||
type = types.str;
|
||||
default = "anthropic/claude-haiku-3-5";
|
||||
description = "Lightweight model for tasks like title generation";
|
||||
};
|
||||
|
||||
mcpServers = mkOption {
|
||||
type = types.attrs;
|
||||
default = { };
|
||||
example = {
|
||||
nixos = {
|
||||
type = "stdio";
|
||||
command = "uvx";
|
||||
args = [ "mcp-nixos" ];
|
||||
};
|
||||
};
|
||||
description = "MCP server configurations";
|
||||
};
|
||||
|
||||
keybinds = mkOption {
|
||||
type = types.attrs;
|
||||
default = { };
|
||||
description = "Custom keybinding overrides";
|
||||
};
|
||||
|
||||
# Future extension points (joelhooks-style)
|
||||
agents = mkOption {
|
||||
type = types.attrsOf types.path;
|
||||
default = { };
|
||||
description = ''
|
||||
Custom agent markdown files.
|
||||
Keys become filenames under ~/.config/opencode/agent/
|
||||
'';
|
||||
};
|
||||
|
||||
commands = mkOption {
|
||||
type = types.attrsOf types.path;
|
||||
default = { };
|
||||
description = ''
|
||||
Custom command markdown files.
|
||||
Keys become filenames under ~/.config/opencode/command/
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.attrs;
|
||||
default = { };
|
||||
description = "Additional config options to merge into opencode.json";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
home.packages = lib.optional (cfg.package != null) cfg.package;
|
||||
|
||||
xdg.configFile = {
|
||||
# Global config file
|
||||
"opencode/opencode.json".text =
|
||||
builtins.toJSON (opencodeConfig // cfg.extraConfig);
|
||||
} // lib.mapAttrs' (name: path:
|
||||
# Agent markdown files
|
||||
lib.nameValuePair "opencode/agent/${name}.md" { source = path; })
|
||||
cfg.agents // lib.mapAttrs' (name: path:
|
||||
# Command markdown files
|
||||
lib.nameValuePair "opencode/command/${name}.md" { source = path; })
|
||||
cfg.commands;
|
||||
};
|
||||
}
|
||||
74
modules/home/programs/nvim/lazy-lock.json
Normal file
74
modules/home/programs/nvim/lazy-lock.json
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"bufferline.nvim": {
|
||||
"branch": "main",
|
||||
"commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3"
|
||||
},
|
||||
"catppuccin": {
|
||||
"branch": "main",
|
||||
"commit": "8c4125e3c746976ba025dc5d908fa22c6aa09486"
|
||||
},
|
||||
"gruvbox.nvim": {
|
||||
"branch": "main",
|
||||
"commit": "5e0a460d8e0f7f669c158dedd5f9ae2bcac31437"
|
||||
},
|
||||
"indent-blankline.nvim": {
|
||||
"branch": "master",
|
||||
"commit": "005b56001b2cb30bfa61b7986bc50657816ba4ba"
|
||||
},
|
||||
"lazy.nvim": {
|
||||
"branch": "main",
|
||||
"commit": "ed4dc336a73c18da6fea6e1cf7ad6e1b76d281eb"
|
||||
},
|
||||
"lazydev.nvim": {
|
||||
"branch": "main",
|
||||
"commit": "12532f81ef8aa35dd4a44713ea32e760d643675c"
|
||||
},
|
||||
"lualine.nvim": {
|
||||
"branch": "master",
|
||||
"commit": "3946f0122255bc377d14a59b27b609fb3ab25768"
|
||||
},
|
||||
"mini.ai": {
|
||||
"branch": "main",
|
||||
"commit": "11c57180bc9084089206e211ac7aa598bedc9673"
|
||||
},
|
||||
"mini.bufremove": {
|
||||
"branch": "main",
|
||||
"commit": "1b5d7e7bc81cd02476bdd964c3d850c48eb91a07"
|
||||
},
|
||||
"mini.pairs": {
|
||||
"branch": "main",
|
||||
"commit": "b9aada8c0e59f2b938e98fbf4eae0799eba96ad9"
|
||||
},
|
||||
"noice.nvim": {
|
||||
"branch": "main",
|
||||
"commit": "d14d02cb709e3bb2da88363c32f8b4250bced52d"
|
||||
},
|
||||
"nui.nvim": {
|
||||
"branch": "main",
|
||||
"commit": "de740991c12411b663994b2860f1a4fd0937c130"
|
||||
},
|
||||
"nvim-lint": {
|
||||
"branch": "master",
|
||||
"commit": "9da1fb942dd0668d5182f9c8dee801b9c190e2bb"
|
||||
},
|
||||
"nvim-lspconfig": {
|
||||
"branch": "master",
|
||||
"commit": "2b52bc2190c8efde2e4de02d829a138666774c7c"
|
||||
},
|
||||
"nvim-treesitter": {
|
||||
"branch": "master",
|
||||
"commit": "42fc28ba918343ebfd5565147a42a26580579482"
|
||||
},
|
||||
"nvim-web-devicons": {
|
||||
"branch": "master",
|
||||
"commit": "8dcb311b0c92d460fac00eac706abd43d94d68af"
|
||||
},
|
||||
"tokyonight.nvim": {
|
||||
"branch": "main",
|
||||
"commit": "4fe1b0c44f5d6ee769cdfbdffc7ccb703f53feda"
|
||||
},
|
||||
"ts-comments.nvim": {
|
||||
"branch": "main",
|
||||
"commit": "217ab9cc137fceb6659b53790bd25e608219abe1"
|
||||
}
|
||||
}
|
||||
|
|
@ -67,6 +67,71 @@ in {
|
|||
|
||||
print $"(ansi green_bold)✓ Core QA checks passed!(ansi reset)"
|
||||
}
|
||||
|
||||
# Beads helper functions for AI agent workflows
|
||||
# Safe Beads initialization with git repository check
|
||||
def bd-init [] {
|
||||
if not (".git" | path exists) and not (".git" | path type) == "dir" {
|
||||
print $"(ansi red_bold)Error: Not in a git repository(ansi reset)"
|
||||
print "Beads requires a git repository. Initialize git first:"
|
||||
print " git init"
|
||||
return
|
||||
}
|
||||
|
||||
if (".beads" | path exists) {
|
||||
print $"(ansi yellow)Beads already initialized in this project(ansi reset)"
|
||||
return
|
||||
}
|
||||
|
||||
print $"(ansi green)Initializing Beads...(ansi reset)"
|
||||
bd init
|
||||
if $env.LAST_EXIT_CODE == 0 {
|
||||
print $"(ansi green_bold)✓ Beads initialized successfully(ansi reset)"
|
||||
print ""
|
||||
print "Next steps:"
|
||||
print " bd create --title \"Your task\" --type feature"
|
||||
print " bd ready"
|
||||
}
|
||||
}
|
||||
|
||||
# View ready tasks with structured output
|
||||
def bd-ready [] {
|
||||
if not (".beads" | path exists) {
|
||||
print $"(ansi red)Not a Beads project. Run 'bd-init' first.(ansi reset)"
|
||||
return
|
||||
}
|
||||
|
||||
let ready_tasks = (bd ready --json | from json)
|
||||
|
||||
if ($ready_tasks | is-empty) {
|
||||
print $"(ansi yellow)No ready tasks(ansi reset)"
|
||||
return
|
||||
}
|
||||
|
||||
print $"(ansi green_bold)Ready Tasks:(ansi reset)\n"
|
||||
$ready_tasks | each {|task|
|
||||
print $"(ansi cyan)[$($task.id)](ansi reset) ($task.title)"
|
||||
print $" Type: ($task.type) | Priority: ($task.priority) | Status: ($task.status)"
|
||||
if ($task.description? != null) and ($task.description | str length) > 0 {
|
||||
print $" ($task.description)"
|
||||
}
|
||||
print ""
|
||||
} | ignore
|
||||
}
|
||||
|
||||
# Sync Beads database with git
|
||||
def bd-sync [] {
|
||||
if not (".beads" | path exists) {
|
||||
print $"(ansi red)Not a Beads project(ansi reset)"
|
||||
return
|
||||
}
|
||||
|
||||
print $"(ansi blue)Syncing Beads database...(ansi reset)"
|
||||
bd sync
|
||||
if $env.LAST_EXIT_CODE == 0 {
|
||||
print $"(ansi green)✓ Sync complete(ansi reset)"
|
||||
}
|
||||
}
|
||||
'';
|
||||
|
||||
programs.nushell.envFile.text = ''
|
||||
|
|
@ -4,9 +4,9 @@
|
|||
# Desktop configs are handled directly in nixos/desktops/* modules
|
||||
|
||||
imports = [
|
||||
../../home/rsydn/base.nix # Base CLI tools (git, tmux, etc.)
|
||||
../../home/rsydn/shell/fish.nix # Shell configuration
|
||||
../../home/rsydn/shell/nushell.nix # Secondary Nushell setup
|
||||
../../home/base.nix # Base CLI tools (git, tmux, etc.)
|
||||
../../home/shell/fish.nix # Shell configuration
|
||||
../../home/shell/nushell.nix # Secondary Nushell setup
|
||||
];
|
||||
|
||||
config.programs.tmux.extraConfig = lib.mkAfter ''
|
||||
|
|
|
|||
8
packages/default.nix
Normal file
8
packages/default.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{ pkgs, lib, beads }:
|
||||
|
||||
{
|
||||
osgrep = pkgs.callPackage ./osgrep.nix { };
|
||||
opencode = pkgs.callPackage ./opencode.nix { };
|
||||
# Re-export beads from flake input for consistent access
|
||||
beads = beads.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||
}
|
||||
59
packages/opencode.nix
Normal file
59
packages/opencode.nix
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{ lib, stdenv, fetchzip, autoPatchelfHook }:
|
||||
let
|
||||
version = "1.0.137";
|
||||
|
||||
platformInfo = {
|
||||
x86_64-darwin = {
|
||||
name = "darwin-x64";
|
||||
ext = "zip";
|
||||
hash = "sha256-ZgzvpW8SAN0HP3Qh+aT1S+WrEoXkTZiL8/8z1w9p9Y0=";
|
||||
};
|
||||
aarch64-darwin = {
|
||||
name = "darwin-arm64";
|
||||
ext = "zip";
|
||||
hash = "sha256-w5hs5arVroLtjr9pRAHYXQL+4L5gw1bJVL4DhgvrpLs=";
|
||||
};
|
||||
x86_64-linux = {
|
||||
name = "linux-x64";
|
||||
ext = "tar.gz";
|
||||
hash = "sha256-N8IR3xq/dGF5jPq9/UW8Mu/PnAUb7r+Ox6nge6wKw1M=";
|
||||
};
|
||||
aarch64-linux = {
|
||||
name = "linux-arm64";
|
||||
ext = "tar.gz";
|
||||
hash = "sha256-LwWbTAVnfEmCjUBNf58bgFFVVvDIQVJkLsGtYX+/EfU=";
|
||||
};
|
||||
};
|
||||
|
||||
platform = platformInfo.${stdenv.hostPlatform.system} or (throw
|
||||
"Unsupported system: ${stdenv.hostPlatform.system}");
|
||||
in stdenv.mkDerivation {
|
||||
pname = "opencode";
|
||||
inherit version;
|
||||
|
||||
src = fetchzip {
|
||||
url =
|
||||
"https://github.com/sst/opencode/releases/download/v${version}/opencode-${platform.name}.${platform.ext}";
|
||||
hash = platform.hash;
|
||||
stripRoot = false;
|
||||
};
|
||||
|
||||
nativeBuildInputs = lib.optionals stdenv.isLinux [ autoPatchelfHook ];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/bin
|
||||
cp opencode $out/bin/opencode
|
||||
chmod +x $out/bin/opencode
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "AI coding assistant CLI from SST";
|
||||
homepage = "https://opencode.ai";
|
||||
license = lib.licenses.mit;
|
||||
mainProgram = "opencode";
|
||||
platforms =
|
||||
[ "x86_64-darwin" "aarch64-darwin" "x86_64-linux" "aarch64-linux" ];
|
||||
};
|
||||
}
|
||||
7292
packages/osgrep-package-lock.json
generated
Normal file
7292
packages/osgrep-package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
32
packages/osgrep.nix
Normal file
32
packages/osgrep.nix
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{ lib, buildNpmPackage, fetchurl, python3 }:
|
||||
|
||||
buildNpmPackage rec {
|
||||
pname = "osgrep";
|
||||
version = "0.5.16";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://registry.npmjs.org/${pname}/-/${pname}-${version}.tgz";
|
||||
hash = "sha256-V23PNxtMCdRaqr4uDOs0rptmSROUrUO7I9HazoGqUCQ=";
|
||||
};
|
||||
|
||||
sourceRoot = "package";
|
||||
|
||||
postPatch = ''
|
||||
cp ${./osgrep-package-lock.json} package-lock.json
|
||||
'';
|
||||
|
||||
npmDepsHash = "sha256-JDeZ3kcsbcZM//0846i1gsvoAgMpIpN8c160cp7wB5s=";
|
||||
|
||||
npmFlags = [ "--legacy-peer-deps" ];
|
||||
|
||||
dontNpmBuild = true; # Already built in npm package
|
||||
|
||||
nativeBuildInputs = [ python3 ];
|
||||
|
||||
meta = {
|
||||
description = "Semantic grep for AI agents";
|
||||
homepage = "https://github.com/Ryandonofrio3/osgrep";
|
||||
license = lib.licenses.asl20;
|
||||
mainProgram = "osgrep";
|
||||
};
|
||||
}
|
||||
98
shells/ai-agent.nix
Normal file
98
shells/ai-agent.nix
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
{ pkgs, lib, customPkgs, ... }:
|
||||
|
||||
let
|
||||
# Get Beads package from custom packages
|
||||
beadsPkg = customPkgs.beads;
|
||||
|
||||
# Helper script to show Beads project status
|
||||
beadsStatus = pkgs.writeShellScriptBin "beads-status" ''
|
||||
if [ ! -d ".beads" ]; then
|
||||
echo "Not a Beads project (no .beads directory found)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Beads Project Status ==="
|
||||
echo ""
|
||||
echo "Ready tasks:"
|
||||
${beadsPkg}/bin/bd ready --json | ${pkgs.jq}/bin/jq -r '.[] | " - [\(.id)] \(.title) (\(.type))"'
|
||||
echo ""
|
||||
echo "In Progress:"
|
||||
${beadsPkg}/bin/bd list --status in-progress --json | ${pkgs.jq}/bin/jq -r '.[] | " - [\(.id)] \(.title)"'
|
||||
echo ""
|
||||
echo "For full details, run: bd list --json | jq"
|
||||
'';
|
||||
|
||||
# Helper script to generate full project context for AI agents
|
||||
beadsContext = pkgs.writeShellScriptBin "beads-context" ''
|
||||
if [ ! -d ".beads" ]; then
|
||||
echo "Not a Beads project (no .beads directory found)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Beads Project Context ==="
|
||||
echo ""
|
||||
echo "All issues:"
|
||||
${beadsPkg}/bin/bd list --json | ${pkgs.jq}/bin/jq '.'
|
||||
echo ""
|
||||
echo "Dependency tree (first ready task):"
|
||||
ready_id=$(${beadsPkg}/bin/bd ready --json | ${pkgs.jq}/bin/jq -r '.[0].id // empty')
|
||||
if [ -n "$ready_id" ]; then
|
||||
${beadsPkg}/bin/bd dep tree "$ready_id"
|
||||
else
|
||||
echo "No ready tasks"
|
||||
fi
|
||||
'';
|
||||
|
||||
in pkgs.mkShell {
|
||||
name = "ai-agent";
|
||||
|
||||
packages = with pkgs; [
|
||||
# Custom packages
|
||||
customPkgs.beads
|
||||
customPkgs.osgrep
|
||||
|
||||
# Version control
|
||||
git
|
||||
jujutsu
|
||||
|
||||
# Code search and navigation
|
||||
ripgrep
|
||||
ast-grep
|
||||
fzf
|
||||
|
||||
# JSON processing
|
||||
jq
|
||||
|
||||
# Helper scripts
|
||||
beadsStatus
|
||||
beadsContext
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
# Add home-manager binaries to PATH (claude-code, codex, etc.)
|
||||
if [ -d "$HOME/.nix-profile/bin" ]; then
|
||||
export PATH="$HOME/.nix-profile/bin:$PATH"
|
||||
fi
|
||||
|
||||
echo "AI Agent development shell loaded"
|
||||
echo ""
|
||||
echo "Available tools:"
|
||||
echo " bd - Beads CLI (issue tracker)"
|
||||
echo " beads-status - Show project status summary"
|
||||
echo " beads-context - Generate full context for AI"
|
||||
echo " osgrep - Semantic code search"
|
||||
echo " jj/git - Version control"
|
||||
echo " rg/ast-grep - Code search"
|
||||
echo ""
|
||||
echo "Quick start:"
|
||||
echo " bd init - Initialize Beads in current project"
|
||||
echo " bd create - Create new issue"
|
||||
echo " bd ready - Show ready tasks"
|
||||
echo " bd --help - Full command reference"
|
||||
echo ""
|
||||
echo "Nushell helpers (if in nushell):"
|
||||
echo " bd-init - Safe init with git checks"
|
||||
echo " bd-ready - View ready tasks (structured)"
|
||||
echo " bd-sync - Sync database with git"
|
||||
'';
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue