nimonyplugins
Skill4 starsChanged 3 months agoMITView on GitHub
Build and debug Nimony compile-time plugins for code generation and DSL rewrites. Use when replacing Nim macros with Nimony plugins, writing or reviewing template, for-loop, module, type, or import plugins, or diagnosing NIF traversal and generated output.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- planetis-m/skillsword for word, first seen Jul 16, 2026
Other versions1 project uses a version of this.
Word for word · 1
- planetis-m/skills★ 59100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository18 other files it gives its agents.
- atlas-package-clonerSkill
- buildSkill
- docs-genSkill
- format-codeSkill
- nim-api-designSkill
- nim-c-bindingsSkill
- nim-code-organizationSkill
- nim-c-wrappersSkill
- nim-debuggingSkill
- nim-defect-analysisSkill
- nim-doc-commentsSkill
- nim-error-handlingSkill
- nim-fuzzingSkill
- nim-mcp-toolsSkill
- nim-ownership-hooksSkill
- nim-style-guideSkill
- nim-testingSkill
- run-testsSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
14 rules. About 0 are common, 3 are distinctive, and 11 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 13
If the resolved path ends in /bin/nimony, open ../src/nimony/lib/plugins.nim relative to the executable directory.
- Distinctive: line 16
Treat that file as the source of truth.
- Very specific: line 32
Use forLoopCallArgs, forLoopVars, and forLoopBody.
- Very specific: line 40
Import: import (path/foo) {.plugin: "p".} transforms an imported module.
- Very specific: line 42
When multiple templates or iterators name the same plugin path, use pluginName(root) to dispatch them inside that one executable.
- Distinctive: line 45
Use the named protocol helpers to access template and for-loop inputs.
- Very specific: line 62
Start a builder with createTree().
- Very specific: line 63
Add known Nimony enum tags with withTree SomeEnum, info:.
- Very specific: line 64
Add textual or dynamic tags with balanced openTree(tag, info) / closeTree().
- Very specific: line 68
Use addTree(dest, child) to append an entire child builder.
- Very specific: line 69
Use addSubtree(dest, cursor) to copy without advancing and takeTree(dest, cursor) to copy and advance.
- Very specific: line 71
Use copyInto(dest, cursor): to copy a node head while transforming all bounded children.
- Very specific: line 73
Use bindSym for hygienic definition-scope symbol references.
- Distinctive: line 114
Use protocol helpers before traversing arguments, variables, or bodies.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Nimony Plugins
Rules
Resolve the actual API
- Resolve
nimonywithreadlink -f "$(command -v nimony)". - If the resolved path ends in
/bin/nimony, open../src/nimony/lib/plugins.nimrelative to the executable directory. Otherwise opensrc/nimony/lib/plugins.nimunder the executable directory. Treat that file as the source of truth. - Plugin modules are compiled with Nimony itself. Each unique plugin path gets
a separate
nimony cinvocation and cached executable, even when two paths contain identical source. Warm builds reuse those executables. - A
{.plugin: "path".}path is relative to the source file containing the pragma, not the call site.
Choose the plugin contract
There are five plugin kinds:
- Template:
template f(...) {.plugin: "p".}receives(stmts <template-name> <args...>). UsecallArgs(root)to read the arguments. Its output is semantically checked again. - For-loop:
iterator f(...) {.plugin: "p".}receives(forcall <iterator-name> (callargs ...) (unpackflat|unpacktup ...) <body>). UseforLoopCallArgs,forLoopVars, andforLoopBody. The body is already typed; transformed output is semantically checked again. - Module:
{.plugin: "p".}receives the semantically checked full module and must return the full module. Output is not checked again. - Type:
type T {.plugin: "p".} = ...receives the full module throughloadPluginInput()and triggering definitions throughloadTypeDefinitions(). It must return the full module; output is not checked again. - Import:
import (path/foo) {.plugin: "p".}transforms an imported module.
When multiple templates or iterators name the same plugin path, use
pluginName(root) to dispatch them inside that one executable.
Use the named protocol helpers to access template and for-loop inputs.
Ownership and identity
NifBuilderis the move-onlynifcore.TokenBuf.NifCursoris a copyable, reference-counted, bounded read cursor.snapshot(tree)borrows a non-empty builder. The cursor keeps its observed storage alive; later builder mutation detaches storage as needed.addTreeborrows its child builder, so the child remains usable afterward.saveTreeaccepts its completed output as asinkparameter.SymIdandTagIdare numeric handles local to shared plugin pools. Resolve their names withsymTextandtagText.- Plugin inputs and builders use shared preseeded pools, so handles obtained from plugin cursors can be reused by builder helpers.
Build NIF
- Start a builder with
createTree(). - Add known Nimony enum tags with
withTree SomeEnum, info:. - Add textual or dynamic tags with balanced
openTree(tag, info)/closeTree(). - Preserve
n.infowhen deriving output from an input node. UseNoLineInfofor synthetic output. - Use
addTree(dest, child)to append an entire child builder. - Use
addSubtree(dest, cursor)to copy without advancing andtakeTree(dest, cursor)to copy and advance. - Use
copyInto(dest, cursor):to copy a node head while transforming all bounded children. - Use
bindSymfor hygienic definition-scope symbol references. - For each local introduced by a plugin, call
genSym()once and pass thatSymIdtoaddSymDefand every correspondingaddSymUse.
Traverse bounded cursors
- Compound nodes have kind
TagLit; strings have kindStrLit. - Cursors are bounded by a remaining-token count.
firstChild(n)returns a cursor bounded to the current node's children.skip(n)advances over one atom or complete subtree.into n:andloopInto n:require their bodies to consume all children.balancedTokens n:visits descendantTagLitnodes, excludes the root, and leavesnadvanced past the root.- Copy a cursor for lookahead and use
hasMoreto test its bounds.
Prefer Replacer for selective rewrites
keep,drop, andreplaceeach consume one input child.- Their kind argument asserts the current child's kind.
keepTagandreplaceHeadbodies must consume every child.loopKeepTagpreserves a node while iterating its children.peekrestores the source cursor; writes tor.destpersist.- Template replacers start at
(stmts <name> <args...>); consume or preserve the leading name deliberately before processing arguments.
Report errors and write output
- Return
errorTree(message, at)when user input violates the plugin's contract. - Reserve assertions for plugin implementation contract violations.
renderNode(cursor)andrenderTree(builder)are debugging helpers that omit line information.saveTreeconsumes a builder.saveReplacerwrites the replacer output.
Workflow
- Resolve and inspect the exact
plugins.nimused by the selected Nimony. - Select the plugin kind and write down its input/output contract.
- Expose the pragma from a small user-facing module and keep transformation logic in a separate plugin module.
- Load input with
loadPluginInput,loadTypeDefinitions, orloadReplacer. - Use protocol helpers before traversing arguments, variables, or bodies.
- Preserve correct subtrees; synthesize only what changes.
- Build one complete output. Return
errorTreefor invalid input, then write the result withsaveTreeorsaveReplacer. - Compile plugin integration tests with Nimony. A host-Nim test harness can
launch
nimonywhen needed.
Common Mistakes
| Mistake | Correction |
| Compiling the plugin module with Nim | Compile plugin modules and integration tests with Nimony |
| Traversing a template root as though every child were an argument | Use callArgs(root); the root also contains the invoked template name |
Confusing addSubtree with takeTree | Use addSubtree to preserve the cursor position and takeTree to advance it |
Leaving children unconsumed in into, keepTag, or replaceHead | Consume every bounded child in the body |
| Returning a transformed fragment from a module or type plugin | Return the complete module |
| Reusing a textual name for a generated local | Call genSym() once and use its SymId for the definition and every use |
Writing output during peek while treating it as a dry run | Keep peek read-only; it restores the source cursor but not r.dest |
References
references/template_plugin.md— A template plugin that generates an expression from literal arguments.references/replacer_api.md— A selective call rewrite that preserves most input children.references/for_loop_plugin.md— A for-loop plugin that expands an already typed body.references/module_plugin.md— A module plugin that rewrites an already typed module.references/type_plugin.md— A type plugin for validation or rewrites driven by selected types.references/generated_symbols.md—genSymdefinition and use for collision-free locals.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

