Node CLI Internal Tool¶
Node-based command-line tools used by developers, CI, operators, or internal automation.
Charter status¶
| Charter status | Value |
|---|---|
| Maturity | Candidate rubric |
| What this state means | Numbered candidate rules carry severity, required evidence, and an exception policy. A versioned rubric can be cut from this page once its promotion criteria are met. |
| Full rubric | Not authored yet. This page is a charter, not a judgeable standard. |
| Reference implementation | vibecodeqa/ref-node-cli-internal-tool (published) — see Reference implementation below. |
| Blocking promotion | Twelve candidate rules carry severity, evidence, and exception terms, and ref-node-cli-internal-tool is published with a self-reported score and a green CI run. Blocking v1: no independent assessment of the reference repo exists, and the exit-code and JSON-mode rules have no scanner signal yet. |
Maturity states are defined in Standards Authoring.
Metadata lives in standards/registry.json.
Full rubric¶
No full versioned rubric has been authored yet.
Reference implementation¶
| Score evidence | Value |
|---|---|
| Repository | vibecodeqa/ref-node-cli-internal-tool (published) |
| VCQA report | 92/100 |
| Verification | self-reported |
| Assessed commit | 95f4194 |
| Assessed on | 2026-07-24 |
| CI run | success (2026-07-24) |
| Independent assessment | None published yet. The score above is the reference repo's own claim, not third-party proof. |
| Catalog entry last verified | 2026-08-08 |
Teaching focus¶
This standard teaches that an internal CLI is still a public contract for scripts, CI, and operators. Choosing this stack means choosing predictable process behavior, safe defaults for privileged environments, and automation-friendly output before adding convenience features.
Scope¶
Node-based command-line tools used by developers, CI, operators, or internal automation.
Not in scope¶
- browser apps
- published SDKs with no CLI entrypoint
- long-running services unless the CLI controls them
Composes¶
Upstream references¶
- Node.js process API
- Node.js package entry points and package metadata
- Node.js security best practices
- npm package.json docs
- GitHub Actions workflow commands
- GitHub Actions exit codes for actions
- OWASP Secrets Management Cheat Sheet
VCQA-owned rule surface¶
- argument parsing and command shape.
- exit-code, stderr, and stdout contract.
- structured JSON output mode.
- credential lookup and redaction boundaries.
- staging/prod safety defaults.
- dry-run, idempotency, and retry behavior.
- noninteractive behavior for CI and agents.
- config precedence and environment selection.
- release, runtime, and packaging policy.
- SDK reuse instead of API duplication.
Detection signals¶
package.json#bin- Node CLI dependencies such as
commanderoryargs - scripts invoked by CI or operators
process.argv,process.exitCode,process.stdout, orprocess.stderr--json,--dry-run,--yes,--force,--env,--profile, or similar CLI flags- CI workflows invoking package scripts or published bins
- direct API calls from a CLI package that duplicate an SDK client
Combination-born guidelines¶
- Exit codes and stderr/stdout behavior are part of the API.
- Credential lookup order must make production operations explicit.
- Structured output mode is required when CI or agents consume results.
- TypeScript types do not validate command-line input; parse and validate external input before side effects.
- GitHub Actions commands use stdout, so CI-facing CLIs must avoid mixing human logs into machine-readable output.
- Node child process and shell features are high-risk boundaries; user-controlled input must not be interpolated into shell commands.
- OpenAPI-backed CLIs should call the same generated or hand-authored SDK used by other clients unless the CLI owns a lower-level transport concern.
Candidate rules¶
- R-CLI-1: Command syntax is explicit and documented. Commands, positional arguments, options,
defaults, aliases, examples, and deprecations are discoverable through
--helpand checked docs. - R-CLI-2: Exit codes are stable.
0means success; non-zero codes distinguish usage errors, validation failures, auth/config failures, not-found/no-op cases, partial failures, and unexpected runtime failures where the distinction matters to automation. - R-CLI-3: stdout is for results. Human diagnostics, progress, warnings, and prompts go to stderr; stdout contains only the primary result, plain text requested by a human, or structured output requested by automation.
- R-CLI-4: JSON mode is structured and quiet.
--jsonemits one documented JSON value to stdout, uses stderr for diagnostics, redacts secrets, and returns a non-zero exit code for failures instead of embedding success as a string. - R-CLI-5: Noninteractive mode never waits. CI and agent use must fail fast when required input,
confirmation, or credentials are missing; prompts require an interactive TTY unless an explicit
--yes,--force, or equivalent flag is present. - R-CLI-6: Config precedence is deterministic. Non-secret configuration resolves in a documented order, normally flags, environment variables, project config, user config, then defaults, with an inspectable redacted effective-config view.
- R-CLI-7: Credentials are separated from config. Secrets come from CI secret stores, environment variables, OS credential stores, or a documented secret manager; project config may name a profile or account but must not contain raw production secrets.
- R-CLI-8: Production writes are explicit. Destructive or production-scoped operations require an explicit environment, target, and confirmation mechanism; staging or read-only behavior is the default when ambiguity would be dangerous.
- R-CLI-9: Dry-run predicts side effects. Mutating commands provide a dry-run mode when feasible, show the target environment and planned operations, and avoid fetching or printing secret material in preview output.
- R-CLI-10: Mutations are idempotent or resumable. Commands used by CI or operators define retry behavior, idempotency keys, conflict handling, and partial-failure reporting so reruns do not silently duplicate work.
- R-CLI-11: Runtime and release policy are pinned.
engines.node, package manager expectations, executable bins, lockfiles, and release artifacts are aligned so CI, developer machines, and operator environments run the same supported Node line. - R-CLI-12: API behavior is not forked. A CLI that drives a product API reuses the product SDK or a shared generated client and keeps its request/response contract fresh with the checked-in API description.
Severity and evidence¶
Severities follow the shared rule contract. Severity belongs to the rule, not to the reviewer.
| Rules | Severity | Escalation |
|---|---|---|
| R-CLI-7, R-CLI-8 | blocker |
Already top severity. A production secret in checked-in config, or a destructive command that defaults to production, makes the tool unsafe to hand to CI or an operator. |
| R-CLI-2, R-CLI-3, R-CLI-4, R-CLI-5 | high |
blocker when the CLI drives a deploy or migration gate: a wrong exit code or a stdout/stderr mix silently turns that gate off. blocker for R-CLI-4 when secret material appears in JSON output. |
| R-CLI-12 | high |
blocker when the forked client bypasses an authorization or tenant-scoping path the SDK enforces. |
| R-CLI-6, R-CLI-9, R-CLI-10, R-CLI-11 | medium |
high for R-CLI-10 when a retried command is not idempotent and writes production data; high for R-CLI-11 when the published bin runs on a Node line the project does not test. |
| R-CLI-1 | low |
medium once the CLI is published to a registry or documented for external operators. |
Required evidence:
evidence:
sourcePaths:
- "bin/**"
- "src/**"
configFiles:
- "package.json"
- ".github/workflows/*.yml"
ciArtifacts:
- "parser and exit-code unit test report"
- "executable smoke-run log from the packed or built bin"
runtimeProof:
- "`--help` transcript"
- "one scripted run per documented exit code, with the observed code recorded"
- "`--json` output captured and parsed by a machine consumer, not eyeballed"
- "a non-TTY run proving no prompt blocks CI"
negativeEvidence:
- "no credential value in stdout, --json output, committed config, or the retained log"
exceptionFormat: "accepted-exception"
CI expectations: the smoke run executes the built or packed bin without a TTY and asserts the
exit code, not just that the process ended. A job that runs the CLI with continue-on-error,
or that only imports its modules, is not evidence for R-CLI-2 or R-CLI-5.
Exception policy¶
Exceptions use the acceptedException record in the rule contract:
owner, scope, environment, reason, compensating controls, evidence, expiry, approval trail.
Stack-specific rulings:
- R-CLI-4 is exceptionable for a CLI with no machine consumer, scoped to the package and recorded with a review date. It stops being exceptionable the day a workflow parses its output.
- R-CLI-9 is exceptionable for commands with no server-side effect, or where a dry run would cost as much as the operation; the reason must name why, not that it was not built.
- R-CLI-10 is exceptionable for operations that are genuinely single-shot, provided the partial-failure behaviour is documented so an operator knows what a rerun does.
- R-CLI-7 and R-CLI-8 are not exceptionable. No owner or compensating control makes a committed production secret or a production-by-default destructive command acceptable; the finding is closed by rotating the credential and changing the default.
- An exception cannot change the archetype. A tool that requires an interactive TTY by design is not a CI-safe CLI with an exception; it is an interactive application.
Anti-patterns¶
- Printing progress, warnings, or prompts to stdout while also advertising scriptable output.
- Returning
0for failed operations because an error object was printed. - Requiring a TTY prompt in CI, cron, release jobs, or agent workflows.
- Defaulting ambiguous destructive commands to production.
- Storing API tokens in repository config, examples, snapshots, or generated debug logs.
- Treating
--forceas a blanket bypass instead of a narrow confirmation of a specific risky action. - Building a separate CLI HTTP client that drifts from the SDK or OpenAPI contract.
- Shelling out with concatenated user input where an argument-array API or library call is available.
- Publishing a bin without a documented Node support range or tested install path.
Promotion criteria¶
This charter can be cut as node-cli-internal-tool/v1 when all of the following are true.
- Every candidate rule is rewritten in the rule-contract rule template, with severity, why,
evidence, exception, a
vcqascanner or human-review signal, and a good/bad example. - Every rule has been judged against
ref-node-cli-internal-toolat a named commit, with the pass/fail recorded — including the rules that repo currently does not exercise. - The exit-code, stdout/stderr, and JSON-mode rules have a machine signal or an explicit human-review note. Today they are checkable by a person running the bin, which is not the same as checkable by a scan.
- The reference implementation carries an independent assessment. Its score is self-reported today, and a rubric cut against a self-graded template inherits that weakness.
- A fresh independent assessment scores this page above the
draftband, replacing the dated report linked below. - The registry entry gains a
v1edition with reviewed, next-review, targets, and lifecycle metadata, and the page is rewritten to the authored charter bar in Standards Authoring.
Review cadence¶
While this charter is a candidate rubric it is reviewed:
- whenever the Node LTS line changes, which moves R-CLI-11's supported-runtime expectation;
- whenever
ref-node-cli-internal-toolchanges shape or is re-scored; - whenever a rule here is contradicted by a real scan finding in
@vibecodeqa/cli; - and in any case no later than six months after the date of the most recent assessment report linked below.
Benefits¶
- Cloudflare SaaS example CLI.
- vcqa/cli.
Independent Assessment¶
That report is a dated snapshot of this page on 2026-07-25, before it carried severity, an exception policy, promotion criteria, or a review cadence. It is not rewritten, and its score is not restated here as current; a fresh assessment is a promotion criterion above.