Ai Language Idioms
Language Idioms for AI Agents
❄️ Nix
- Infinite Recursion: Never use
config.footo define theenablecondition forconfig.foo. - Strings: Prefer
lib.concatStringsSepover repetitive string interpolation for lists. - Let Bindings: Keep
let ... inblocks as close to their usage scope as possible.
🥟 Janet
- Immutability: Janet has both mutable (
array,table,buffer) and immutable (tuple,struct,string) data structures. Be explicit about which you are using. - Macros: Avoid macros unless absolutely necessary. Use higher-order functions (
map,filter,reduce) first. - Error Handling: Use
(try ... ([err] ...))instead of letting the script crash, especially inheyCLI tasks. (dyn :syspath)Trap: Janet sets the default(dyn :syspath)to the last entry ofJANET_PATH, not to the directory where a module was actually found. Never use(dyn :syspath)to construct filesystem paths that must exist (e.g.,(os/realpath (path/join (dyn :syspath) "../bin"))). Instead, iterateJANET_PATHentries withsomeand check(path/directory? ...)before using the result. Seelib/hey/lib.janetexec-pathdefinition anddocs/toolchain.md§6 for the full rationale.os/realpathCrashes on Missing Paths: Unlikeos/statorpath/directory?which returnnilon missing files,os/realpaththrows an error if the target doesn’t exist. Prefer existence checks (path/directory?,path/file?) overos/realpathunless symlink resolution is required AND you know the path exists.- Janet Image Creation Trap (
defat build time): Whenjpm installbuilds a compiled executable, Janet evaluates all module-leveldef,var, anddelayexpressions at image creation time (the build sandbox), capturing build-time environment values into the binary.(os/getenv "USER")returnsnix-build,(os/getenv "XDG_DATA_HOME")returns/build/.local/share, etc. These stale values are baked into/run/current-system/sw/bin/heypermanently.- Never use
(def x (os/getenv ...))or(var x (os/getenv ...))for values that must reflect the runtime host. - Never rely on
(delay ...)— Janet fibers may not survivemake-image/load-imagecycles intact, or may be forced at build time with stale env. - Always use
(defn name [] ...)— pure functions called at runtime, evaluatingos/getenvfresh each invocation. - Testing: The dev build (
./scripts/build_hey.zsh) runs from source with correct env vars and will not reproduce the bug. Always test the nix-built binary (nix build .#hey && result/bin/hey info) to confirm the system-level fix. - See
docs/toolchain.md§XDG Path Compile-Time Caching Bug and §6 Exec-Path Resolution.
- Never use
🎨 Matugen Templates (matugen 4.0.0)
- Never use
| set_alpha: X | format: "rgba"oncolors.*.default: This panics in matugen 4.0.0 with “Cant convert map to FilterReturnType”. The color object structure is incompatible with the filter chain. Use.hex_alpha | set_alpha: Ninstead. .hexfor opaque,.hex_alphafor transparency:# Safe — opaque hex {{ colors.primary.default.hex }} # Safe — hex with alpha (8-digit #RRGGBBAA) {{ colors.background.default.hex_alpha | set_alpha: 0.85 }} # PANICS in 4.0.0 {{ colors.background.default | set_alpha: 0.85 | format: "rgba" }}| format: "rgba"only with| to_colorfirst: Theformatfilter works when preceded byto_coloron a string literal, e.g.{{ "red" | to_color | set_alpha: 0.5 | format: "rgba" }}. It panics when applied to acolors.*object directly.- Always test all 11 templates after changes: See
docs/toolchain.md§7 for the full verification protocol. Rungrep -r "set_alpha\|format:" config/matugen/templates/before committing any matugen changes.
🐚 Zsh
- Scoping: Always use
localfor variables inside functions. - Arrays: Use Zsh array syntax
my_array=(a b c)and iterate withfor item in "${my_array[@]}"; do. - Conditionals: Prefer
[[ ]]over[ ]for safe string evaluation.