prelude-just
Use when authoring or editing Justfile recipes in a repository wired to Prelude, when the user asks to add just recipes or make them discoverable in the x menu, or when a recipe needs descriptions, typed arguments, groups, aliases, or module namespacing. Covers recipe authoring for Prelude's runtime Justfile import and verification through x.
How do I install this agent skill?
npx skills add https://github.com/darkmatter/prelude --skill prelude-justIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill provides secure guidelines for authoring Justfile recipes within the Prelude environment. It includes explicit warnings about shell injection risks, recommends defensive coding practices like quoted shell expansion, and provides verification steps to ensure safe execution. No malicious patterns or security risks were detected.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
What does this agent skill do?
Prelude + Just
The Justfile stays the canonical owner of task semantics; Prelude imports it at
runtime — recipes are never copied into prelude.commands. Treat the user's
request as the specification, never as shell text to interpolate. Bind every
recipe to the project's real canonical command — the invocation the tool owner
already uses (bun run test, go test ./..., nix flake check) — and confirm
it actually exists in the repo before writing it; never invent placeholder
scripts.
Enable the import (once)
In the flake-parts module (sidecar prelude.nix or inline configuration):
prelude.menu.enable = true;
prelude.menu.just.enable = true;
# prelude.menu.just.justfile = ./just/Justfile; # pin; null = just's own discovery
# prelude.menu.just.group = "tasks"; # menu group for flat recipes
With config.packages.prelude-shell in the consumer devshell, enabling both
options provides x and just. The Justfile import flag alone does not enable
the menu. See /prelude-install if shell integration is missing.
Attribute support is version-gated in
just ([metadata] 1.42+, [arg(long/short)] 1.46+, [arg(pattern)] 1.45+,
[arg(min/max)] 1.56+) and the import itself only maps fields the consumer's
locked Prelude revision knows — check just --version and confirm against the
locked prelude input before relying on an attribute. An existing
prelude.commands.<name> entry always wins over a same-named recipe.
Author recipes the import understands
The menu reads just --dump --dump-format json; only these fields surface:
# doc comment→ menu description[group('ci')]→ menu group; the key stays flat (x check)alias ship := deploy→ its own entry, inheriting target's doc and groupmod ops 'ops.just'→ ONEx opsrow; Enter (or barex ops) opens a subcommand picker over the module's recipes, while recipes dispatch publicly via parent routing (x ops migrate, orx ops <recipe> [args…]). The recipe executes internally via its canonical command (just ops::migrate). Imported module recipes cannot be selected through double-colon keys (x ops::migrate). A module de-clutters the menu instead of adding one row per recipe. Modules do not inherit the parent Justfile'ssetsettings or recipes; module recipes need their own private helpers (dependencies cannot cross module boundaries).[group('ops')]on a module recipe → the recipe escapes the submenu and stays top-level in that group in the menu, while remaining callable via parent routing (x ops migrate)[private]or leading_→ omitted from the menu (recipes and aliases)[metadata('just test --fix')]→ one worked Example row in the details pane[arg('package', long)]→--packageoption in argument entry[arg('dry', long, flag)]→ toggleable flag in argument entry[arg('kind', pattern='staging|production')]→ pickable options (plain pipe alternation; a regex like[a-z-]+is enforced but renders no options)- default on the recipe line (
package="./...") → optional arg pre-filled
Canonical shape — adapt these commands to the project's actual tooling:
# run the unit test suite
[group('ci')]
test:
bun run test
# run go tests for one package
# (add [group('go')] if a go group is wanted)
[arg('package', help='import path, or ./... for all')]
test-go $package="./...":
go test "$package"
# E2E suites grouped behind one menu row: `just e2e <suite>`
mod e2e 'e2e.just'
with e2e.just carrying its own private helpers:
[private]
guard:
@test -n "${IN_NIX_SHELL:-}"
# run the desktop e2e suite
[metadata('just e2e desktop main')]
[arg('revision', help='branch, commit, PR number or URL')]
desktop $revision="main": guard
bun run desktop-test smoke "$revision"
$package exports the parameter into the recipe environment; "$package"
preserves it as one shell argument. Raw {{…}} interpolation inserts text into
shell source; merely surrounding it with quotes does not make arbitrary values
safe. Prefer exported parameters with quoted shell expansion.
Rules:
- Prefer
[group]over renaming — the public key staysx test. - Argument attributes can change invocation semantics and require a newer
Just version;
long/shortoptions in particular change positional usage. Preserve existing invocation forms unless the task calls for changing them. Private/group/metadata attributes affect visibility or presentation and also need support from the installed Just version. - A parameter with no default is required; argument entry rejects blank submit until it is filled.
- Scope edits to the request; never rename recipes — that changes public keys.
Moving recipes into a module changes their invocation path (e.g.
x coder-e2e→x e2e coder, internaljust e2e::coder); do it only when the user asks for that reorganization, and update any docs that show the old invocation.
Dispatch contract
x <recipe> [args…] currently joins extra arguments with spaces and executes
the assembled command through sh -c. Original argument boundaries are lost:
quotes used by the calling shell do not protect multiword values, and embedded
metacharacters can become shell syntax. Use direct just <recipe> "$value"
for multiword or untrusted values, with safe parameter handling in the recipe
itself. Do not describe x forwarding as argv-preserving.
Bare x <recipe> opens interactive argument entry when parameters exist.
Bare x <module> opens the module's subcommand picker. Module recipes dispatch as
x <module> <recipe> [args…] (or nested x <parent> [submodule…] <recipe> [args…]),
executing the canonical just <module>::<recipe> command internally. Aliases dispatch as
x ship.
Documenting workflows
Menu entries are discovery only. A useful workflow doc covers prerequisites,
arguments, worked examples, effects, and troubleshooting — write that in the
project's docs pages or README (see /prelude-docs), and mirror the worked
invocations with one [metadata('just <recipe> <example>')] line each so the
menu details pane shows them.
Verify (no source checkout assumed)
Read the recipe before running anything: just evaluates backticks when the
file loads, so even --dry-run can execute commands. Then, inside the shell:
just --summary # new recipe listed
just --dump --dump-format json # the exact payload the menu imports
x --list # module appears as one row; children indented
just --dry-run <recipe> [args…] # after inspection: prints lines without running them
x <recipe> # exercise a safe no-argument recipe
References: Prelude import guide — nix run github:darkmatter/prelude#skill -- guide command-conventions; just manual — https://github.com/casey/just.
Initial flake wiring: /prelude-install.
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/darkmatter/prelude/prelude-just">View prelude-just on skillZs</a>