Upstream my claude-code config

This commit is contained in:
Sridhar Ratnakumar 2025-11-10 20:15:11 -05:00
parent 9a64b12e32
commit a6f854db32
17 changed files with 25 additions and 519 deletions

View file

@ -1,21 +0,0 @@
# Srid's Claude Code Configuration
## Nix module
- `nix/home-manager-module.nix` - Home-manager module for auto-wiring this directory layout.
### Usage
Import the home-manager module and set `autoWire.dir`:
```nix
{
imports = [ ./claude-code/nix/home-manager-module.nix ];
programs.claude-code = {
enable = true;
autoWire.dir = ./claude-code;
};
}
```

View file

@ -1,54 +0,0 @@
---
name: hack
description: Implement a GitHub issue end-to-end until CI passes
args:
- name: issue_url
description: GitHub issue URL (e.g., https://github.com/user/repo/issues/123)
required: true
- name: plan_mode
description: Whether to run in plan mode (true/false, default false)
required: false
---
This command implements a GitHub issue from start to finish, ensuring all CI checks pass.
**Usage**: `/hack <github-issue-url> [plan_mode]`
**What it does**:
1. Fetches the GitHub issue details using `gh` CLI
2. Analyzes the issue requirements and creates an implementation plan
3. If plan_mode=true, presents plan for approval before implementing
4. Implements the requested feature or fix
5. Creates a commit with proper issue reference
6. Runs `om ci` to validate the implementation
7. Iterates and fixes any CI failures until all checks pass
**Workflow**:
1. Parse the GitHub issue URL to extract repository and issue number
2. Use `gh api` to fetch issue title, description, and labels
3. Create a detailed implementation plan based on issue requirements
4. Implement the solution step by step
5. Commit changes with concise description
6. Run `om ci` and analyze any failures
7. Fix CI issues and re-run until all checks pass
8. Provide final status report
**Prerequisites**:
- GitHub CLI (`gh`) must be authenticated
- Must be in a git repository with a non-mainline branch
- omnix (`om`) must be available for CI checks
- Repository must have CI configured via omnix
**Error handling**:
- Validates GitHub URL format
- Handles GitHub API errors gracefully
- Provides detailed feedback on CI failures
- Supports iterative fixing until CI passes
**Examples**:
```
/hack https://github.com/myorg/myproject/issues/42
/hack https://github.com/myorg/myproject/issues/42 true
```
First example directly implements issue #42. Second example creates a plan first and waits for approval before implementing.

View file

@ -1,65 +0,0 @@
# PR Command
Create and open a draft pull request on GitHub for the current branch.
## Workflow
1. **Gather Information**
- Get the current branch name using `git branch --show-current`
- Get the default branch (usually `main` or `master`) using `git remote show origin | grep 'HEAD branch'`
- Analyze the diff from the default branch to understand all changes (ignore individual commits)
- Review changed files to understand the scope of changes
2. **Generate PR Content**
- Create a descriptive title that summarizes the changes
- Generate a comprehensive description with:
- A brief summary paragraph at the top
- **User-Facing Changes**: What end-users will notice or experience
- **Developer Notes**: Technical details, implementation notes, or items of interest to other developers
- Keep the description concise but informative
3. **Get User Confirmation**
- Present the proposed PR title and description to the user
- Ask for confirmation or request modifications
- Allow the user to edit the title or description before proceeding
4. **Create Draft PR**
- Once confirmed, use the `gh` CLI to create a draft PR:
```bash
gh pr create --draft --title "TITLE" --body "DESCRIPTION"
```
- Report the PR URL to the user
## Requirements
- The `gh` CLI must be installed and authenticated (if not installed, use `nix run nixpkgs#gh` to run it)
- The repository must have a remote configured on GitHub
- The current branch must have commits that aren't in the default branch
## Example Output Format
```markdown
PR Title: Add new authentication system
PR Description:
This PR introduces a modern OAuth-based authentication system alongside improved password management, enhancing both security and user experience.
## User-Facing Changes
- Users can now log in using OAuth providers (Google, GitHub)
- Improved password reset flow with better email notifications
- Session timeout increased from 1 hour to 24 hours
## Developer Notes
- Implemented OAuth2 client using the `oauth2-client` library
- Added new `AuthService` class to handle authentication logic
- Updated database schema with new `oauth_tokens` table
- Added comprehensive unit tests for authentication flows
```
## Notes
- Always create as a **draft** PR initially so the user can make further changes if needed
- If the branch name follows a convention (e.g., `feature/`, `fix/`), incorporate that context into the title
- If there are uncommitted changes, warn the user before proceeding

View file

@ -1,4 +0,0 @@
{
command = "npx";
args = [ "chrome-devtools-mcp@latest" ];
}

View file

@ -1,4 +0,0 @@
{
command = "uvx";
args = [ "mcp-nixos" ];
}

View file

@ -1,12 +0,0 @@
# System Instructions
- Talk like a naive kid as much as possible
- Sacrifice grammar for brevity.
- Don't say "First, " say "Indeed, "
- Don't say "Good" or "Perfect" say "Great"
# Tools
- **gh**: If `gh` is unavailable, get it from nixpkgs, viz.: `nix run nixpkgs#gh`.
- **article-extractor**: To extract clean article content from URLs (blog posts, articles, tutorials), use the article-extractor skill. It removes ads, navigation, and clutter and saves readable text.

View file

@ -1,124 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.programs.claude-code;
# Auto-wire subagents from subagents/ directory
subagentsDir = cfg.autoWire.dir + "/subagents";
autoAgents = lib.optionalAttrs (builtins.pathExists subagentsDir)
(lib.mapAttrs'
(fileName: _:
lib.nameValuePair
(lib.removeSuffix ".md" fileName)
(builtins.readFile (subagentsDir + "/${fileName}"))
)
(builtins.readDir subagentsDir));
# Auto-wire commands from commands/ directory
commandsDir = cfg.autoWire.dir + "/commands";
autoCommands = lib.optionalAttrs (builtins.pathExists commandsDir)
(lib.mapAttrs'
(fileName: _:
lib.nameValuePair
(lib.removeSuffix ".md" fileName)
(builtins.readFile (commandsDir + "/${fileName}"))
)
(builtins.readDir commandsDir));
# Auto-wire skills from skills/ directory
skillsDir = cfg.autoWire.dir + "/skills";
skillDirs = lib.optionalAttrs (builtins.pathExists skillsDir)
(lib.filterAttrs (_: type: type == "directory") (builtins.readDir skillsDir));
# Process skill: if it has default.nix, build and substitute; otherwise use as-is
processSkill = skillName:
let
skillPath = skillsDir + "/${skillName}";
hasDefaultNix = builtins.pathExists (skillPath + "/default.nix");
in
if hasDefaultNix then
let
skillPkg = pkgs.callPackage skillPath { };
in
pkgs.runCommand "${skillName}-skill" { } ''
mkdir -p $out
substitute ${skillPath}/SKILL.md $out/SKILL.md \
--replace-fail '@${skillName}@' '${skillPkg}/bin/${skillName}'
''
else
skillPath;
# Auto-wire MCP servers from mcp/ directory
mcpDir = cfg.autoWire.dir + "/mcp";
autoMcpServers = lib.optionalAttrs (builtins.pathExists mcpDir)
(lib.mapAttrs'
(fileName: _:
lib.nameValuePair
(lib.removeSuffix ".nix" fileName)
(import (mcpDir + "/${fileName}"))
)
(builtins.readDir mcpDir));
# Auto-load settings from settings.nix
settingsFile = cfg.autoWire.dir + "/settings.nix";
autoSettings = lib.optionalAttrs (builtins.pathExists settingsFile)
(import settingsFile);
# Auto-load memory from memory.md
memoryFile = cfg.autoWire.dir + "/memory.md";
autoMemory = lib.optionalAttrs (builtins.pathExists memoryFile)
{ text = builtins.readFile memoryFile; };
in
{
options.programs.claude-code = {
autoWire = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether to automatically wire up subagents, commands, skills, and MCP servers from autoWire.dir.
Set to false if you want to manually configure these.
'';
};
dir = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
Path to the claude-code directory containing subagents/, commands/, skills/, mcp/, settings.nix, and memory.md.
When set, these will be automatically discovered and configured.
'';
};
};
};
config = lib.mkIf (cfg.enable && cfg.autoWire.dir != null && cfg.autoWire.enable) {
# Link skill directories to ~/.claude/skills/
home.file = lib.mapAttrs'
(skillName: _:
lib.nameValuePair ".claude/skills/${skillName}" {
source = processSkill skillName;
recursive = true;
}
)
skillDirs;
programs.claude-code = {
# Auto-wire settings if settings.nix exists
settings = lib.mkDefault autoSettings;
# Auto-wire memory if memory.md exists
memory = lib.mkDefault autoMemory;
# Auto-wire commands from commands/ directory
commands = lib.mkDefault autoCommands;
# Auto-wire agents from subagents/ directory
agents = lib.mkDefault autoAgents;
# Auto-wire MCP servers from mcp/ directory
mcpServers = lib.mkDefault autoMcpServers;
};
};
}

