
Research
/Security News
737 Chrome VPN Extensions Linked to Brand Impersonation and Browser Traffic Redirection
The campaign amassed more than 75,000 installs by targeting Russian-speaking users seeking access to blocked services.
@drbaher/draft-cli
Advanced tools
Fill placeholders in a legal-document template with parameter values. Part of the contract-operations suite.
A deterministic placeholder-filler for legal-document templates. Reads
bracketed ([Party A]) or mustache ({{Party A}}) markup, .docx yellow
highlights, or generic-name heuristics; substitutes from CLI flags, a JSON
params file, or an interactive prompt; writes a ready-to-review draft.
Single-file Node.js. One runtime dependency (jszip, for .docx). Local-first,
no telemetry, MIT-licensed. Part of the contract-operations suite (see
cli.drbaher.com).
You have a template. You have a deal. You want a draft you can review and
send. The middle step — finding every [Party A], [Effective Date], and
[State of California] and replacing them with real values — is mechanical,
deterministic work that doesn't need an LLM and shouldn't need to leave your
machine.
template-vault get nda/house-mutual | draft - \
--party-a "Acme Corporation" \
--party-b "Vendor Inc." \
--effective-date 2026-06-01 \
--output draft.md
Or via a params file:
draft nda/house-mutual --params deal-acme.json --output draft.md
draft does only that step. Templates come from template-vault-cli or
any markdown / .docx / stdin source. Review and red-line happens in
nda-review-cli. Conversion to PDF goes through docx2pdf-cli. Signing
goes through sign-cli. Each tool stays small and composable.
npm install -g @drbaher/draft-cli
Or run without installing:
npx @drbaher/draft-cli@latest --demo
Requires Node.js ≥ 18. Tested on Ubuntu and macOS, Node 18 / 20 / 22.
# bash
draft --completion bash >> ~/.bashrc
# zsh
draft --completion zsh > ~/.zsh/completions/_draft
# ensure ~/.zsh/completions is in fpath, then: autoload -U compinit && compinit
Completes flags, the --syntax bracket|mustache value, --completion bash|zsh,
and file paths for --params, --output, and --dictionary.
No file authoring required. The bundled demo runs end-to-end:
npx @drbaher/draft-cli@latest --demo
demo: substituting [Party A], [Party B], [Effective Date]
# Mutual Non-Disclosure Agreement (demo)
This Agreement is entered into on 2026-06-01 between Acme Corporation
and Vendor Inc. (collectively, the "Parties").
1. Confidentiality. Acme Corporation and Vendor Inc. agree to keep confidential
any information disclosed under this Agreement.
2. Term. This Agreement remains in effect for two years from the
2026-06-01.
What just happened: draft-cli detected three bracketed placeholders
([Party A], [Party B], [Effective Date]), mapped them to the
canonical keys party_a, party_b, effective_date, and substituted
in pre-canned demo values. Real runs use your own template and your own
values.
$ cat > nda.md <<'EOF'
This Agreement is between [Party A] and [Party B], effective [Effective Date].
[Party A] and [Party B] agree to keep confidential information confidential.
EOF
$ draft --list-placeholders nda.md
party_a (Party A) ×2 [tier=bracket]
party_b (Party B) ×2 [tier=bracket]
effective_date (Effective Date) ×1 [tier=bracket]
$ draft nda.md --party-a "Acme" --party-b "Vendor Inc." --effective-date 2026-06-01
This Agreement is between Acme and Vendor Inc., effective 2026-06-01.
Acme and Vendor Inc. agree to keep confidential information confidential.
$ cat > deal.json <<'EOF'
{"party_a": "Acme", "party_b": "Vendor Inc.", "effective_date": "2026-06-01"}
EOF
$ draft nda.md --params deal.json --output draft.md --why
draft: substituted 3 of 3 placeholders → draft.md
why:
input = nda.md
tier = bracket
schema = (none, inferred)
placeholders = 3 distinct, 5 occurrences
resolved = 3 (0 from CLI, 3 from --params, 0 interactive, 0 default)
defaulted = 0
unresolved = 0
unmapped = 0
warnings = 0
$ draft --validate nda.md --params deal.json && echo "ok"
ok: 3 parameter(s) resolved
ok
draft-cli finds placeholders by trying five strategies in order. The
first non-empty tier wins and the others are skipped.
| Tier | Strategy | When |
|---|---|---|
| 1 | [Title Case] | Default. Matches Common Paper / YC SAFE / Bonterms convention. |
| 2 | {{Title Case}} | Opt-in with --syntax mustache. |
| 3 | .docx highlights | Auto on .docx input. Yellow / green / cyan / magenta runs. |
| 4 | Heuristic dictionary | Bundled list of generic names (Acme Corporation, John Doe, example@example.com, etc.). Warn-only by default. |
| 5 | LLM | Last resort. Runs only when .env or process env configures ANTHROPIC_API_KEY, OPENAI_API_KEY, or DRAFT_LLM_*. |
The cascade is deterministic through tier 4. Tier 5 is the only
non-deterministic step and runs only when you've explicitly configured a
provider key. Pass --no-llm to disable it even when configured. Pass
--no-heuristic to skip tier 4.
See PARAM_SCHEMA.md for the full contract.
A sibling <template>.params.json lets you declare canonical keys, alias
phrases, defaults, and whether each parameter is required.
Short form:
{
"party_a": ["Party A", "Disclosing Party"],
"party_b": ["Party B", "Receiving Party"],
"effective_date": ["Effective Date"]
}
Long form (gates on _meta):
{
"_meta": { "schema_version": 1 },
"party_a": { "aliases": ["Party A"], "required": true },
"effective_date": { "aliases": ["Effective Date"], "required": false, "default": "the date first written above" }
}
With a schema, draft-cli substitutes only declared parameters and
leaves other bracketed text untouched. Without one, every detected
bracketed phrase is treated as a required parameter.
draft <template> fill placeholders and emit the result
draft <category>/<name> pull via `template-vault get`
draft - template body on stdin
draft --demo bundled demo, no file needed
draft --list-placeholders <t> enumerate placeholders and exit
draft --validate <t> --params completeness check, no output
OPTIONS
--params FILE JSON file of param values (snake_case keys)
-o, --output PATH write to PATH (default: stdout)
--syntax bracket|mustache
-i, --interactive prompt for missing required parameters
--why structured explanation to stderr
--json machine-readable result on stdout
-q, --silent suppress all stderr (warnings, --why, notes)
--no-heuristic disable tier 4
--yes-heuristic substitute tier-4 matches without confirmation
--no-llm disable tier 5 even when env is configured
--llm assert that env is configured (fail-fast if not)
--check-llm one-token roundtrip to verify provider config
--diff show substitution table without writing output
--dictionary PATH override the bundled heuristic dictionary
--<param-name> VALUE set a parameter directly (kebab → snake_case)
-h, --help show full help
-V, --version show version
Exit codes: 0 ok · 1 i/o · 2 validation · 3 template-vault failure
· 4 llm failure.
When tiers 1–4 all find nothing, draft-cli falls back to a language model
only if a provider key is in the environment. Read order: .env in
the working directory, then process.env (process wins).
echo 'ANTHROPIC_API_KEY=sk-ant-…' >> .env
draft some-freeform-draft.md # tier 5 auto-runs when 1-4 empty
Supported providers: Anthropic (ANTHROPIC_API_KEY), OpenAI
(OPENAI_API_KEY), or explicit (DRAFT_LLM_PROVIDER + DRAFT_LLM_API_KEY
DRAFT_LLM_MODEL). The LLM receives template text only — no
params file, no .env contents, no other data. Pass --no-llm to disable
even when configured.draft-cli reads from stdin, writes to stdout by default, and exits with
distinct codes for each failure class. It composes with template-vault-cli
on the read side and nda-review-cli / docx2pdf-cli / sign-cli on
the write side:
template-vault get nda/house-mutual \
| draft - --params deal-acme.json \
| nda-review review - --playbook house \
| docx2pdf - draft.pdf
The --why and --json flags make every step inspectable by agents and
shell pipelines.
draft-cli is one of a small set of single-purpose CLIs for contract
operations. See cli.drbaher.com for the suite
landing page.
template-vault-cli (a Git-backed, clause-aware package manager for
legal-document templates) is the natural upstream of draft-cli and
will join the suite when it ships.
draft-cli needs.MIT. See LICENSE.
FAQs
Fill placeholders in a legal-document template with parameter values. Part of the contract-ops CLI suite.
The npm package @drbaher/draft-cli receives a total of 21 weekly downloads. As such, @drbaher/draft-cli popularity was classified as not popular.
We found that @drbaher/draft-cli demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
The campaign amassed more than 75,000 installs by targeting Russian-speaking users seeking access to blocked services.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.