Script writing
Universal AI Agent OS — audited skills, governance rules, replayable state. One contract, every host agent.
npx -y skills add event4u-app/agent-config --skill script-writingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when adding or editing any script under `scripts/` — `--quiet`, `_lib/script_output`, silent Taskfile wiring, Iron-Law carve-outs; fires on 'add a check script for X'.
SKILL.md
9.1 KB, as published. Nobody here has run it
script-writing
When to use
- Creating a new TypeScript script in
src/scripts/{name}.ts(linters, checks, generators, measure tools — run via./scripts-run src/scripts/{name}) - Editing an existing script that prints progress or success lines
- Wiring a script into
Taskfile.ymlortaskfiles/*.yml - Reviewing a PR that adds scripts and asking "why does this still print on minimal?"
Do NOT use this skill when:
- The content is a one-off / archival under
scripts/ai_council/one_off_archive/— those carry an_one_off_prefix and are exempt from the verbosity convention - The content is a shell entrypoint with secret prompts (install-keys, release confirms) → see § 3 Iron-Law carve-outs
- The content is a
.mjs/ Node script underscripts/cost/— different runtime; convention covered inagents/settings/contexts/cost-tracking.md
Script vs other writers — critical test
| Intent | Artifact |
|---|---|
| "Maintenance script the agent or CI runs" | This skill |
"User types /foo to invoke" | command-writing |
| "Constraint the agent must always honor" | rule-writing |
| "Reference knowledge agents cite" | guideline-writing |
Scripts orchestrate file checks, generators, and validators. They are
neither user-invoked nor agent-routed — task and CI call them.
Procedure
0. Run the Drafting Protocol
Creating or materially rewriting a script that joins the linter / check
family must go through Understand → Research → Draft from the
artifact-drafting-protocol rule.
- Understand — what failure does this script catch that no existing check catches? Is it a one-off (then archive it) or evergreen?
- Research —
ls src/scripts/check_*.ts src/scripts/lint_*.ts, grep for overlap, skim 1–2 peer scripts (e.g.lint_handoffs.ts,check_md_language.ts). - Draft — propose name + one-line purpose first. Only fill the body after the shape is confirmed.
1. --quiet flag — argv check
Every check_*.ts / lint_*.ts script MUST accept --quiet so the
silent Taskfile layer (§ 4) can suppress success-only output.
Canonical pattern (see e.g. lint_handoffs.ts):
const QUIET = process.argv.slice(2).includes('--quiet');
// ...
if (!QUIET) {
console.log('✅ All clean');
}
Failure output (❌, non-zero exit) is never gated — failures must
always print regardless of --quiet.
2. _lib/script_output helpers — preferred for new scripts
For anything richer than a single ✅/❌, import the verbosity-aware
router instead of raw print():
import { info, success, warn, error, flush_summary } from './_lib/script_output.js';
info('Loading manifest'); // drops on silent + minimal
success('Wrote 3 files'); // collected at minimal, printed at verbose
warn('Skipping stale entry'); // stderr unless silent
error('Manifest missing'); // stderr always
flush_summary('Done — 3 entries'); // one-line summary at minimal
Resolution order (first wins, cached for the process):
AGENT_SCRIPT_VERBOSITYenv (silent/minimal/verbose)SCRIPT_OUTPUT_VERBOSE=1alias (==verbose).agent-settings.yml→verbosity.script_output- Default
minimal
The resolved level is exported back into AGENT_SCRIPT_VERBOSITY so
child processes inherit it. Tests reset via reset_level() from the
same module — see tests/lib/script_output.test.ts.
3. Iron-Law carve-outs — never silenced
The following surfaces MUST use plain print() and never the
helpers, so verbosity settings cannot suppress them:
- Release confirms — every task in
taskfiles/release.yml - Secret prompts —
install-anthropic-key,install-openai-key,setup-evals,install-hooksinteractive sections runtime-e2eandtest-triggers-live- CI orchestration sentinels —
_ci-start,_ci-end, rootci - Any prompt that asks the user for confirmation per
non-destructive-by-default— Hard Floor cannot be silenced
If unsure, check src/scripts/ai_council/one_off_archive/2026-05/README.md
for the archived carve-out inventory.
4. Taskfile wiring — silent: true + {{.QUIET_FLAG}}
Every Taskfile task that wraps a --quiet-aware script MUST set
silent: true and pass {{.QUIET_FLAG}} to the script:
# Per-task in taskfiles/*.yml:
tasks:
lint-handoffs:
silent: true
cmd: ./scripts-run src/scripts/lint_handoffs {{.QUIET_FLAG}}
The QUIET_FLAG var is defined once at the root of Taskfile.yml
and resolves to "" only when AGENT_SCRIPT_VERBOSITY=verbose:
# Root Taskfile.yml — already in place, do not duplicate:
vars:
QUIET_FLAG:
sh: '[ "$AGENT_SCRIPT_VERBOSITY" = "verbose" ] && echo "" || echo "--quiet"'
Carve-out tasks (release, install secrets, CI orchestration — see § 3)
do not add silent: true and do not use {{.QUIET_FLAG}}.
5. Validate
- Run
./scripts-run src/scripts/skill_linter src/skills/script-writing/SKILL.md→ 0 FAIL - Run
./scripts-run src/scripts/{your-script} --quietand the verbose path — exit code 0 on clean, non-zero on failure regardless of flag - If the script uses
_lib/script_output, add a test undertests/patterned ontests/lib/script_output.test.ts— assertsilent/minimal/verbosebehave per § 2 - Run the full CI pipeline locally (see
Taskfile.ymlin this repo for the script list) — must exit 0 except for tolerated warnings
Output format
- Script file at
src/scripts/{name}.tswith--quietaccepted - Taskfile wiring with
silent: true+{{.QUIET_FLAG}}(unless carve-out) - Test under
tests/if_lib/script_outputis used - Linter output showing 0 FAIL
Gotchas
- Forgetting
--quiet— the silent Taskfile layer wraps the script and the call fails withunrecognized arguments: --quiet - Gating
❌failures behind--quiet— failures must always print - Using raw
print()for progress lines — drops onminimal, no inheritance - Adding
silent: trueto a release / install-keys task — bypasses the Hard Floor confirmation - Editing
Taskfile.yml'sQUIET_FLAGvar — single source of truth, do not duplicate - Forgetting that
import … from './_lib/script_output.js'resolves relative to the script's own directory — copy the import path from a peer undersrc/scripts/
Frugality Standards
Apply the Frugality Charter
to every script you author. Phase 10 of the charter (settings hooks
row — verbosity.script_output / verbosity.taskfile_command_echo)
is what this skill exists to teach.
Examples in this artifact:
- Per the charter's default-terse rule, success lines are gated behind
--quietso the only thing visible atminimalis the end-of-run summary or a failure. - Per the post-action summary suppression, scripts with multi-step
output collect via
success()and emit oneflush_summary()line. - Per the cheap-question check, scripts never prompt unless they hit a Hard Floor surface (§ 3 carve-outs).
Pre-save self-check:
- Does every
print("✅ ...")line sit behind--quiet/ the helper? - Does the script add
silent: true+{{.QUIET_FLAG}}to its Taskfile entry (unless a carve-out)? - Are failure lines (
❌, exit non-zero) never gated by quiet? - Are Iron-Law surfaces using plain
print()and not the helper?
Do NOT
- Do NOT gate
❌/ failure output behind--quiet - Do NOT use
_lib/script_outputfor release confirms or secret prompts - Do NOT add
silent: trueto carve-out tasks - Do NOT hardcode
print()for progress in new scripts — useinfo() - Do NOT skip the Taskfile wiring — without it the verbosity gates leak
- Do NOT edit
dist/agent-src/,.augment/, or.claude/projections
Cloud Behavior
On cloud surfaces (Claude.ai Web, Skills API) the package's task
runner and _lib/script_output are not reachable. The skill still
applies — with prose-only validation:
- Emit the full script + Taskfile snippet as copyable Markdown blocks. Do not attempt to write to disk.
- Self-check:
--quietaccepted, failures never gated, success lines gated, helper imports look syntactically right. - Tell the user to save under
src/scripts/{name}.ts, wire the Taskfile entry, and runtask lint-skills && task cilocally before committing. - Skip every reference to running the linter or
taskcommands yourself — they only run on the user's machine.
Examples
Good description (trigger-shaped, names domain + symptoms):
"Use when adding or editing any script under
scripts/—--quietflag,_lib/script_outputhelpers, silent Taskfile wiring, Iron-Law carve-outs — even when you just say 'add a check script for X'."
Bad description (vague, no trigger):
"Script conventions"