View file

@ -1,8 +0,0 @@
{
# theme = "dark";
permissions = {
defaultMode = "bypassPermissions";
};
# Disable Claude from adding itself as co-author to commits
includeCoAuthoredBy = false;
}

View file

@ -1,31 +0,0 @@
---
name: article-extractor
description: Extract clean article content from URLs using reader. Use when user wants to download/extract/save an article from a URL.
allowed-tools:
- Bash
- Write
---
# Article Extractor
Extracts clean article content from URLs using `reader` (Mozilla Readability).
## When to Use
User wants to:
- Extract article from URL
- Download blog post content
- Save article as text
## Workflow
Extract article content and save it:
```bash
CONTENT=$(@article-extractor@ "$URL")
```
Then use the Write tool to save `$CONTENT` to the desired location with an appropriate filename.
The script outputs clean markdown content to stdout. You decide where and how to save it based on the user's request.

View file

@ -1,23 +0,0 @@
{ writeShellApplication, curl, reader }:
writeShellApplication {
name = "article-extractor";
runtimeInputs = [ curl reader ];
text = ''
URL="$1"
# Create unique temp file
TEMP_HTML=$(mktemp)
# Download HTML
curl -s -L "$URL" > "$TEMP_HTML"
# Extract and output article to stdout
reader "$TEMP_HTML"
# Clean up
rm "$TEMP_HTML"
'';
}

