riglet-creator
Imported from ypares/rigup.nix/riglets/riglet-creator.
Install
npx skills add https://github.com/YPares/rigup.nix/tree/main/riglets/riglet-creator
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install ypares-rigup-nix@llmmart
git clone https://github.com/YPares/rigup.nix.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole ypares/rigup.nix collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Riglet Creator
Creating effective riglets means writing knowledge (SKILL.md) that agents will rely on. This guide focuses on how to write high-quality documentation for riglets, organized efficiently.
For the structural/technical side of riglets (what goes in the Nix module, metadata fields, schema), see the riglet agent-rig-system's SKILL.md and references/metadata-guide.md.
Core Principles
Define the Main Intent
Ask yourself: what is the end goal here? What should this riglet teach?
The intent metadata is there to help you here. It should guide how you approach the writing of a riglet.
As a reminder, the possible intents are:
- base: "abstract" riglet (e.g. to define options) solely meant to be imported by others to factorize configuration. Cannot be disclosed in a manifest
- sourcebook: compendium of knowledge, glossary, useful domain knowledge
- toolbox: open-ended set of tools related together
- cookbook: operational know-how, heuristics, tricks and techniques that are useful to apprehend an otherwise complex toolset or domain
- playbook: specific procedure or workflow to follow in a rigorous manner
A riglet should fall under one of these categories. If several apply, then it might be a better idea to split it into several.
Discuss that with your user. Several riglets, each one with a clear focus, are better than one unorganized riglet that tries to cover everything without a real goal.
Remember riglets can depend on each other via imports, so for example a very specialized "playbook" can depend on tools explained and documented in a more general "toolbox".
Concise is Key
Agents share context windows with conversation history, system instructions, and other riglets in the rig. Context is a shared resource.
Default assumption: Agents are already very capable. Only include knowledge agents don't already have. Challenge each piece of information: "Does the agent really need this explanation?" and "Does this paragraph justify its token cost?"
Prefer concrete examples over verbose explanations. Prefer links to references over embedding everything in SKILL.md.
Set Appropriate Degrees of Freedom
Match documentation specificity to the task's fragility and variability:
High freedom (general guidance): Use when multiple approaches are valid, decisions depend on context, or heuristics guide the process. Example: "Organizing commits in JJ" — many strategies work.
Medium freedom (documented patterns with options): Use when a preferred pattern exists but some variation is acceptable. Example: "Creating PDFs with Typst" — follow the basic template but customize styling.
Low freedom (specific procedures, few choices): Use when operations are fragile and error-prone, consistency is critical, or a specific sequence must be followed. Example: "Setting up encrypted credentials" — must follow exact steps.
Think of it as a path: a narrow bridge with cliffs needs specific guardrails (low freedom, detailed steps), while an open field allows many routes (high freedom, general principles).
Structure: Know What Goes Where
Riglets have different components for different purposes:
SKILL.md - Primary workflows and procedures
- What: Core knowledge agents load first
- When: Procedures, common workflows, decision trees
- Length: ~100-150 lines ideally
- Load cost: Loaded for every interaction
references/ - Deep knowledge, advanced topics
- What: Advanced patterns, troubleshooting, detailed specifications
- When: Complex scenarios, edge cases, detailed reference material
- Length: 50-200 lines each, with TOC if >100
- Load cost: Only loaded when agent determines it's needed
tools in Nix - Executable packages
- What: CLI tools, compilers, interpreters needed by the riglet
- When: When the riglet teaches workflows that use specific tools
- Load cost: Built into rig environment, always available
Keep information in one place: SKILL.md or references, not both. Prefer references for detailed material unless it's core to the riglet—this keeps SKILL.md lean and makes information discoverable without hogging context.
Understanding the Riglet with Concrete Examples
Skip this step only when the riglet's patterns are already clearly understood.
Before writing a riglet, deeply understand what it will teach. Concrete examples drive effective documentation.
To create an effective riglet, clarify the scope with concrete examples:
- "What workflows does this riglet enable?"
- "What are realistic use cases?"
- "What problems does it solve?"
- "What would agents ask for that this riglet answers?"
For example, when building a riglet about version control with JJ:
- What functionality should it cover? (Creating changes, managing history, collaboration?)
- Can you give concrete examples? ("I need to reorganize my commits" or "I'm collaborating with git users")
- What would an agent say that should trigger this riglet?
To avoid overwhelming agents later, ask progressively—start with the most important questions. Conclude when the riglet's scope is clear and you have concrete examples.
Planning the Reusable Documentation Contents
Transform concrete examples into effective documentation by analyzing what knowledge is needed.
For each concrete example/workflow:
- What knowledge is needed to execute it? (procedures, patterns, concepts)
- What details are essential vs. advanced? (core flow vs. edge cases)
- What reference materials would help? (checklists, templates, troubleshooting)
Example: For a JJ riglet handling "reorganizing commits":
- Agents need to understand: revsets, rebasing, interactive rebase workflows
- Essential: Basic rebase commands; Advanced: complex revset patterns
- Reference materials: Revset syntax guide, troubleshooting merge conflicts
Example: For a PDF riglet handling "extracting tables from PDFs":
- Agents need: Understanding of PDF structure, table detection, format conversion
- Essential: Simple table extraction; Advanced: handling complex nested tables
- Reference materials: Format specifications, edge cases, tool limitations
Example: For a Typst riglet handling "generating documents":
- Agents need: Typst syntax, layout patterns, styling fundamentals
- Essential: Basic template structure; Advanced: custom layouts and functions
- Tools needed:
typstcompiler,pandocfor format conversion - Configuration: Templates for common document types
- Reference materials: Syntax reference, styling guide, troubleshooting layout issues
From this analysis, create a list of:
- Main sections for SKILL.md (primary workflows)
- Reference files needed (advanced patterns, troubleshooting, checklists)
- Tools to include (what agents will need to execute workflows)
- Configuration (templates, pre-configured settings)
Writing Effective SKILL.md
SKILL.md is the core knowledge. Write for agent efficiency:
Content Organization
Start with overview:
# My Riglet
This riglet teaches [what it covers].
Primary use cases:
- Use case 1
- Use case 2
- Use case 3
See references/advanced.md for deeper patterns.
Remain concise in this section, DO NOT duplicate info that is already in the meta.description and meta.whenToUse.
For documentation patterns, see patterns.md.
Documentation Patterns
For proven patterns to organize riglet documentation, see patterns.md. It covers:
- Sequential workflows
- Domain-specific organization
- Conditional details with progressive disclosure
- Troubleshooting-driven structures
- Converting Skills to riglets
Writing Guidelines
Avoid deeply nested references - Keep reference links one level deep. All reference files should link directly from SKILL.md, not from other references.
Use imperative/infinitive form:
- Good: "Use jj to manage changes"
- Avoid: "This riglet manages changes" or "JJ is a version control system"
Avoid using bold text as pseudo section headers:
You can go up to level 4 headers (####). The Rig manifest may show a table of contents of the riglets' SKILL.md files, and it detects headers starting at level 2 (##).
Therefore, structuring with proper Markdown headers helps making this table of contents meaningful and evocative of what the SKILL.md will contain.
For the same reason, do not go deeper than level 4, this would make the ToC more cluttered that it needs to.
Include concrete examples:
Bad: You can create commits with jj.
Good: To create a new commit:
jj new -m "Add feature X"
Show expected output when relevant:
$ jj log
@ ckd6n8pf 2025-12-15 alice (empty) Add feature X
○ xzrxt9al 2025-12-15 alice Add docs
Link to references when context is available:
For complex scenarios, see [patterns.md](references/patterns.md) or [metadata-guide.md](references/metadata-guide.md).
Don't link proactively—mention references only when the agent is in a situation where they'd be relevant.
Avoid overwhelming context - Keep SKILL.md to ~100 lines. Extended explanations belong in reference files.
Use relative paths for references - All paths are relative to the file mentioning them: [patterns.md](references/patterns.md)
What Goes Where: SKILL.md vs References
Keep in SKILL.md:
- Primary workflows and procedures agents will use most
- Common decision trees ("If X, then do Y")
- Essential concepts agents need to understand the workflows
- Links to reference files (but not the detailed content itself)
Move to references:
- Advanced patterns and edge cases
- Detailed specifications and schemas
- Troubleshooting guides
- Code examples longer than 10 lines
- Domain knowledge only needed for specific scenarios
- Detailed API or command documentation
Rule of thumb: Information should live in SKILL.md OR references, not both. Information repetition wastes token budget.
When you find yourself writing "For more details, see..." you've found something that belongs in a reference file.
Organizing Reference Files
Reference files provide depth without bloating SKILL.md.
Design Principle: One Level Deep
Keep all references one level deep from SKILL.md. References should not link to other references.
Good:
SKILL.md → references/advanced.md
SKILL.md → references/troubleshooting.md
Avoid:
SKILL.md → references/patterns.md → references/patterns-detailed.md
Why? Agents need to understand the full scope of what's available. If references link to other references, the structure becomes opaque and agents might miss information.
Structure Longer References
For reference files longer than ~100 lines, include a table of contents so agents can see the full scope when previewing:
# Advanced JJ Patterns
## Table of Contents
- Revset Syntax (line 10)
- Interactive Rebase (line 45)
- Conflict Resolution (line 80)
- Undoing Changes (line 120)
## Revset Syntax
...
This lets agents understand the file's full scope without reading all of it, helping them decide if they need to load it.
Naming conventions
Use clear, specific names:
advanced.md- Advanced patterns in the main topictroubleshooting.md- Common problems and solutionschecklists.md- Reusable checklistsdomain-name.md- Domain-specific knowledge (for multi-domain riglets)syntax-reference.md- Detailed syntax specifications
Packaging Custom Tools or Scripts with Riglets
Operations that are expected to be commonly performed when using the riglet can and probably SHOULD be provided as helper scripts.
It's Nix, so tools can be created on the fly and properly packaged with the usual builders like writeShellScriptBin, writeShellApplication or even stdenv.mkDerivation, but riglets have a simple option for simple cases.
Simple cases: write local scripts and list paths in tools
The tools field supports direct file paths to scripts, which are automatically wrapped as executable packages:
How it works:
- Script paths (e.g.,
./scripts/helper[.sh]) are detected and wrapped usingwriteShellScriptBin - Final executable name is derived from filename (with extension if it has any, so prefer without extensions)
- Scripts become available in the rig's
bin/directory alongside other tools
This is intended ONLY for SIMPLE sh or bash scripts which have NO DEPENDENCIES besides what is already listed in tools (as they will be together in $PATH once the rig is built).
Example directory-based riglet with scripts:
_:
{ pkgs, riglib, ... }: {
config.riglets.my-riglet = {
tools = [
pkgs.jujutsu
./scripts/jj-desc-read # → executable "jj-desc-read"
./scripts/jj-desc-edit # → executable "jj-desc-edit"
];
docs = riglib.writeFileTree {
"SKILL.md" = ''
# My Riglet
## Utility Scripts
**Read a revision:**
```bash
jj-desc-read @
```
**Edit description programmatically:**
```bash
jj-desc-edit sed 's/foo/bar/g'
```
'';
};
meta = {
name = "My Riglet";
description = "JJ utilities with helper scripts";
# ... other metadata
};
};
}
Directory structure:
riglets/my-riglet/
├── default.nix
└── scripts/
├── jj-desc-read
└── jj-desc-edit
Advanced cases: make a custom tool via a custom derivation
For cases when you need more control over the packaging of the tools, consider the usual Nix builders from nixpkgs.
writeShellApplication e.g. can package an inlined script with its dependencies:
writeShellApplication {
name = "show-nixos-org";
runtimeInputs = [
curl
w3m
];
text = ''
curl -s 'https://nixos.org' | w3m -dump -T text/html
'';
}
For instance, if you want to include a Python script to the riglet, package it properly with buildPythonApplication so ALL its dependencies are present.
Language-specific packaging guides
See the references directory for detailed guides on packaging tools in specific languages:
- Python -
buildPythonApplicationand modernpyproject.tomlsupport - Node.js/JavaScript -
buildNpmPackagefor npm-based projects - Rust -
buildRustPackagewithcargoHashorCargo.lock - Go -
buildGoModulewithvendorHash - Haskell -
haskellPackages.developPackageandcallCabal2nix - Ruby -
bundlerAppandbundlerEnvfor gems - Java/Kotlin -
buildMavenPackageand Gradle approaches
About external package-managers (uv, npm...)
If the riglet assumes that Python scripting will have to be done manually as part of executing the riglet's instructions, then prefer relying on uvx (provided through tools = [ pkgs.uv ... ]) and including usage instructions in the riglet's docs. Same goes for JS/TS with npx, etc.
But in such case DO:
- include a proper
pyproject.toml/package.json/etc. as an asset file (<riglet-folder>/assets/<foo>/pyproject.toml) - refer to it in the main riglet's doc
- MAKE SURE it is packaged via the
docsof the riglet (either as part of a path to a folder, or as an arg toriglib.writeFileTree)
The GOLDEN RULE is: users of a riglet must NEVER have to install ANYTHING globally on their system to use this riglet!!.
This is why use of uvx, npx, etc (i.e. anything installing packages in a project-scoped fashion) is tolerated, but pip install IS NOT.
However whenever you can, proper packaging of ALL dependencies, packages etc. through Nix is always preferable to enable easy one-command installation of the whole rig.
The Riglet Creation Process
Putting it all together:
Understand with concrete examples (5-10 min)
- What workflows? What problems? What would agents ask for?
Plan the documentation structure (5-10 min)
- Which sections for SKILL.md?
- Which topics need reference files?
- Any assets or templates?
Write SKILL.md with primary workflows (20-30 min)
- Overview
- 3-5 core workflows with concrete examples
- Links to reference files
Write reference files for advanced topics (10-20 min per reference)
- Advanced patterns
- Troubleshooting
- Detailed specifications
Test with real tasks (10+ min)
- Use the riglet for actual work
- Notice gaps or confusion
- Update SKILL.md or references
Iterate based on usage
- Clarify confusing sections
- Add missing workflows
- Reorganize if structure isn't working
Quality Checklist
Before considering documentation complete:
- SKILL.md exists and covers primary workflows
- Concrete examples throughout (commands, output, use cases)
- No jargon without explanation - define domain terms
- Links to references mentioned naturally (not exhaustively)
- Reference files structured with TOC if >100 lines
- Relative paths all correct (tested from the docs directory)
- No unreferenced tools - everything mentioned has a link or exists in the rig
- Tested in practice - actually used for real workflows
Files (rigup.nix)
-
references
-
metadata-guide.md 2 KB
# Documentation Quality Checklist Before publishing a riglet's documentation: ## Content Coverage - [ ] **SKILL.md exists** with clear overview - [ ] **Primary workflows documented** (3-5 core use cases) - [ ] **Concrete examples throughout** - actual commands and output - [ ] **No unexplained jargon** - domain terms are defined or linked - [ ] **Links to references natural** (not exhaustive listing) ## Organization & Structure - [ ] **SKILL.md is concise** (~100-150 lines max) - [ ] **Complex topics in references** (not in SKILL.md) - [ ] **Reference files have TOC** if longer than 100 lines - [ ] **Clear file names** (advanced.md, troubleshooting.md, etc.) - [ ] **One level deep references** - all links from SKILL.md, not between references ## Writing Quality - [ ] **Imperative/infinitive form** ("Use tool X" not "This riglet uses") - [ ] **Step-by-step when procedural** (numbered lists with expected output) - [ ] **Examples show real output** where helpful - [ ] **Tool warnings/limitations mentioned** if relevant - [ ] **Related workflows cross-linked** (e.g., "For bulk ops, see...") ## Technical Accuracy - [ ] **No tool errors in examples** (actually tested) - [ ] **All mentioned tools exist in the rig** (in `tools = [ ]`) - [ ] **All reference links valid** (files exist, paths relative) - [ ] **Configuration examples correct** (if any provided) ## Reference Design - [ ] **Troubleshooting reference** (if users commonly hit problems) - [ ] **Advanced patterns reference** (if basics + advanced split makes sense) - [ ] **Checklists/templates** (if helpful for the workflow) - [ ] **Each reference focuses** on one topic (not kitchen-sink) ## Before Declaring Complete Test the riglet in a real rig: ```bash # Add to rigup.toml [rigs.default.riglets] self = ["my-riglet"] # Build nix build .#rigs.x86_64-linux.default.home # Read documentation cat result/docs/my-riglet/SKILL.md cat result/docs/my-riglet/references/*.md # Try workflows from SKILL.md ``` Ask: "If I were an agent, would I understand how to do the workflows described?" -
packaging-go.md 2.9 KB
# Packaging Go Tools with Nix Quick reference for packaging Go applications as Nix derivations. ## Basic Application Packaging: buildGoModule Standard approach for Go modules (most common in 2025): ```nix { lib, buildGoModule, fetchFromGitHub }: buildGoModule rec { pname = "my-go-tool"; version = "1.0.0"; src = fetchFromGitHub { owner = "example"; repo = "my-tool"; rev = "v${version}"; hash = "sha256-..."; }; # Hash of vendored Go dependencies vendorHash = "sha256-..."; meta = with lib; { description = "My Go tool"; homepage = "https://example.com"; license = licenses.mit; mainProgram = "my-tool"; }; } ``` ## Getting the vendorHash To obtain the vendor hash, use a fake hash: ```nix vendorHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; ``` Build the package and Nix will report the correct hash. Alternatively, use: ```nix vendorHash = lib.fakeHash; ``` ## Using Vendored Dependencies If your project already vendors dependencies (has a `vendor/` directory), skip fetching: ```nix buildGoModule { pname = "my-tool"; version = "1.0.0"; src = ./.; # Use existing vendor directory vendorHash = null; } ``` ## Two-Phase Build Process `buildGoModule` works in two phases: 1. **Fetcher derivation**: Downloads and vendors all Go module dependencies (produces the `vendorHash`) 2. **Final derivation**: Builds the binary using the vendored dependencies This ensures reproducibility by locking all transitive dependencies. ## Local Go Projects For Go tools included in your riglet: ```nix { pkgs, ... }: { config.riglets.my-riglet = { tools = [ (pkgs.buildGoModule { pname = "my-local-tool"; version = "0.1.0"; src = ./scripts/my-tool; # Contains go.mod vendorHash = "sha256-..."; }) ]; }; } ``` ## Specifying Go Version Different Go versions are available: ```nix buildGoModule.override { go = pkgs.go_1_22; } ``` Common versions: `go` (latest stable), `go_1_22`, `go_1_21`, etc. ## Building Without go.mod For older projects not using modules, use `buildGoPackage` (deprecated but still available): ```nix buildGoPackage { pname = "old-tool"; goPackagePath = "github.com/example/old-tool"; # ... } ``` However, `buildGoModule` is strongly preferred for all new projects. ## Alternative: gomod2nix For more control over dependency management: ```bash # Generate nix expressions from go.mod gomod2nix ``` This creates `gomod2nix.toml` which can be used instead of `vendorHash`. ## Further Reading - **Official NixOS Wiki - Go**: https://nixos.wiki/wiki/Go - **nixpkgs Go documentation**: https://ryantm.github.io/nixpkgs/languages-frameworks/go/ - **buildGoModule source**: https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/go/module.nix - **Packaging a Go app tutorial**: https://blog.ktz.me/packaging-a-go-app-for-nixos/ - **gomod2nix announcement**: https://www.tweag.io/blog/2021-03-04-gomod2nix/ -
packaging-haskell.md 3.3 KB
# Packaging Haskell Tools with Nix Quick reference for packaging Haskell applications as Nix derivations. ## Basic Concepts **haskellPackages**: A large set containing Haskell packages from Hackage and Stackage. It's a synonym for `haskell.packages.ghcXYZ` where XYZ is the current default GHC version. **Version selection**: - Stackage packages: Use versions from current Stackage LTS snapshot - Other packages: Use latest version from Hackage ## Simple Development Shell For quick Haskell development in a riglet: ```nix { pkgs, ... }: pkgs.mkShell { packages = with pkgs.haskellPackages; [ (ghcWithPackages (hpkgs: with hpkgs; [ aeson text bytestring ])) cabal-install ]; } ``` ## Using developPackage For projects with a `.cabal` file, use `developPackage`: ```nix { pkgs, ... }: { config.riglets.my-riglet = { tools = [ (pkgs.haskellPackages.developPackage { root = ./scripts/my-tool; # Directory containing .cabal file name = "my-tool"; }) ]; }; } ``` `developPackage` is a wrapper around `callCabal2nixWithOptions` that automatically converts a Cabal file to a Nix expression. ## Manual Package Definition For more control, define a Haskell package manually: ```nix { lib, haskellPackages, fetchFromGitHub }: haskellPackages.mkDerivation { pname = "my-haskell-tool"; version = "1.0.0"; src = fetchFromGitHub { owner = "example"; repo = "my-tool"; rev = "v1.0.0"; hash = "sha256-..."; }; libraryHaskellDepends = with haskellPackages; [ aeson text ]; executableHaskellDepends = with haskellPackages; [ optparse-applicative ]; license = lib.licenses.mit; } ``` ## Using callCabal2nix Convert a Cabal file to Nix expression on-the-fly: ```nix { haskellPackages }: haskellPackages.callCabal2nix "my-tool" ./path/to/cabal/project { } ``` The third argument is for overriding dependencies if needed. ## Specifying GHC Version Use a specific GHC version: ```nix { pkgs }: pkgs.haskell.packages.ghc965.developPackage { root = ./.; } ``` Available: `ghc98`, `ghc965`, `ghc947`, `ghc928`, etc. ## Known Limitations (2025) - About 50% of packages in `haskellPackages` are marked as broken (deprecated/unmaintained) - GHCJS support removed; use `pkgsCross.ghcjs` instead - GHC versions with integer-simple removed (as of Sept 2025) ## Quick Tool Packaging Example Packaging a Haskell CLI tool in a riglet: ```nix _: { pkgs, riglib, ... }: { config.riglets.my-riglet = { tools = [ (pkgs.haskellPackages.callCabal2nix "my-tool" ./scripts/my-tool { }) pkgs.haskellPackages.cabal-install ]; docs = riglib.writeFileTree { "SKILL.md" = '' # My Riglet Use `my-tool` for... ''; }; meta = { name = "My Haskell Riglet"; description = "Provides my-tool for X"; }; }; } ``` ## Further Reading - **Official NixOS Wiki - Haskell**: https://wiki.nixos.org/wiki/Haskell - **nixpkgs Haskell documentation**: https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/haskell.section.md - **Haskell package user's guide**: https://haskell4nix.readthedocs.io/nixpkgs-users-guide.html - **Incremental packaging guide**: https://www.haskellforall.com/2022/08/incrementally-package-haskell-program.html - **Gabriella439's Haskell-Nix guide**: https://github.com/Gabriella439/haskell-nix -
packaging-java-kotlin.md 4.3 KB
# Packaging Java/Kotlin Tools with Nix Quick reference for packaging Java and Kotlin applications as Nix derivations. ## Maven Projects: buildMavenPackage For Maven-based projects (works for Java, Kotlin, Scala, and other JVM languages): ```nix { lib, maven, fetchFromGitHub }: maven.buildMavenPackage rec { pname = "my-java-tool"; version = "1.0.0"; src = fetchFromGitHub { owner = "example"; repo = "my-tool"; rev = "v${version}"; hash = "sha256-..."; }; # Hash of Maven dependencies mvnHash = "sha256-..."; # Optional: specify which artifact to install installPhase = '' runHook preInstall install -Dm644 target/my-tool-${version}.jar $out/share/java/my-tool.jar runHook postInstall ''; meta = with lib; { description = "My Java/Kotlin tool"; homepage = "https://example.com"; license = licenses.asl20; }; } ``` ## Getting the mvnHash Use a fake hash initially: ```nix mvnHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; ``` Build and Nix will provide the correct hash. ## Standard Installation After building, `buildMavenPackage` automatically: - Saves `.jar` to `$out/share/java` - Creates a wrapper script for execution (if there's a main class) ## Gradle Projects **Status (2025)**: Gradle support is improving but remains challenging compared to Maven. For Gradle projects, consider these approaches: ### 1. Pre-built Binary Wrapping Package the pre-built JAR/binary with proper Java runtime: ```nix { lib, stdenv, makeWrapper, jre, fetchurl }: stdenv.mkDerivation rec { pname = "my-kotlin-tool"; version = "1.0.0"; src = fetchurl { url = "https://example.com/releases/my-tool-${version}.jar"; hash = "sha256-..."; }; nativeBuildInputs = [ makeWrapper ]; dontUnpack = true; installPhase = '' runHook preInstall mkdir -p $out/share/java cp $src $out/share/java/my-tool.jar mkdir -p $out/bin makeWrapper ${jre}/bin/java $out/bin/my-tool \ --add-flags "-jar $out/share/java/my-tool.jar" runHook postInstall ''; meta = with lib; { description = "My Kotlin tool"; license = licenses.mit; mainProgram = "my-tool"; }; } ``` ### 2. Manual Gradle Build For simpler Gradle projects, build manually: ```nix { lib, stdenv, gradle, jdk, makeWrapper }: stdenv.mkDerivation { pname = "my-gradle-app"; version = "1.0.0"; src = ./.; nativeBuildInputs = [ gradle jdk makeWrapper ]; buildPhase = '' gradle build --no-daemon ''; installPhase = '' mkdir -p $out/share/java $out/bin cp build/libs/*.jar $out/share/java/ makeWrapper ${jdk}/bin/java $out/bin/my-app \ --add-flags "-jar $out/share/java/my-app.jar" ''; } ``` **Note**: This approach isn't fully reproducible as Gradle may download dependencies at build time. ## Using makeWrapper for JAVA_HOME When packaging Java/Kotlin tools, use `makeWrapper` to set `JAVA_HOME`: ```nix makeWrapper ${jre}/bin/java $out/bin/my-tool \ --set JAVA_HOME ${jre} \ --add-flags "-jar $out/share/java/my-tool.jar" ``` This ensures the correct Java version without requiring `patchelf` or FHS environments. ## Java Versions Specify Java version by choosing the appropriate JDK/JRE: ```nix buildMavenPackage.override { jdk = pkgs.jdk21; } ``` Available: `jdk` (latest LTS), `jdk21`, `jdk17`, `jdk11`, `jre`, etc. ## Kotlin-Specific Considerations Kotlin projects work the same as Java: - **Maven**: Use `buildMavenPackage` (recommended) - **Gradle**: Pre-built binary wrapping or manual build Kotlin Language Server example (2025): Packaged using pre-built binary approach with `makeWrapper`. ## Alternative: mvn2nix For complex Maven projects: ```bash # Generate Nix expression from pom.xml mvn2nix ``` This can help handle complex dependency trees. ## Further Reading - **nixpkgs Maven documentation**: https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/maven.section.md - **Maven language guide**: https://ryantm.github.io/nixpkgs/languages-frameworks/maven/ - **Packaging Kotlin LSP (2025)**: https://britter.dev/blog/2025/11/15/kotlin-lsp-nixvim/ - **NixOS + Enterprise Java (2025)**: https://britter.dev/blog/2025/02/27/nix-java-enterprise/ - **Packaging Gradle software**: https://rafael.ovh/posts/packaging-gradle-software-with-nix/ - **mvn2nix tool**: https://discourse.nixos.org/t/mvn2nix-packaging-maven-application-made-easy/8751 -
packaging-nodejs.md 2.8 KB
# Packaging Node.js/JavaScript Tools with Nix Quick reference for packaging Node.js applications and npm packages as Nix derivations. ## Basic Application Packaging: buildNpmPackage The modern approach for npm-based projects (2025): ```nix { lib, buildNpmPackage, fetchFromGitHub }: buildNpmPackage rec { pname = "my-node-tool"; version = "1.0.0"; src = fetchFromGitHub { owner = "example"; repo = "my-tool"; rev = "v${version}"; hash = "sha256-..."; }; # Hash of npm dependencies cache npmDepsHash = "sha256-..."; # Optional: run custom build script npmBuildScript = "build"; meta = with lib; { description = "My Node.js tool"; homepage = "https://example.com"; license = licenses.mit; mainProgram = "my-tool"; }; } ``` ## Getting the npmDepsHash To obtain the hash, use a fake hash initially: ```nix npmDepsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; ``` Build the package and Nix will report the correct hash in the error message. Replace with the correct hash. ## Key Points **Modern approach**: `buildNpmPackage` creates a reproducible npm cache of dependencies without requiring auto-generated lock files. **npm vs yarn vs pnpm**: - For npm projects: use `buildNpmPackage` (recommended) - For yarn projects: consider `yarn2nix` or `buildNpmPackage` with yarn support - For pnpm projects: experimental support available **Build scripts**: Specify custom build script with `npmBuildScript = "build"` (defaults to "build" if it exists in package.json). ## Local Project Packaging For a local Node.js project in your riglet: ```nix { pkgs, ... }: { config.riglets.my-riglet = { tools = [ (pkgs.buildNpmPackage { pname = "my-local-tool"; version = "0.1.0"; src = ./scripts/my-tool; # Contains package.json npmDepsHash = "sha256-..."; }) ]; }; } ``` ## Alternative: node2nix For projects requiring more control, `node2nix` generates Nix expressions from `package.json`: ```bash # Generate nix expressions node2nix -i package.json # This creates node-packages.nix, node-env.nix, default.nix ``` Then reference the generated `default.nix` in your riglet. ## Node.js Versions Multiple Node.js versions available in nixpkgs: - `nodejs`: Latest LTS (alias) - `nodejs_22`: Node.js 22.x - `nodejs_20`: Node.js 20.x Specify version explicitly if needed: ```nix buildNpmPackage.override { nodejs = pkgs.nodejs_20; } ``` ## Further Reading - **Official NixOS Wiki - Node.js**: https://wiki.nixos.org/w/index.php?title=Node.js - **nixpkgs JavaScript documentation**: https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/javascript.section.md - **node2nix repository**: https://github.com/svanderburg/node2nix - **Managing Node.js on NixOS guide**: https://medium.com/thelinux/managing-node-js-versions-on-nixos-a-comprehensive-guide-0b452e194a1b -
packaging-python.md 2.7 KB
# Packaging Python Tools with Nix Quick reference for packaging Python applications and scripts as Nix derivations. ## Basic Application Packaging: buildPythonApplication For standalone Python applications (not libraries), use `buildPythonApplication`: ```nix { lib, python3, fetchPypi }: python3.pkgs.buildPythonApplication rec { pname = "my-tool"; version = "1.0.0"; # Modern pyproject.toml-based projects pyproject = true; src = fetchPypi { inherit pname version; hash = "sha256-..."; }; # Runtime dependencies propagatedBuildInputs = with python3.pkgs; [ requests click ]; # Build-time dependencies (for pyproject builds) build-system = with python3.pkgs; [ setuptools wheel ]; meta = with lib; { description = "My Python tool"; homepage = "https://example.com"; license = licenses.mit; }; } ``` ## Key Points **Applications vs Libraries**: `buildPythonApplication` is for end-user tools. Use `buildPythonPackage` for libraries that will be dependencies of other Python packages. **Modern build systems (2025)**: Set `pyproject = true` for projects using `pyproject.toml`. Specify the build backend in `build-system` (commonly `setuptools`, `hatchling`, `poetry-core`, or `flit-core`). **Legacy projects**: For older `setup.py`-based projects, use `format = "setuptools"` instead of `pyproject = true`. **Dependencies**: - `propagatedBuildInputs`: Runtime Python dependencies - `build-system`: Build tools (setuptools, wheel, etc.) - `nativeBuildInputs`: Build-time non-Python tools ## Local Scripts For simple local scripts included in a riglet: ```nix { pkgs, python3, ... }: let myScript = python3.pkgs.buildPythonApplication { pname = "my-script"; version = "0.1.0"; pyproject = true; src = ./scripts/my-script; # Directory with pyproject.toml propagatedBuildInputs = with python3.pkgs; [ requests ]; build-system = with python3.pkgs; [ setuptools ]; }; in { config.riglets.my-riglet = { tools = [ myScript ]; }; } ``` ## Helper Tools **nix-init**: Automatically generate package expressions for Python projects. Prefetches sources, parses dependencies, and fills in most metadata. ## Further Reading - **Official nixpkgs Python documentation**: https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/python.section.md - **NixOS Wiki - Packaging/Python**: https://wiki.nixos.org/wiki/Packaging/Python - **Python language guide**: https://ryantm.github.io/nixpkgs/languages-frameworks/python/ - **Tutorial - Using and creating Python packages**: https://fridh.github.io/nix-tutorials/tutorials/02-python/01-using-and-creating-python-packages.html -
packaging-ruby.md 3.3 KB
# Packaging Ruby Tools with Nix Quick reference for packaging Ruby applications and gems as Nix derivations. ## Basic Application Packaging: bundlerApp For Ruby executables intended as standalone tools, use `bundlerApp`: ```nix { bundlerApp }: bundlerApp { pname = "my-ruby-tool"; gemdir = ./.; # Directory with Gemfile, Gemfile.lock, gemset.nix exes = [ "my-tool" ]; # List of executables to expose } ``` `bundlerApp` creates a package that only exposes the listed executables, avoiding conflicts from common paths like `bin/rake` or `bin/bundler`. ## Using bundlerEnv For development environments or when you need all gems available: ```nix { bundlerEnv, ruby }: let gems = bundlerEnv { name = "my-project-gems"; gemdir = ./.; }; in mkShell { packages = [ gems gems.wrappedRuby ]; } ``` `bundlerEnv` is a wrapper over all gems in your gemset, making all `/lib` and `/bin` directories available. **Note**: By default, only the `default` group is included. To include other groups: ```nix bundlerEnv { name = "my-gems"; gemdir = ./.; groups = [ "default" "development" "test" ]; } ``` ## Generating gemset.nix with bundix Ruby packaging in Nix requires a `gemset.nix` file generated from your `Gemfile.lock`: ```bash # Install bundix nix-shell -p bundix # Generate gemset.nix bundix ``` This creates `gemset.nix` alongside your `Gemfile` and `Gemfile.lock`. ## Directory Structure Your Ruby project directory should contain: ``` my-ruby-tool/ ├── Gemfile ├── Gemfile.lock ├── gemset.nix # Generated by bundix └── my-tool.rb # or bin/my-tool ``` ## Local Ruby Tool in a Riglet Example of packaging a local Ruby script: ```nix _: { pkgs, riglib, ... }: { config.riglets.my-riglet = { tools = [ (pkgs.bundlerApp { pname = "my-tool"; gemdir = ./scripts/my-tool; exes = [ "my-tool" ]; }) ]; docs = riglib.writeFileTree { "SKILL.md" = '' # My Ruby Riglet Use `my-tool` to... ''; }; meta = { name = "My Ruby Riglet"; description = "Provides my-tool for X"; }; }; } ``` ## Packaging Individual Gems For packaging a single gem (less common in riglets): ```nix { lib, bundlerApp, fetchFromGitHub }: bundlerApp { pname = "jekyll"; gemdir = ./.; exes = [ "jekyll" ]; } ``` ## Alternative: ruby-nix For modern reproducible Ruby environments, consider `ruby-nix`: ```bash # Generate nix files from Gemfile.lock nix run github:inscapist/ruby-nix -- lock ``` This generates `.nix-ruby` directory with all necessary Nix files. ## Ruby Versions Specify Ruby version by using different Ruby packages: ```nix bundlerApp.override { ruby = pkgs.ruby_3_3; } ``` Available: `ruby` (default), `ruby_3_3`, `ruby_3_2`, etc. ## Further Reading - **Official nixpkgs Ruby documentation**: https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/ruby.section.md - **Ruby language guide**: https://ryantm.github.io/nixpkgs/languages-frameworks/ruby/ - **NixOS Wiki - Packaging/Ruby**: https://nixos.wiki/wiki/Packaging/Ruby - **bundix repository**: https://github.com/nix-community/bundix - **ruby-nix (modern approach)**: https://github.com/inscapist/ruby-nix - **Ruby development guide**: https://jamesmead.org/blog/2020-07-26-a-simple-ruby-development-environment-using-nix-shell -
packaging-rust.md 2.9 KB
# Packaging Rust Tools with Nix Quick reference for packaging Rust applications as Nix derivations. ## Basic Application Packaging: buildRustPackage Standard approach using `rustPlatform.buildRustPackage`: ```nix { lib, rustPlatform, fetchFromGitHub }: rustPlatform.buildRustPackage rec { pname = "my-rust-tool"; version = "1.0.0"; src = fetchFromGitHub { owner = "example"; repo = "my-tool"; rev = "v${version}"; hash = "sha256-..."; }; # Hash of all Cargo dependencies cargoHash = "sha256-..."; meta = with lib; { description = "My Rust tool"; homepage = "https://example.com"; license = licenses.mit; mainProgram = "my-tool"; }; } ``` ## Getting the cargoHash Use a fake hash initially: ```nix cargoHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; ``` Build the package and Nix will provide the correct hash. Replace with it. ## Alternative: Using Cargo.lock Directly Simpler approach when you have `Cargo.lock`: ```nix { lib, rustPlatform }: rustPlatform.buildRustPackage { pname = "my-tool"; version = "0.1.0"; src = lib.cleanSource ./.; # Reference Cargo.lock directly cargoLock.lockFile = ./Cargo.lock; meta = with lib; { description = "My Rust tool"; license = licenses.mit; }; } ``` This is often simpler for local projects where you already have a committed `Cargo.lock`. ## Local Rust Projects For Rust tools included in your riglet: ```nix { pkgs, system, ... }: { config.riglets.my-riglet = { tools = [ (pkgs.rustPlatform.buildRustPackage { pname = "my-local-tool"; version = "0.1.0"; src = ./scripts/my-tool; # Contains Cargo.toml and Cargo.lock cargoLock.lockFile = ./scripts/my-tool/Cargo.lock; }) ]; }; } ``` ## Advanced: Faster Builds with Alternative Tools For larger projects, these tools can provide faster incremental builds by separating dependencies from application code: - **crane**: Modern, composable Rust build system for Nix - **naersk**: Minimal, fast Rust builds - **crate2nix**: Generates Nix expressions from Cargo.toml Example with crane: ```nix { crane, system }: let craneLib = crane.mkLib pkgs; in craneLib.buildPackage { src = ./.; # Crane automatically handles Cargo.lock } ``` ## 2025 Development: devenv Integration Modern Rust development environments can use `devenv` with `languages.rust.import` for automatic packaging. ## Further Reading - **Official NixOS Wiki - Rust**: https://wiki.nixos.org/wiki/Rust - **nixpkgs Rust documentation**: https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/rust.section.md - **How to package a Rust app**: https://m7.rs/blog/2022-11-01-package-a-rust-app-with-nix/ - **devenv Rust guide (2025)**: https://devenv.sh/blog/2025/08/22/closing-the-nix-gap-from-environments-to-packaged-applications-for-rust/ - **Building from workspaces**: https://www.tweag.io/blog/2022-09-22-rust-nix/ -
patterns.md 2 KB
# Riglet Documentation Patterns Proven patterns for organizing riglet documentation effectively. ## Pattern 1: Sequential Workflow Use when the riglet teaches step-by-step procedures: ```markdown ## Workflow: Rotating PDFs 1. Load document: `pdftool load file.pdf` 2. Rotate pages: `pdftool rotate -a 90 file.pdf` 3. Save result: `pdftool save file.pdf` For bulk operations: See [batch-operations.md](references/batch-operations.md) ``` ## Pattern 2: Domain-Specific Organization Use when covering multiple domains (e.g., BigQuery finance vs. product metrics): ```markdown # BigQuery Riglet ## Overview Query BigQuery for metrics across different domains. ## Financial Metrics See [finance.md](references/finance.md) for: - Revenue calculations - Billing costs ## Product Metrics See [product.md](references/product.md) for: - Feature usage - API adoption ``` Agents only load the domain reference they need. ## Pattern 3: Conditional Details with Progressive Disclosure Use for tools/topics with basic and advanced usage: ```markdown ## Creating Documents Basic template for most cases: ```nix typst { title = "..."; } ``` **Advanced layouts**: See [layouts.md](references/layouts.md) **Custom styling**: See [styling.md](references/styling.md) **Performance**: See [performance.md](references/performance.md) ``` ## Pattern 4: Troubleshooting-Driven Organization Use when users commonly hit problems: ```markdown ## Common Workflows - Creating a change (simple case) - Rebasing changes ## Troubleshooting See [troubleshooting.md](references/troubleshooting.md) for: - "I accidentally deleted a change" - "Rebasing is creating conflicts" - "I need to undo multiple changes" ``` ## Pattern 5: Skill-to-Riglet Direct Port When converting an existing Agent Skill to a riglet: 1. Copy SKILL.md content verbatim (it's already well-written) 2. Move advanced sections to `references/` subdirectory 3. Update any skill-specific instructions (build scripts, etc.) 4. Keep the same organization and linking structure This is the lowest-friction conversion.
-
-
default.nix 1023 B · in bundle
-
SKILL.md 17.1 KB
# Riglet Creator Creating effective riglets means writing knowledge (SKILL.md) that agents will rely on. This guide focuses on how to write high-quality documentation for riglets, organized efficiently. For the structural/technical side of riglets (what goes in the Nix module, metadata fields, schema), see the riglet agent-rig-system's `SKILL.md` and `references/metadata-guide.md`. ## Core Principles ### Define the Main Intent Ask yourself: what is the end goal here? What should this riglet teach? The `intent` metadata is there to help you here. It should guide how you approach the writing of a riglet. As a reminder, the possible intents are: - base: "abstract" riglet (e.g. to define options) solely meant to be imported by others to factorize configuration. Cannot be disclosed in a manifest - sourcebook: compendium of knowledge, glossary, useful domain knowledge - toolbox: open-ended set of tools related together - cookbook: operational know-how, heuristics, tricks and techniques that are useful to apprehend an otherwise complex toolset or domain - playbook: specific procedure or workflow to follow in a rigorous manner A riglet should fall under **one** of these categories. If several apply, then it might be a better idea to split it into several. **Discuss that with your user.** Several riglets, each one with a clear focus, are better than one unorganized riglet that tries to cover everything without a real goal. Remember riglets can depend on each other via `imports`, so for example a very specialized "playbook" can depend on tools explained and documented in a more general "toolbox". ### Concise is Key Agents share context windows with conversation history, system instructions, and other riglets in the rig. Context is a shared resource. **Default assumption: Agents are already very capable.** Only include knowledge agents don't already have. Challenge each piece of information: "Does the agent really need this explanation?" and "Does this paragraph justify its token cost?" Prefer concrete examples over verbose explanations. Prefer links to references over embedding everything in SKILL.md. ### Set Appropriate Degrees of Freedom Match documentation specificity to the task's fragility and variability: **High freedom (general guidance)**: Use when multiple approaches are valid, decisions depend on context, or heuristics guide the process. Example: "Organizing commits in JJ" — many strategies work. **Medium freedom (documented patterns with options)**: Use when a preferred pattern exists but some variation is acceptable. Example: "Creating PDFs with Typst" — follow the basic template but customize styling. **Low freedom (specific procedures, few choices)**: Use when operations are fragile and error-prone, consistency is critical, or a specific sequence must be followed. Example: "Setting up encrypted credentials" — must follow exact steps. Think of it as a path: a narrow bridge with cliffs needs specific guardrails (low freedom, detailed steps), while an open field allows many routes (high freedom, general principles). ### Structure: Know What Goes Where Riglets have different components for different purposes: **SKILL.md** - Primary workflows and procedures - What: Core knowledge agents load first - When: Procedures, common workflows, decision trees - Length: ~100-150 lines ideally - Load cost: Loaded for every interaction **references/** - Deep knowledge, advanced topics - What: Advanced patterns, troubleshooting, detailed specifications - When: Complex scenarios, edge cases, detailed reference material - Length: 50-200 lines each, with TOC if >100 - Load cost: Only loaded when agent determines it's needed **tools in Nix** - Executable packages - What: CLI tools, compilers, interpreters needed by the riglet - When: When the riglet teaches workflows that use specific tools - Load cost: Built into rig environment, always available Keep information in one place: SKILL.md or references, not both. Prefer references for detailed material unless it's core to the riglet—this keeps SKILL.md lean and makes information discoverable without hogging context. ## Understanding the Riglet with Concrete Examples Skip this step only when the riglet's patterns are already clearly understood. Before writing a riglet, deeply understand what it will teach. Concrete examples drive effective documentation. To create an effective riglet, clarify the scope with concrete examples: - "What workflows does this riglet enable?" - "What are realistic use cases?" - "What problems does it solve?" - "What would agents ask for that this riglet answers?" For example, when building a riglet about version control with JJ: - What functionality should it cover? (Creating changes, managing history, collaboration?) - Can you give concrete examples? ("I need to reorganize my commits" or "I'm collaborating with git users") - What would an agent say that should trigger this riglet? To avoid overwhelming agents later, ask progressively—start with the most important questions. Conclude when the riglet's scope is clear and you have concrete examples. ## Planning the Reusable Documentation Contents Transform concrete examples into effective documentation by analyzing what knowledge is needed. For each concrete example/workflow: 1. **What knowledge is needed to execute it?** (procedures, patterns, concepts) 2. **What details are essential vs. advanced?** (core flow vs. edge cases) 3. **What reference materials would help?** (checklists, templates, troubleshooting) Example: For a JJ riglet handling "reorganizing commits": 1. Agents need to understand: revsets, rebasing, interactive rebase workflows 2. Essential: Basic rebase commands; Advanced: complex revset patterns 3. Reference materials: Revset syntax guide, troubleshooting merge conflicts Example: For a PDF riglet handling "extracting tables from PDFs": 1. Agents need: Understanding of PDF structure, table detection, format conversion 2. Essential: Simple table extraction; Advanced: handling complex nested tables 3. Reference materials: Format specifications, edge cases, tool limitations Example: For a Typst riglet handling "generating documents": 1. Agents need: Typst syntax, layout patterns, styling fundamentals 2. Essential: Basic template structure; Advanced: custom layouts and functions 3. Tools needed: `typst` compiler, `pandoc` for format conversion 4. Configuration: Templates for common document types 5. Reference materials: Syntax reference, styling guide, troubleshooting layout issues From this analysis, create a list of: - Main sections for SKILL.md (primary workflows) - Reference files needed (advanced patterns, troubleshooting, checklists) - **Tools to include** (what agents will need to execute workflows) - **Configuration** (templates, pre-configured settings) ## Writing Effective SKILL.md SKILL.md is the core knowledge. Write for agent efficiency: ### Content Organization Start with **overview**: ```markdown # My Riglet This riglet teaches [what it covers]. Primary use cases: - Use case 1 - Use case 2 - Use case 3 See references/advanced.md for deeper patterns. ``` Remain concise in this section, DO NOT duplicate info that is already in the `meta.description` and `meta.whenToUse`. For documentation patterns, see [patterns.md](references/patterns.md). ### Documentation Patterns For proven patterns to organize riglet documentation, see [patterns.md](references/patterns.md). It covers: - Sequential workflows - Domain-specific organization - Conditional details with progressive disclosure - Troubleshooting-driven structures - Converting Skills to riglets ### Writing Guidelines **Avoid deeply nested references** - Keep reference links one level deep. All reference files should link directly from SKILL.md, not from other references. **Use imperative/infinitive form**: - Good: "Use jj to manage changes" - Avoid: "This riglet manages changes" or "JJ is a version control system" **Avoid using bold text as pseudo section headers**: You can go up to level 4 headers (`####`). The Rig manifest may show a table of contents of the riglets' SKILL.md files, and it detects headers starting at level 2 (`##`). Therefore, structuring with proper Markdown headers helps making this table of contents meaningful and evocative of what the SKILL.md will contain. For the same reason, do not go deeper than level 4, this would make the ToC more cluttered that it needs to. **Include concrete examples**: ```markdown Bad: You can create commits with jj. Good: To create a new commit: jj new -m "Add feature X" ``` **Show expected output** when relevant: ```markdown $ jj log @ ckd6n8pf 2025-12-15 alice (empty) Add feature X ○ xzrxt9al 2025-12-15 alice Add docs ``` **Link to references when context is available**: ```markdown For complex scenarios, see [patterns.md](references/patterns.md) or [metadata-guide.md](references/metadata-guide.md). ``` Don't link proactively—mention references only when the agent is in a situation where they'd be relevant. **Avoid overwhelming context** - Keep SKILL.md to ~100 lines. Extended explanations belong in reference files. **Use relative paths for references** - All paths are relative to the file mentioning them: `[patterns.md](references/patterns.md)` ## What Goes Where: SKILL.md vs References **Keep in SKILL.md:** - Primary workflows and procedures agents will use most - Common decision trees ("If X, then do Y") - Essential concepts agents need to understand the workflows - Links to reference files (but not the detailed content itself) **Move to references:** - Advanced patterns and edge cases - Detailed specifications and schemas - Troubleshooting guides - Code examples longer than 10 lines - Domain knowledge only needed for specific scenarios - Detailed API or command documentation **Rule of thumb:** Information should live in SKILL.md OR references, not both. Information repetition wastes token budget. When you find yourself writing "For more details, see..." you've found something that belongs in a reference file. ## Organizing Reference Files Reference files provide depth without bloating SKILL.md. ### Design Principle: One Level Deep Keep all references one level deep from SKILL.md. References should not link to other references. Good: ``` SKILL.md → references/advanced.md SKILL.md → references/troubleshooting.md ``` Avoid: ``` SKILL.md → references/patterns.md → references/patterns-detailed.md ``` Why? Agents need to understand the full scope of what's available. If references link to other references, the structure becomes opaque and agents might miss information. ### Structure Longer References For reference files longer than ~100 lines, include a table of contents so agents can see the full scope when previewing: ```markdown # Advanced JJ Patterns ## Table of Contents - Revset Syntax (line 10) - Interactive Rebase (line 45) - Conflict Resolution (line 80) - Undoing Changes (line 120) ## Revset Syntax ... ``` This lets agents understand the file's full scope without reading all of it, helping them decide if they need to load it. ### Naming conventions Use clear, specific names: - `advanced.md` - Advanced patterns in the main topic - `troubleshooting.md` - Common problems and solutions - `checklists.md` - Reusable checklists - `domain-name.md` - Domain-specific knowledge (for multi-domain riglets) - `syntax-reference.md` - Detailed syntax specifications ## Packaging Custom Tools or Scripts with Riglets Operations that are expected to be commonly performed when using the riglet can and probably SHOULD be provided as helper scripts. It's Nix, so tools can be created on the fly and properly packaged with the usual builders like `writeShellScriptBin`, `writeShellApplication` or even `stdenv.mkDerivation`, but riglets have a simple option for simple cases. ### Simple cases: write local scripts and list paths in `tools` The `tools` field supports direct file paths to scripts, which are automatically wrapped as executable packages: **How it works:** - Script paths (e.g., `./scripts/helper[.sh]`) are detected and wrapped using `writeShellScriptBin` - Final executable name is derived from filename (with extension if it has any, so prefer without extensions) - Scripts become available in the rig's `bin/` directory alongside other tools **This is intended ONLY for SIMPLE sh or bash scripts which have NO DEPENDENCIES besides what is already listed in `tools`** (as they will be together in `$PATH` once the rig is built). **Example directory-based riglet with scripts:** ````nix _: { pkgs, riglib, ... }: { config.riglets.my-riglet = { tools = [ pkgs.jujutsu ./scripts/jj-desc-read # → executable "jj-desc-read" ./scripts/jj-desc-edit # → executable "jj-desc-edit" ]; docs = riglib.writeFileTree { "SKILL.md" = '' # My Riglet ## Utility Scripts **Read a revision:** ```bash jj-desc-read @ ``` **Edit description programmatically:** ```bash jj-desc-edit sed 's/foo/bar/g' ``` ''; }; meta = { name = "My Riglet"; description = "JJ utilities with helper scripts"; # ... other metadata }; }; } ```` **Directory structure:** ``` riglets/my-riglet/ ├── default.nix └── scripts/ ├── jj-desc-read └── jj-desc-edit ``` ### Advanced cases: make a custom tool via a custom derivation For cases when you need more control over the packaging of the tools, consider the usual Nix builders from nixpkgs. `writeShellApplication` e.g. can package an inlined script with its dependencies: ```nix writeShellApplication { name = "show-nixos-org"; runtimeInputs = [ curl w3m ]; text = '' curl -s 'https://nixos.org' | w3m -dump -T text/html ''; } ``` For instance, if you want to include a Python script to the riglet, package it properly with `buildPythonApplication` so ALL its dependencies are present. #### Language-specific packaging guides See the references directory for detailed guides on packaging tools in specific languages: - [Python](references/packaging-python.md) - `buildPythonApplication` and modern `pyproject.toml` support - [Node.js/JavaScript](references/packaging-nodejs.md) - `buildNpmPackage` for npm-based projects - [Rust](references/packaging-rust.md) - `buildRustPackage` with `cargoHash` or `Cargo.lock` - [Go](references/packaging-go.md) - `buildGoModule` with `vendorHash` - [Haskell](references/packaging-haskell.md) - `haskellPackages.developPackage` and `callCabal2nix` - [Ruby](references/packaging-ruby.md) - `bundlerApp` and `bundlerEnv` for gems - [Java/Kotlin](references/packaging-java-kotlin.md) - `buildMavenPackage` and Gradle approaches #### About external package-managers (uv, npm...) If the riglet assumes that Python scripting will have to be done **manually** as part of **executing the riglet's instructions**, then prefer relying on `uvx` (provided through `tools = [ pkgs.uv ... ]`) and including usage instructions in the riglet's docs. Same goes for JS/TS with `npx`, etc. **But** in such case DO: - include a proper `pyproject.toml`/`package.json`/etc. as an asset file (`<riglet-folder>/assets/<foo>/pyproject.toml`) - refer to it in the main riglet's doc - **MAKE SURE it is packaged via the `docs` of the riglet** (either as part of a path to a folder, or as an arg to `riglib.writeFileTree`) The GOLDEN RULE is: **users of a riglet must NEVER have to install ANYTHING globally on their system to use this riglet!!**. This is why use of `uvx`, `npx`, etc (i.e. anything installing packages in a **project-scoped** fashion) is tolerated, but `pip install` **IS NOT**. However **whenever you can**, proper packaging of ALL dependencies, packages etc. through Nix is **always** preferable to enable easy one-command installation of the whole rig. ## The Riglet Creation Process Putting it all together: 1. **Understand** with concrete examples (5-10 min) - What workflows? What problems? What would agents ask for? 2. **Plan** the documentation structure (5-10 min) - Which sections for SKILL.md? - Which topics need reference files? - Any assets or templates? 3. **Write SKILL.md** with primary workflows (20-30 min) - Overview - 3-5 core workflows with concrete examples - Links to reference files 4. **Write reference files** for advanced topics (10-20 min per reference) - Advanced patterns - Troubleshooting - Detailed specifications 5. **Test with real tasks** (10+ min) - Use the riglet for actual work - Notice gaps or confusion - Update SKILL.md or references 6. **Iterate** based on usage - Clarify confusing sections - Add missing workflows - Reorganize if structure isn't working ## Quality Checklist Before considering documentation complete: - [ ] **SKILL.md exists** and covers primary workflows - [ ] **Concrete examples** throughout (commands, output, use cases) - [ ] **No jargon without explanation** - define domain terms - [ ] **Links to references** mentioned naturally (not exhaustively) - [ ] **Reference files** structured with TOC if >100 lines - [ ] **Relative paths** all correct (tested from the docs directory) - [ ] **No unreferenced tools** - everything mentioned has a link or exists in the rig - [ ] **Tested in practice** - actually used for real workflows
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.