Template arguments for AI prompts.
You write a prompt with blanks ({{like_this}}), and promptargs fills them in.
Review {{file}} for {{focus}} issues.
becomes...
Review src/app.ts for security issues.
That's it. That's the whole idea.
Works as a CLI and as a skill in Claude Code, Copilot, Goose, and Bob.
Requires Node.js 22 or newer.
npm install -g @hivecommons/promptargsOr just run it without installing:
npx @hivecommons/promptargs helppromptargs ships an Agent Skill at skills/promptargs/SKILL.md, loaded by GitHub Copilot (CLI, cloud agent, VS Code agent mode) and Claude Code.
With the GitHub CLI (2.90.0 or later):
gh skill install hivecommons/promptargs promptargsManually (copy the skills/promptargs/ directory):
# Copilot
mkdir -p ~/.copilot/skills
cp -r skills/promptargs ~/.copilot/skills/
# Claude Code
mkdir -p ~/.claude/skills
cp -r skills/promptargs ~/.claude/skills/Use .github/skills/ or .claude/skills/ inside a project instead to share it with your team.
Claude Code:
mkdir -p ~/.claude/commands
curl -o ~/.claude/commands/promptargs.md \
https://raw.githubusercontent.com/hivecommons/promptargs/main/.claude/commands/promptargs.mdGoose:
mkdir -p ~/.config/goose/skills
curl -o ~/.config/goose/skills/promptargs.md \
https://raw.githubusercontent.com/hivecommons/promptargs/main/.goose/agents/promptargs.mdBob (IBM):
mkdir -p ~/.bob/skills
curl -o ~/.bob/skills/promptargs.md \
https://raw.githubusercontent.com/hivecommons/promptargs/main/.bob/skills/promptargs.mdpromptargs initThis creates a .prompts/ folder with 3 starter templates. Done!
promptargs listAvailable templates:
review
vars: {{file}} {{focus=correctness}} {{tone=concise}}
explain
vars: {{file}} {{style=simple}} {{audience=junior developer}}
fix
vars: {{issue}} {{file}} {{expected}} {{actual}}
promptargs review --file=src/app.tsReview src/app.ts for correctness issues.
Be concise in your feedback.
Focus on real bugs, not style nitpicks.
Variables with =something already have a default. Variables without one will ask you to fill them in.
Powered by Mustache — a logic-less template language available in every major language.
A blank looks like this: {{name}}
A blank with a default looks like this: {{name=hello}} (promptargs extension)
Padding inside the braces is fine too — {{ name }} and {{ name=hello }} mean the same thing, and so does {{ name = hello }} (padding around = is not part of the default).
Names may use letters, digits, _ and - ({{file-name}}). Dotted names such as {{repo.owner}} are rejected with an error — use {{repo_owner}}; the switch names no-interactive, cross, json, status and help are also rejected, as they are reserved for CLI switches. Likewise, the template file names help, env, ui, init, list and show are reserved for the subcommands of the same name; such a template is listed as unreachable by promptargs list (and show warns), because the subcommand always wins.
A default may appear on any occurrence of a blank ({{name}} … {{name=hello}}); if two occurrences give different defaults, the first one wins.
That's the basics. Mustache comments ({{! ignore me}}) work as documented and are safe to use.
Mustache sections ({{#flag}}...{{/flag}}) and partials ({{>name}}) are parsed too, but aren't practically usable yet: promptargs only resolves plain {{name}} / {{name=default}} tags from --flag=value, auto-detected context, defaults, or interactive fill — a section's condition name is never filled this way (so its content is always dropped, or always kept for an inverted {{^name}} section), and partial content is never supplied, so {{>name}} always expands to nothing. Stick to plain blanks and comments; avoid sections and partials for now.
promptargs show reviewShows the template with red blanks (required) and yellow blanks (has a default).
promptargs review --file=main.go --focus=security --tone=detailedpromptargs review
file: main.go
focus: (correctness) ← press Enter to keep default
tone: detailedpromptargs "Explain {{thing}} to a {{audience=5-year-old}}" --thing=recursionExplain recursion to a 5-year-old
Want to review 5 files? Don't run the command 5 times. Use a comma:
promptargs review --file=api.go,auth.go,db.go,cache.go,main.gopromptargs runs the template once for each value and prints each expanded result separated by ---:
Review api.go for correctness issues.
Be concise in your feedback.
Focus on real bugs, not style nitpicks.
---
Review auth.go for correctness issues.
Be concise in your feedback.
Focus on real bugs, not style nitpicks.
---
Review db.go for correctness issues.
...
Status lines showing iteration progress go to stderr:
✅ review [1/5]: file=api.go focus=correctness tone=concise
✅ review [2/5]: file=auth.go focus=correctness tone=concise
...
| Syntax | What it does |
|---|---|
--file=a.go,b.go,c.go |
Comma-separated list |
--file="src/*.go" |
Glob pattern (expands to matching files) |
--file="src/**/*.go" |
Recursive glob (** matches any depth) |
--file=@list.txt |
Reads one value per line from a file |
Zip mode (default): arrays pair up 1:1:
promptargs "Review {{file}} for {{focus}}" \
--file=api.go,auth.go,db.go \
--focus=security,perf,correctness✅ [1/3]: file=api.go focus=security
✅ [2/3]: file=auth.go focus=perf
✅ [3/3]: file=db.go focus=correctness
When arrays have different lengths, the number of runs is the length of the longest array, and shorter arrays repeat (cycle around):
promptargs "Review {{file}} for {{focus}}" \
--file=api.go,auth.go,db.go \
--focus=security✅ [1/3]: file=api.go focus=security
✅ [2/3]: file=auth.go focus=security
✅ [3/3]: file=db.go focus=security
Or with two unequal arrays:
promptargs "Review {{file}} for {{focus}}" \
--file=a.go,b.go,c.go \
--focus=x,y✅ [1/3]: file=a.go focus=x
✅ [2/3]: file=b.go focus=y
✅ [3/3]: file=c.go focus=x
Cross-product mode (--cross): every combination of every value:
promptargs "Review {{file}} for {{focus}}" \
--file=api.go,auth.go,db.go \
--focus=security,perf,correctness \
--cross✅ [1/9]: file=api.go focus=security
✅ [2/9]: file=api.go focus=perf
✅ [3/9]: file=api.go focus=correctness
✅ [4/9]: file=auth.go focus=security
✅ [5/9]: file=auth.go focus=perf
✅ [6/9]: file=auth.go focus=correctness
✅ [7/9]: file=db.go focus=security
✅ [8/9]: file=db.go focus=perf
✅ [9/9]: file=db.go focus=correctness
3 files × 3 focuses = 9 runs. Use --cross when you want the full matrix.
| Location | What it's for |
|---|---|
.prompts/ |
Your project's templates (commit these!) |
~/.prompts/ |
Your personal templates (available everywhere) |
Project templates override personal ones with the same name.
Symlinked *.md entries are followed only when their real target is inside the same .prompts/ directory (a sub-directory is fine); a symlink whose target escapes the directory is listed with an error and refused when run, so a cloned repo cannot make promptargs read files elsewhere on your machine. Symlinks to directories and dangling symlinks are skipped. The project .prompts/ entry itself must be a real directory: if it is a symlink, it is refused with a diagnostic on stderr (loader_dir_symlink under PROMPTARGS_LOG=json) and no project templates are loaded (~/.prompts/ is yours and may be a symlink).
promptargs discovers variables from two sources:
Run promptargs env any time to preview exactly what's auto-detected in your current shell before you run a template:
promptargs envThese variable names fill themselves automatically when you're in a git repo:
| Variable | Auto-fills with |
|---|---|
{{branch}} |
Current git branch |
{{repo}} |
Repository name |
{{org}} |
GitHub org/user |
{{user}} |
Git config user name |
{{date}} |
Today's date |
{{diff}} |
Staged or unstaged diff |
{{pr}} |
Current PR number |
Any environment variable in your terminal is available as a template variable. Use the same name:
# If your terminal has DATABASE_URL and AWS_REGION set:
promptargs "Connect to {{DATABASE_URL}} in {{AWS_REGION}}"In the Builder UI (promptargs ui), click "Show terminal env" to see all available env vars from your shell. Click any one to insert it at the cursor.
Common useful env vars: NODE_ENV, AWS_REGION, CI, USER, EDITOR, PATH, SHELL.
Credential-looking names are intentionally excluded from auto-detection: anything containing TOKEN, SECRET, PASSWORD/PASSWD/PASSPHRASE, CREDENTIAL, API_KEY/ACCESS_KEY/PRIVATE_KEY, BEARER, COOKIE, WEBHOOK, JWT, HMAC, OAUTH, CONNECTION_STRING, or the _-delimited words AUTH, KEY/KEYS, PWD, PAT, PASS, DSN (so GITHUB_TOKEN, SIGNING_KEY, MYSQL_PWD, GITHUB_PAT and SLACK_WEBHOOK_URL are all refused, while PATH, PWD, KEYBOARD and AUTHOR still work). Credential-shaped values are excluded whatever the name: URLs with a password in them (postgres://user:pass@host/db), PEM blocks, JWTs, and well-known token prefixes (ghp_, github_pat_, glpat-, sk-, xoxb-, AKIA…, npm_…, …). A repo-controlled template can therefore never expand {{GITHUB_TOKEN}} or {{DATABASE_URL}} into a secret, even though an explicit --flag=value can still pass any value you choose. This also applies to the Builder UI's "Show terminal env" list.
You can always override any auto-detected value with a flag. The order is:
--flag=value(explicit, always wins)- Auto-detect from environment (git context and terminal env vars)
- Template default (
{{name=fallback}}) - Interactive prompt — only for variables still unfilled, and only without
--no-interactive
A variable that auto-detects or has a default is never prompted for; pass --name=value to override it.
promptargs review --file=main.gopromptargs review --file=main.go --jsonpromptargs review --file=main.go --status✅ review: file=main.go focus=correctness(default) tone=concise(default)
Don't want to memorize flags? Open the visual builder:
promptargs uiOpens a browser at http://localhost:3700/?t=<token> — the token is random per run and printed at startup — with:
- Preset examples — 8 clickable templates (review, explain, fix, test, migrate, security, docs, refactor)
- Template editor — type your template, variables auto-populate below
- Variable table — set values, arrays (comma-separated), and sources (manual, glob, @file)
- Environment panel — git context vars + all terminal env vars, click any to insert
{{var}}at cursor - Mustache cheatsheet — collapsible syntax reference for template features
- Zip / Cross toggle — switch array iteration mode
- Live preview — see expanded output update as you type
- CLI command — copy the generated command with one click
Use --port=N if 3700 is taken:
promptargs ui --port=4000promptargs does not collect or export telemetry. There is no telemetry SDK, metrics endpoint, or observability backend configured anywhere in this package — nothing you run ever phones home.
All runtime diagnostics are human-readable console output (CLI status/errors, UI startup/port messages). The Builder UI (promptargs ui) binds to loopback only (127.0.0.1), rejects requests with a non-local Host header, and only serves the page to a client presenting the random per-run token in the URL it prints at startup, so the page — including the auto-detected Git and terminal environment values it embeds (see Auto-Magic Variables) — is never reachable from other machines on your network, nor from other accounts sharing the same machine's loopback interface.
Opt-in structured diagnostics: set PROMPTARGS_LOG=json to make diagnostics (CLI errors and iteration progress, UI Host and token rejections, asset failures, unreadable or symlinked prompts directories, and one line per UI request) print as JSON lines on stderr with a fixed field set: event, plus status, duration_ms, error_class (usage, not_found, io, port_in_use, unknown), count, current, total where relevant. Template contents, argument values, paths and error messages are never logged. When unset, output is unchanged. Nothing is sent over the network.
If observability is ever added in the future, it will be explicit opt-in, bounded to local diagnostics, and will exclude environment values, template/prompt content, file paths, diffs, and user identifiers. No network exporter will be added unless you explicitly configure a backend yourself.
The package also exports its building blocks as an ES module (Node.js 22+). Install it first with npm install @hivecommons/promptargs.
import { parseVars, expand } from '@hivecommons/promptargs';
const template = 'Review {{file}} for {{focus=correctness}} issues.';
parseVars(template);
// [{ name: 'file', ... }, { name: 'focus', defaultValue: 'correctness', ... }]
expand(template, { file: 'src/app.ts', focus: 'security' });
// 'Review src/app.ts for security issues.'
expand(template, { file: 'src/app.ts' });
// 'Review src/app.ts for correctness issues.' (defaults fill missing values)Variables with no value and no default are left as {{name}} in the output. Other exports: autodetect, autodetectAll, AUTODETECT_VARS, loadTemplates, findTemplate, resolve and renderStatus.
Create a file in .prompts/ with any name ending in .md:
.prompts/buddy.md
Hey {{name=buddy}}! Can you help me understand {{topic}}?
I learn best with {{style=examples and analogies}}.
Now use it:
promptargs buddy --topic="async/await"Hey buddy! Can you help me understand async/await?
I learn best with examples and analogies.
promptargs works with any AI tool that accepts piped input:
# Claude
promptargs review --file=src/main.ts --no-interactive | claude -p "do this review"
# Goose
promptargs review --file=src/main.ts --no-interactive | goose run
# Copilot CLI (needs the standalone `copilot` CLI, installed and signed in)
copilot -p "$(promptargs review --file=src/main.ts --no-interactive)"If you installed the skill (see Install), use it directly inside your session:
Claude Code:
/promptargs review --file=src/api.ts
Goose / Bob: The skill is automatically available after install — ask your agent to "use promptargs" or run a template.
Copilot: Installed skills load automatically; ask Copilot to use promptargs.
| Command | What it does |
|---|---|
promptargs ui |
Open the visual builder in your browser |
promptargs init |
Create .prompts/ with examples |
promptargs list |
Show all available templates |
promptargs show review |
Preview template with highlighted blanks |
promptargs review --file=x |
Run template with flags |
promptargs review |
Run template interactively |
promptargs "inline {{var}}" |
Use inline template |
promptargs env |
Show auto-detected variable values |
--no-interactive |
Skip questions, use defaults only |
--cross |
Cross-product mode (all combinations) |
--json |
Output as JSON |
--status |
Output status line only |
... | claude -p "do this" |
Pipe to Claude |
... | goose run |
Pipe to Goose |
The switch names no-interactive, cross, json, status and help are reserved and cannot be used as template variable names. Switches take no value: --json=false is rejected with a usage error. A flag that names no blank in the template (e.g. a typo like --fiel=x) is also an error. So is a blank left unfilled under --no-interactive or piped stdin: promptargs exits 1 with Missing value for {{name}}: ... rather than printing the raw placeholder.
promptargs is part of Hive Commons, a family of tools for working with AI agents.
- Want to contribute? See CONTRIBUTING.md for setup, checks, and pull request guidelines.
- Found a bug or have an idea? Open an issue.
- Reporting a security vulnerability? Follow SECURITY.md to report it privately, not through public issues.
- Please follow the Hive Commons Code of Conduct.
Apache-2.0