View file

@ -1,129 +0,0 @@
---
name: haskell
description: Expert Haskell development assistance. Use when working with Haskell code, .hs files, Cabal, ghcid, or when user mentions Haskell, functional programming, or type-level programming.
---
# Haskell Development
Expert assistance for Haskell programming.
## Guidelines
**CRITICAL - Error Handling in Code**: NEVER write code that silently ignores errors:
- Do NOT use `undefined` or `error` as placeholders
- Do NOT skip handling error cases in pattern matches
- Do NOT ignore `Maybe`/`Either` failure cases
- Handle all possible cases explicitly
- Use types to make impossible states unrepresentable
Every error case in generated code must be handled properly.
**Code Quality**:
- Write type signatures for all top-level definitions
- Write total functions (avoid `head`, `tail`)
- Prefer pure functions over IO when possible
- Use explicit exports in modules
- Leverage type system for safety
- Favor composition over complex functions
- Write Haddock documentation for public APIs
**Idiomatic Patterns**:
- Prefer `Text` over `String`
- Use `newtype` wrappers for domain types
- Apply smart constructors for validation
- Use RecordDotSyntax (`value.field`) instead of manually unpacking data types
- Use lenses for record manipulation when appropriate
- Use `Applicative` and `Monad` appropriately
- Avoid trivial `let` bindings when inlining keeps code simple and readable
## HLint
**IMPORTANT**: Always check if the project has a `.hlint.yaml` file. If it does:
1. Read the `.hlint.yaml` file to understand project-specific style rules
2. Follow all recommendations in that file when writing code
3. After making code changes, run `hlint` to ensure no warnings
## Relude Best Practices
When using relude prelude, follow these HLint recommendations (from https://github.com/kowainik/relude/blob/main/.hlint.yaml):
**Basic Idioms**:
- Use `pass` instead of `pure ()` or `return ()`
- Use `one` instead of `(: [])`, `(:| [])`, or singleton functions
- Use `<<$>>` for double fmap: `f <<$>> x` instead of `fmap (fmap f) x`
- Use `??` (flap) operator: `ff ?? x` instead of `fmap ($ x) ff`
**File I/O**:
- `readFileText`, `writeFileText`, `appendFileText` for Text files
- `readFileLText`, `writeFileLText`, `appendFileLText` for lazy Text
- `readFileBS`, `writeFileBS`, `appendFileBS` for ByteString
- `readFileLBS`, `writeFileLBS`, `appendFileLBS` for lazy ByteString
**Console Output**:
- `putText`, `putTextLn` for Text
- `putLText`, `putLTextLn` for lazy Text
- `putBS`, `putBSLn` for ByteString
- `putLBS`, `putLBSLn` for lazy ByteString
**Maybe/Either Helpers**:
- `whenJust m f` instead of `maybe pass f m`
- `whenJustM m f` for monadic versions
- `whenNothing_ m x` / `whenNothingM_ m x` for Nothing cases
- `whenLeft_ m f`, `whenRight_ m f` for Either
- `whenLeftM_ m f`, `whenRightM_ m f` for monadic Either
- `leftToMaybe`, `rightToMaybe` for conversions
- `maybeToRight l`, `maybeToLeft r` for conversions
- `isLeft`, `isRight` instead of `either (const True/False) (const False/True)`
**List Operations**:
- Use `ordNub` instead of `nub` (O(n log n) vs O(n²))
- Use `sortNub` instead of `Data.Set.toList . Data.Set.fromList`
- Use `sortWith f` instead of `sortBy (comparing f)` for simple cases
- Use `viaNonEmpty f x` instead of `fmap f (nonEmpty x)`
- Use `asumMap f xs` instead of `asum (map f xs)`
- Use `toList` instead of `foldr (:) []`
**Monadic Operations**:
- `andM s` instead of `and <$> sequence s`
- `orM s` instead of `or <$> sequence s`
- `allM f s` instead of `and <$> mapM f s`
- `anyM f s` instead of `or <$> mapM f s`
- `guardM f` instead of `f >>= guard`
- `infinitely` instead of `forever` (better typed)
- `unlessM (not <$> x)` → use `whenM x` instead
- `whenM (not <$> x)` → use `unlessM x` instead
**State/Reader Operations**:
- `usingReaderT` instead of `flip runReaderT`
- `usingStateT` instead of `flip runStateT`
- `evaluatingStateT s st` instead of `fst <$> usingStateT s st`
- `executingStateT s st` instead of `snd <$> usingStateT s st`
**Transformer Lifting**:
- `hoistMaybe m` instead of `MaybeT (pure m)`
- `hoistEither m` instead of `ExceptT (pure m)`
**List Pattern Matching**:
- `whenNotNull m f` for `case m of [] -> pass; (x:xs) -> f (x :| xs)`
- `whenNotNullM m f` for monadic version
**Text/ByteString Conversions**:
- Use relude's `toText`, `toString`, `toLText` instead of pack/unpack
- Use relude's `encodeUtf8`, `decodeUtf8` for UTF-8 encoding
- `fromStrict`, `toStrict` for lazy/strict conversions
## Testing
- Use QuickCheck for property-based testing
- Use HUnit or Hspec for unit tests
- Provide good examples in documentation
## Build instructions
As you make code changes, start a subagent in parallel to resolve any compile errors in `ghcid.txt`.
**IMPORTANT**: Do not run build commands yourself. The human runs ghcid in the terminal, which then updates `ghcid.txt` with any compile error or warning (if this file does not exist, or if ghcid has stopped, remind the human to address it). You should read `ghcid.txt` (in _entirety_) after making code changes; this file updates near-instantly.
**Adding/Deleting modules**: When a new `.hs` file is added or deleted, the `.cabal` file must be updated accordingly. However, if `package.yaml` exists in the project, run `hpack` instead to regenerate the `.cabal` file with the updated module list. This will trigger `ghcid` to restart automatically.
**HLint warnings**: Once all code changes are made and `ghcid.txt` shows success, check if the project has a `.hlint.yaml` file. If it does, run hlint to ensure there are no warnings and address any that appear.

View file

@ -1,11 +0,0 @@
---
name: nix
description: Expert Nix development assistance. Use when working with Nix code, .nix files, flakes, NixOS configuration, or when user mentions Nix, flake-parts, nixpkgs.
---
# Nix Development
## Guidelines
- Use **flake-parts** when creating new flakes
- Format with **nixpkgs-fmt** after changes

View file

@ -1,31 +0,0 @@
---
name: pre-commit
description: Invoke after changing sources locally, and only if git-hooks.nix is used by Nix.
tools: Bash
---
# Pre-commit Quality Check Agent
## Purpose
This agent runs `pre-commit run -a` to automatically check code quality and formatting when other agents modify files in the repository.
## When to Use
- After any agent makes file modifications
- Before committing changes
- When code quality checks are needed
## Tools Available
- Bash (for running pre-commit)
- Read (for checking file contents if needed)
## Typical Workflow
1. Run `pre-commit run -a` to check all files
2. Report any issues found
3. Suggest fixes if pre-commit hooks fail
4. Re-run after fixes are applied
## Example Usage
```bash
pre-commit run -a
```
This agent ensures code quality standards are maintained across the repository by leveraging the configured pre-commit hooks.

17
flake.lock generated
View file

@ -1,5 +1,21 @@
{
"nodes": {
"AI": {
"flake": false,
"locked": {
"lastModified": 1762823677,
"narHash": "sha256-tAFietBkeOYSUh+5KqZcfDA55L+A9IsPQZSuupNY+vM=",
"owner": "srid",
"repo": "AI",
"rev": "ba61df36131e5a9a7165c141e7e9ba18a56da324",
"type": "github"
},
"original": {
"owner": "srid",
"repo": "AI",
"type": "github"
}
},
"agenix": {
"inputs": {
"darwin": "darwin",
@ -895,6 +911,7 @@
},
"root": {
"inputs": {
"AI": "AI",
"agenix": "agenix",
"disko": "disko",
"flake-parts": "flake-parts",

View file

@ -31,6 +31,8 @@
nix-ai-tools.url = "github:numtide/nix-ai-tools";
nix-ai-tools.inputs.nixpkgs.follows = "nixpkgs";
landrun-nix.url = "github:srid/landrun-nix";
AI.url = "github:srid/AI";
AI.flake = false;
# Neovim
nixvim.url = "github:nix-community/nixvim";

View file

@ -17,6 +17,7 @@
"nix-index-database"
"nixvim"
"nix-ai-tools"
"AI"
];
};
};

View file

@ -1,8 +1,11 @@
{ flake, pkgs, ... }:
let
inherit (flake.inputs) AI;
in
{
# Import the general home-manager module
imports = [
../../../claude-code/nix/home-manager-module.nix
"${AI}/nix/home-manager-module.nix"
];
# Packages often used by Claude Code CLI
@ -20,6 +23,6 @@
else pkgs.claude-code;
# Set the claude-code directory for auto-wiring
autoWire.dir = ../../../claude-code;
autoWire.dir = AI;
};
}