mirror of
https://github.com/srid/nixos-config.git
synced 2026-04-09 12:27:30 +08:00
Migrate AI config to nixos-config, use nix-agent-wire (#107)
- Move AI config from nix-agent-wire/srid to ./AI - Update flake input: srid/AI -> srid/nix-agent-wire - Update home modules to use local AI folder via flake.self.outPath
This commit is contained in:
parent
7a127fbdb4
commit
0537ef99b9
16 changed files with 747 additions and 27 deletions
31
AI/agents/pre-commit.md
Normal file
31
AI/agents/pre-commit.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
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.
|
||||
105
AI/commands/gci.md
Normal file
105
AI/commands/gci.md
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
description: Stage, commit, and push changes
|
||||
subtask: true
|
||||
---
|
||||
|
||||
# GCI Command
|
||||
|
||||
Stage all changes, generate a commit message, commit, and push after user approval.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/gci # Normal mode - prompts for approval, then commits and pushes
|
||||
/gci yes # Auto mode - commits and pushes without prompting
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Stage All Changes**
|
||||
- Run `git add -A` to stage all changes (new files, modifications, deletions)
|
||||
|
||||
2. **Show Status and Generate Commit Message**
|
||||
- Run `git status` to show what will be committed
|
||||
- Analyze the staged changes using `git diff --cached`
|
||||
- Generate a concise, descriptive commit message that:
|
||||
- Summarizes WHAT changed in a single line (50-72 characters)
|
||||
- If needed, adds a brief description of WHY in the body
|
||||
- Uses imperative mood (e.g., "Add feature" not "Added feature")
|
||||
- Follows conventional commit style if appropriate
|
||||
|
||||
3. **Present to User for Approval** (skip if 'yes' argument provided)
|
||||
- Display the generated commit message
|
||||
- Show the `git status` output of what will be committed
|
||||
- **Use the question tool** to ask for approval with options:
|
||||
- "Commit" - proceed with the commit
|
||||
- "Edit message" - user wants to modify the message (use custom option)
|
||||
- "Cancel" - abort the commit
|
||||
- **If 'yes' argument was provided**: Skip this step entirely and proceed directly to commit
|
||||
|
||||
4. **Commit Changes**
|
||||
- Once approved (or if 'yes' argument provided), run `git commit -m "MESSAGE"` (or `git commit -F -` with multi-line message)
|
||||
- Report the commit hash and summary to the user
|
||||
|
||||
5. **Push Changes**
|
||||
- After successful commit, run `git push` to push to remote
|
||||
- Report push status to user
|
||||
|
||||
## Important Constraints
|
||||
|
||||
- **NEVER auto-commit**: ALWAYS ask user for approval before running `git commit` - NEVER commit without explicit user confirmation (UNLESS the 'yes' argument is provided)
|
||||
- **Single commit only**: This command creates exactly ONE new commit on top of the current branch
|
||||
- **No history rewriting**: Never use `--amend`, `--fixup`, rebase, or reset operations
|
||||
- **No other mutations**: The only git operations are `git commit` and `git push`
|
||||
|
||||
## Requirements
|
||||
|
||||
- Must be in a git repository
|
||||
- There must be changes to commit (either unstaged or already staged)
|
||||
|
||||
## Example Output Format
|
||||
|
||||
### Normal Mode (`/gci`)
|
||||
```markdown
|
||||
Staged changes:
|
||||
M src/app.ts
|
||||
A src/utils/helper.ts
|
||||
D old-file.js
|
||||
|
||||
Proposed commit message:
|
||||
Add helper utilities and refactor app
|
||||
|
||||
Removes deprecated old-file.js and introduces new helper functions
|
||||
for data validation. Updates app.ts to use the new utilities.
|
||||
|
||||
[Uses question tool with options: Commit, Edit message, Cancel]
|
||||
```
|
||||
|
||||
### Auto Mode (`/gci yes`)
|
||||
```markdown
|
||||
Staged changes:
|
||||
M src/app.ts
|
||||
A src/utils/helper.ts
|
||||
D old-file.js
|
||||
|
||||
Generated commit message:
|
||||
Add helper utilities and refactor app
|
||||
|
||||
Removes deprecated old-file.js and introduces new helper functions
|
||||
for data validation. Updates app.ts to use the new utilities.
|
||||
|
||||
Creating commit...
|
||||
[master abc1234] Add helper utilities and refactor app
|
||||
|
||||
Pushing to remote...
|
||||
Done. Pushed to origin/master.
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Use the question tool for approval in normal mode - this provides a structured UI for the user
|
||||
- If user selects "Edit message", use the question tool's custom option to let them type a new message
|
||||
- If there are already staged changes, ask the user if they want to add unstaged changes too
|
||||
- If there are no changes at all, inform the user and exit
|
||||
- Keep the commit message clear and focused on the user-facing impact
|
||||
- The default branch of the commit message should be concise (50-72 chars)
|
||||
58
AI/commands/gh-settings.md
Normal file
58
AI/commands/gh-settings.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
description: Apply preferred GitHub repo settings
|
||||
subtask: true
|
||||
---
|
||||
|
||||
# GH Settings Command
|
||||
|
||||
Apply preferred GitHub repository settings.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/gh-settings # Apply to current repo
|
||||
/gh-settings owner/repo # Apply to specific repo
|
||||
```
|
||||
|
||||
## Settings Applied
|
||||
|
||||
1. **Squash merge format**: title=PR_TITLE, message=PR_BODY
|
||||
2. **Disable**: wiki, projects, merge-commit
|
||||
3. **Enable**: rebase-merge, squash-merge
|
||||
4. **Enable**: allow-update-branch, delete-branch-on-merge
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Detect Repository**
|
||||
- If argument provided: use `owner/repo` format
|
||||
- If no argument: detect from `git remote get-url origin`
|
||||
```bash
|
||||
git remote get-url origin | sed 's/.*github.com[/:]//' | sed 's/.git$//'
|
||||
```
|
||||
|
||||
2. **Apply Settings**
|
||||
|
||||
Run both commands:
|
||||
```bash
|
||||
# Set squash merge commit format
|
||||
gh api --method PATCH repos/{owner}/{repo} -f squash_merge_commit_title=PR_TITLE -f squash_merge_commit_message=PR_BODY > /dev/null
|
||||
|
||||
# Apply repository settings
|
||||
gh repo edit --enable-wiki=false --enable-projects=false --enable-merge-commit=false --enable-rebase-merge --enable-squash-merge --allow-update-branch --delete-branch-on-merge
|
||||
```
|
||||
|
||||
3. **Confirm**
|
||||
- Report success to user
|
||||
- Show the repo that was updated
|
||||
|
||||
## Requirements
|
||||
|
||||
- `gh` CLI installed and authenticated (use `nix run nixpkgs#gh` if not installed)
|
||||
- Must have admin access to the repository
|
||||
- Repository must have a GitHub remote (for auto-detection)
|
||||
|
||||
## Notes
|
||||
|
||||
- This is idempotent - running multiple times has the same effect
|
||||
- Settings are applied in sequence; both must succeed for complete application
|
||||
- The `{owner}/{repo}` placeholder in the API call works with `gh` CLI's default behavior
|
||||
123
AI/commands/plan.md
Normal file
123
AI/commands/plan.md
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
# Plan Command
|
||||
|
||||
Create a detailed implementation plan for a feature, fix, or change. The plan is saved to `.plan/<slug>.md` for iterative refinement through review cycles.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/plan <description> # Create plan from description
|
||||
/plan <github-issue-url> # Create plan from GitHub issue
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. **Create Initial Plan**
|
||||
|
||||
**IMPORTANT: This command ONLY creates the plan file. DO NOT implement anything. DO NOT write code. ONLY create the plan document.**
|
||||
|
||||
- Parse the input (description or GitHub issue URL)
|
||||
- If GitHub issue URL, fetch the issue content using `gh issue view <number>`
|
||||
- Generate a suitable slug from the main topic (lowercase, hyphenated)
|
||||
- Create `.plan/` directory if it doesn't exist
|
||||
- Write plan to `.plan/<slug>.md` with:
|
||||
- **Overview**: High-level description of what needs to be done and why
|
||||
- **Phases**: Determine number of phases based on complexity:
|
||||
- Each phase must be self-contained and easily implementable by Claude
|
||||
- Each phase must be easily reviewable by user before next phase
|
||||
- If task is trivial, use single phase or omit phases section entirely
|
||||
- For each phase include:
|
||||
- Phase number and name
|
||||
- Specific tasks/steps within that phase
|
||||
- Expected outcomes
|
||||
- Any dependencies or prerequisites
|
||||
- **STOP after creating the plan file. Tell user the plan is ready for review.**
|
||||
|
||||
### 2. **Plan Review Cycle**
|
||||
- User reviews the plan file
|
||||
- User adds comments prefixed with `ME: ` right below the specific item/section they're commenting on
|
||||
- User asks Claude to "review comments" or "address comments"
|
||||
- Claude:
|
||||
- Reads the plan file
|
||||
- Reviews all `ME: ` comments
|
||||
- Adjusts the plan based on feedback
|
||||
- **Removes the `ME: ` comments** that have been addressed
|
||||
- Writes the updated plan back to the file
|
||||
- Repeat until user is satisfied
|
||||
|
||||
### 3. **Implementation**
|
||||
- User typically asks to implement one phase at a time (e.g., "implement phase 1")
|
||||
- Claude implements that specific phase
|
||||
- User reviews the implementation
|
||||
- User asks for next phase when ready
|
||||
- Repeat until all phases complete
|
||||
- Can reference the plan file throughout implementation
|
||||
|
||||
## Plan File Format
|
||||
|
||||
```markdown
|
||||
# Plan: <Title>
|
||||
|
||||
## Overview
|
||||
|
||||
<High-level description of the change, including context and motivation>
|
||||
|
||||
## Phases
|
||||
|
||||
### Phase 1: <Name>
|
||||
|
||||
- Task or step description
|
||||
- Another task
|
||||
- Expected outcome: <what this phase achieves>
|
||||
|
||||
### Phase 2: <Name>
|
||||
|
||||
- Task or step description
|
||||
- Another task
|
||||
- Expected outcome: <what this phase achieves>
|
||||
|
||||
### Phase 3: <Name>
|
||||
|
||||
...
|
||||
|
||||
## Notes
|
||||
|
||||
- Any additional considerations
|
||||
- Risks or gotchas
|
||||
- References or links
|
||||
```
|
||||
|
||||
## Example Flow
|
||||
|
||||
```markdown
|
||||
User: /plan Add dark mode support to the application
|
||||
|
||||
Claude: Created plan at .plan/dark-mode-support.md
|
||||
|
||||
User: [Reviews file, adds comments]
|
||||
ME: Should we also handle system preference detection?
|
||||
ME: What about persisting user choice?
|
||||
|
||||
User: Review the comments
|
||||
|
||||
Claude: [Updates plan to address both comments, removes the ME: lines]
|
||||
Updated plan at .plan/dark-mode-support.md
|
||||
|
||||
User: Looks good, implement it
|
||||
|
||||
Claude: [Proceeds with Phase 1 implementation...]
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- If input is a GitHub issue URL, `gh` CLI must be available (use `nix run nixpkgs#gh` if not installed)
|
||||
- Write permission in the repository root for creating `.plan/` directory
|
||||
|
||||
## Notes
|
||||
|
||||
- Plan files are iterative - expect multiple review cycles
|
||||
- Number of phases depends on task complexity - trivial tasks may have one or no phases
|
||||
- Keep phases sequential and logical
|
||||
- Each phase should be self-contained, easily implementable, and easily reviewable
|
||||
- Each phase should have clear entry and exit criteria
|
||||
- Remove `ME: ` comments only after addressing them in the plan
|
||||
- The plan file is the source of truth for implementation
|
||||
120
AI/commands/pr-review.md
Normal file
120
AI/commands/pr-review.md
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
---
|
||||
description: Resolve PR review comments
|
||||
subtask: true
|
||||
---
|
||||
|
||||
# PR Review Command
|
||||
|
||||
Fetch and resolve review comments from a GitHub pull request by implementing the requested changes.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/pr-review # Review comments on current branch's PR
|
||||
/pr-review 123 # Review comments on PR #123
|
||||
/pr-review https://github.com/owner/repo/pull/123
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. **Identify the PR**
|
||||
|
||||
- If URL provided: Extract owner, repo, and PR number
|
||||
- If number provided: Use current repo (from `git remote -v`)
|
||||
- If no argument: Get PR number from current branch using `gh pr view --json number`
|
||||
|
||||
### 2. **Fetch Review Comments**
|
||||
|
||||
**IMPORTANT: Fetch REVIEW COMMENTS, not plain comments. Review comments are on specific lines of code.**
|
||||
|
||||
Use `gh api` to fetch:
|
||||
```bash
|
||||
# Get PR review threads (includes is_resolved field)
|
||||
gh api repos/OWNER/REPO/pulls/NUMBER/threads
|
||||
|
||||
# Get PR reviews (contains review state: CHANGES_REQUESTED, APPROVED, etc.)
|
||||
gh api repos/OWNER/REPO/pulls/NUMBER/reviews
|
||||
```
|
||||
|
||||
**IMPORTANT: Filter out resolved threads. Only process threads where `is_resolved` is false.**
|
||||
|
||||
The threads API returns:
|
||||
- `is_resolved`: Whether the thread has been marked as resolved
|
||||
- `path`: File being commented on
|
||||
- `line`: Line number
|
||||
- `comments`: Array of comments in the thread
|
||||
- `body`: Comment text
|
||||
- `user.login`: Author
|
||||
- `pull_request_review_id`: Links to the review
|
||||
|
||||
### 3. **Filter and Present Comments**
|
||||
|
||||
- **Filter out resolved threads** - only process threads where `is_resolved` is false
|
||||
- Group threads by file for clarity
|
||||
- Check review states - prioritize comments from reviews with `CHANGES_REQUESTED` state
|
||||
- Present a summary:
|
||||
```markdown
|
||||
## PR #123 Review Comments
|
||||
|
||||
### src/auth.rs (2 comments)
|
||||
1. @reviewer: "This function should handle the error case properly"
|
||||
Line: 45
|
||||
2. @reviewer: "Consider using a constant here"
|
||||
Line: 52
|
||||
|
||||
### src/main.rs (1 comment)
|
||||
1. @reviewer: "Add documentation"
|
||||
Line: 12
|
||||
|
||||
Total: 3 unresolved comments
|
||||
```
|
||||
|
||||
### 4. **Implement Changes**
|
||||
|
||||
For each review comment:
|
||||
- Read the relevant file and understand the context around the commented line
|
||||
- Implement the requested change
|
||||
- Use the comment's intent, not just literal interpretation
|
||||
- If a comment is unclear, ask for clarification before proceeding
|
||||
- After making changes, confirm with the user
|
||||
|
||||
### 5. **Summary**
|
||||
|
||||
After implementing all changes:
|
||||
- List what was changed in response to each comment
|
||||
- Remind user to push changes and respond to comments on GitHub
|
||||
- Optionally: `git diff --stat` to show changed files
|
||||
|
||||
## API Details
|
||||
|
||||
### Fetching Review Comments
|
||||
|
||||
```bash
|
||||
# Get the repo from git remote
|
||||
REPO=$(git remote get-url origin | sed 's/.*github.com[/:]//' | sed 's/.git$//')
|
||||
|
||||
# Fetch review comments
|
||||
gh api "repos/$REPO/pulls/$NUMBER/comments" --jq '.[] | select(.in_reply_to_id == null) | {path, line, body, user: .user.login}'
|
||||
|
||||
# Fetch reviews to see states
|
||||
gh api "repos/$REPO/pulls/$NUMBER/reviews" --jq '.[] | {user: .user.login, state, body}'
|
||||
```
|
||||
|
||||
### Comment vs Review Comment
|
||||
|
||||
- **Issue comments** (`/issues/123/comments`): General discussion, not tied to code
|
||||
- **Review comments** (`/pulls/123/comments`): Tied to specific lines of code during review
|
||||
- This command handles **review comments only**
|
||||
|
||||
## Requirements
|
||||
|
||||
- `gh` CLI installed and authenticated (use `nix run nixpkgs#gh` if not installed)
|
||||
- Repository must have a GitHub remote
|
||||
- For no-argument usage: current branch must have an associated PR
|
||||
|
||||
## Notes
|
||||
|
||||
- Focus on actionable code comments, not general discussion
|
||||
- If review was dismissed, still show the comments for context
|
||||
- If multiple reviews exist, show comments from all but prioritize unresolved ones
|
||||
- After implementing, the user should mark conversations as resolved on GitHub
|
||||
4
AI/mcp/chrome-devtools.nix
Normal file
4
AI/mcp/chrome-devtools.nix
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
command = "npx";
|
||||
args = [ "chrome-devtools-mcp@latest" ];
|
||||
}
|
||||
4
AI/mcp/nixos-mcp.nix
Normal file
4
AI/mcp/nixos-mcp.nix
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
command = "uvx";
|
||||
args = [ "mcp-nixos" ];
|
||||
}
|
||||
16
AI/memory.md
Normal file
16
AI/memory.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# System Instructions
|
||||
|
||||
- Talk like a naive kid as much as possible
|
||||
- Sacrifice grammar for brevity.
|
||||
|
||||
# Git Policy
|
||||
|
||||
- **NEVER auto-commit**: ALWAYS consult user before running `git commit` - never commit without explicit user approval
|
||||
- User will use `/gci` command when they want Claude to help with commits
|
||||
- **Avoid destructive operations**: No force pushing, rebasing, or amending commits
|
||||
- **devShell required**: Run commits inside devShell if pre-commit hooks exist
|
||||
|
||||
# Tools
|
||||
|
||||
- **nix tools**: If any tool is unavailable, get it from nixpkgs: `nix run nixpkgs#<tool>`.
|
||||
- **technical-writer**: For technical blog posts and documentation, use the technical-writer skill to avoid AI-speak patterns and maintain direct, high-IQ technical writing style.
|
||||
8
AI/settings/claude-code.nix
Normal file
8
AI/settings/claude-code.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
# theme = "dark";
|
||||
permissions = {
|
||||
defaultMode = "bypassPermissions";
|
||||
};
|
||||
# Disable Claude from adding itself as co-author to commits
|
||||
includeCoAuthoredBy = false;
|
||||
}
|
||||
68
AI/skills/haskell/RELUDE.md
Normal file
68
AI/skills/haskell/RELUDE.md
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# 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
|
||||
76
AI/skills/haskell/SKILL.md
Normal file
76
AI/skills/haskell/SKILL.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
name: haskell
|
||||
description: Haskell coding with relude, ghcid-based workflow, hlint compliance, and strict error handling. Use when working with .hs files, Cabal projects, or ghcid.
|
||||
---
|
||||
|
||||
# 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.
|
||||
|
||||
**CRITICAL - Compile Status**:
|
||||
- The code MUST compile without errors.
|
||||
- You MUST check `ghcid.txt` after every change and fix any errors reported there.
|
||||
- Do NOT proceed to verification or linting until `ghcid.txt` is clean.
|
||||
|
||||
**CRITICAL - HLint Compliance**:
|
||||
- You MUST check for `.hlint.yaml` in the project root.
|
||||
- If it exists, you MUST run `hlint` on any file you modify.
|
||||
- You MUST fix ALL hlint warnings before considering the task complete.
|
||||
- Do NOT ignore hlint warnings unless explicitly instructed by the user.
|
||||
|
||||
**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
|
||||
- Records:
|
||||
- Use RecordDotSyntax & OverloadedRecordDot (add pragma to modules that use the syntax)
|
||||
- Use DisambiguateRecordFields and DuplicateRecordFields for simple field names (add pragma to modules that use the syntax)
|
||||
- Use lenses for record manipulation when appropriate
|
||||
- Use `Applicative` and `Monad` appropriately
|
||||
- Avoid trivial `let` bindings when inlining keeps code simple and readable
|
||||
|
||||
**Working with Aeson**:
|
||||
- NEVER construct aeson objects by hand
|
||||
- Instead create a type and use `encode` and `decode` on it
|
||||
- These types should generally use generic deriving of aeson (no hand deriving)
|
||||
|
||||
|
||||
## Relude Best Practices
|
||||
|
||||
When using `relude`, refer to [RELUDE.md](RELUDE.md) for best practices and idioms.
|
||||
|
||||
## 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**: MANDATORY. After `ghcid.txt` shows success, if `.hlint.yaml` exists, run `hlint` on the modified files. You are NOT done until `hlint` reports no issues.
|
||||
110
AI/skills/technical-writer/SKILL.md
Normal file
110
AI/skills/technical-writer/SKILL.md
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
name: technical-writer
|
||||
description: Direct, no-nonsense technical writing. Use for blog posts, documentation, and READMEs. Eliminates AI-speak, hedging, and filler.
|
||||
---
|
||||
|
||||
# Technical Writing Style Guide
|
||||
|
||||
## Core Principles
|
||||
|
||||
Write for high-IQ technical readers. Assume expertise. Remove hand-holding.
|
||||
|
||||
## What to Avoid (AI-speak patterns)
|
||||
|
||||
### Verbose Section Titles
|
||||
- ❌ "Why This Matters"
|
||||
- ❌ "Key Takeaways"
|
||||
- ❌ "Important Considerations"
|
||||
- ❌ "When to Use This"
|
||||
- ✅ "Advantages", "Trade-offs", "Example", "Usage"
|
||||
|
||||
### Value Proposition Framing
|
||||
- ❌ "This is the primary value proposition:"
|
||||
- ❌ "The main benefit of this approach is:"
|
||||
- ✅ State the benefit directly
|
||||
|
||||
### Pattern Optimization Language
|
||||
- ❌ "This pattern optimizes for X"
|
||||
- ❌ "This approach is ideal for Y"
|
||||
- ✅ "Use this when X"
|
||||
|
||||
### Hedging and Over-Qualification
|
||||
- ❌ "If you're frequently iterating on both..."
|
||||
- ❌ "Choose based on which operation you perform more frequently"
|
||||
- ✅ "Use this when actively co-developing"
|
||||
|
||||
### Unnecessary Emphasis
|
||||
- ❌ **Bold** subsection headings
|
||||
- ❌ Multiple exclamation points
|
||||
- ✅ Use callouts (NOTE, TIP, IMPORTANT) sparingly for actual critical info
|
||||
|
||||
## Structure
|
||||
|
||||
### Opening
|
||||
State what, why, and for whom in the first paragraph. No preamble.
|
||||
|
||||
### Pattern/Implementation
|
||||
Show code first. Minimal explanation. Assume readers can read code.
|
||||
|
||||
### Technical Details
|
||||
Link to official documentation. Use callouts for non-obvious gotchas.
|
||||
- `[!NOTE]` for clarifications
|
||||
- `[!TIP]` for advanced understanding
|
||||
- `[!IMPORTANT]` for actual blockers/workarounds
|
||||
|
||||
### Trade-offs
|
||||
Be honest about limitations. Link to upstream issues. Don't sugarcoat.
|
||||
|
||||
### Usage Guidance
|
||||
Direct imperatives. "Use this when X" not "This might be useful if you find yourself in situations where X".
|
||||
|
||||
## Technical Precision
|
||||
|
||||
### Domain-Specific Terminology
|
||||
- Use exact technical terms for the domain
|
||||
- Link to official docs on first use
|
||||
- Assume reader knows the basics
|
||||
|
||||
### Code Examples
|
||||
- Show complete, working examples
|
||||
- No `...` placeholders or "existing code" comments
|
||||
- Include all relevant flags/options
|
||||
|
||||
### References Section
|
||||
- Link to upstream documentation
|
||||
- Link to relevant issues/discussions
|
||||
- Link to working examples
|
||||
- Keep descriptions minimal (one clause)
|
||||
|
||||
## Iteration Notes
|
||||
|
||||
When revising:
|
||||
1. Remove all "This is because..." explanations unless non-obvious
|
||||
2. Cut phrases like "as mentioned above", "as we saw earlier"
|
||||
3. Remove transition sentences between sections
|
||||
4. State facts directly - no "it's worth noting that"
|
||||
5. Replace "you can" with imperative: "Run X" not "You can run X"
|
||||
|
||||
## Example Transformations
|
||||
|
||||
### Before (AI-speak)
|
||||
> This pattern optimizes for active co-development. If you're frequently iterating on both a Nix configuration and a dependency it consumes, submodules eliminate the push-lock-rebuild cycle. Choose based on which operation you perform more frequently.
|
||||
|
||||
### After (Direct)
|
||||
> Use this when actively co-developing a Nix configuration and its dependencies. Submodules eliminate the push-lock-rebuild cycle.
|
||||
|
||||
---
|
||||
|
||||
### Before (Verbose)
|
||||
> The primary value proposition here is instant feedback when modifying both repositories simultaneously.
|
||||
|
||||
### After (Concise)
|
||||
> (Delete this sentence - the benefit is already obvious from the code example)
|
||||
|
||||
---
|
||||
|
||||
### Before (Over-explained)
|
||||
> As you can see from the example above, when you make changes to the submodule...
|
||||
|
||||
### After (Direct)
|
||||
> Changes to `vendor/AI/` are picked up immediately on rebuild.
|
||||
38
flake.lock
generated
38
flake.lock
generated
|
|
@ -1,23 +1,5 @@
|
|||
{
|
||||
"nodes": {
|
||||
"AI": {
|
||||
"inputs": {
|
||||
"skills": "skills"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773691758,
|
||||
"narHash": "sha256-hogU3oBAJQ52v9IsEVun8s8r7R4rY8ZSXyDZEDJHnR0=",
|
||||
"owner": "srid",
|
||||
"repo": "AI",
|
||||
"rev": "89bd7cfb23e050420fed5caf2cd78f1aa17e2d74",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "srid",
|
||||
"repo": "AI",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"aeson-typescript": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
|
|
@ -909,6 +891,24 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-agent-wire": {
|
||||
"inputs": {
|
||||
"skills": "skills"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773694375,
|
||||
"narHash": "sha256-wk2i1T3b3OMrOwI/ho8M9TEu7A3VU2jkhc9lb6IcF2E=",
|
||||
"owner": "srid",
|
||||
"repo": "nix-agent-wire",
|
||||
"rev": "ab54edc3de7a44723d91e19f541485856654f85d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "srid",
|
||||
"repo": "nix-agent-wire",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
|
@ -1278,7 +1278,6 @@
|
|||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"AI": "AI",
|
||||
"agenix": "agenix",
|
||||
"disc-scrape": "disc-scrape",
|
||||
"disko": "disko",
|
||||
|
|
@ -1290,6 +1289,7 @@
|
|||
"imako": "imako",
|
||||
"jumphost-nix": "jumphost-nix",
|
||||
"landrun-nix": "landrun-nix",
|
||||
"nix-agent-wire": "nix-agent-wire",
|
||||
"nix-darwin": "nix-darwin",
|
||||
"nix-index-database": "nix-index-database",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
oc.url = "github:juspay/oc";
|
||||
# landrun-nix.url = "github:srid/landrun-nix";
|
||||
landrun-nix.url = "github:adrian-gierakowski/landrun-nix/darwin-implementation-via-sandbox-exec";
|
||||
AI.url = "github:srid/AI";
|
||||
nix-agent-wire.url = "github:srid/nix-agent-wire";
|
||||
jumphost-nix.url = "github:srid/jumphost-nix";
|
||||
jumphost-nix.flake = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
{ flake, pkgs, ... }:
|
||||
let
|
||||
inherit (flake.inputs) AI;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
AI.homeManagerModules.claude-code
|
||||
flake.inputs.nix-agent-wire.homeManagerModules.claude-code
|
||||
];
|
||||
|
||||
home.packages = with pkgs; [
|
||||
|
|
@ -16,6 +13,6 @@ in
|
|||
|
||||
package = flake.inputs.self.packages.${pkgs.stdenv.hostPlatform.system}.claude;
|
||||
|
||||
autoWire.dir = AI;
|
||||
autoWire.dir = flake.self.outPath + "/AI";
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
{
|
||||
imports = [
|
||||
flake.inputs.oc.homeModules.default
|
||||
flake.inputs.AI.homeManagerModules.opencode
|
||||
flake.inputs.nix-agent-wire.homeManagerModules.opencode
|
||||
];
|
||||
|
||||
programs.opencode = {
|
||||
package = flake.inputs.oc.packages.${pkgs.stdenv.hostPlatform.system}.opencode;
|
||||
autoWire.dir = flake.inputs.AI;
|
||||
autoWire.dir = flake.self.outPath + "/AI";
|
||||
};
|
||||
|
||||
programs.zsh.initContent = ''
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue