@hivecommons/promptargs 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -20
- package/dist/autodetect.js +39 -12
- package/dist/autodetect.js.map +1 -1
- package/dist/cli.js +78 -147
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +4 -0
- package/dist/commands.js +148 -0
- package/dist/commands.js.map +1 -0
- package/dist/flags.d.ts +20 -0
- package/dist/flags.js +101 -0
- package/dist/flags.js.map +1 -0
- package/dist/loader.d.ts +2 -0
- package/dist/loader.js +84 -11
- package/dist/loader.js.map +1 -1
- package/dist/log.d.ts +19 -0
- package/dist/log.js +41 -0
- package/dist/log.js.map +1 -0
- package/dist/parser.js +39 -9
- package/dist/parser.js.map +1 -1
- package/dist/resolver.d.ts +3 -1
- package/dist/resolver.js +105 -34
- package/dist/resolver.js.map +1 -1
- package/dist/status.d.ts +1 -1
- package/dist/status.js +5 -4
- package/dist/status.js.map +1 -1
- package/dist/ui.d.ts +3 -0
- package/dist/ui.html +21 -6
- package/dist/ui.js +89 -12
- package/dist/ui.js.map +1 -1
- package/package.json +13 -4
- package/dist/autodetect.test.d.ts +0 -1
- package/dist/autodetect.test.js +0 -207
- package/dist/autodetect.test.js.map +0 -1
- package/dist/cli.test.d.ts +0 -1
- package/dist/cli.test.js +0 -310
- package/dist/cli.test.js.map +0 -1
- package/dist/index.test.d.ts +0 -1
- package/dist/index.test.js +0 -59
- package/dist/index.test.js.map +0 -1
- package/dist/iterate.test.d.ts +0 -1
- package/dist/iterate.test.js +0 -20
- package/dist/iterate.test.js.map +0 -1
- package/dist/loader.test.d.ts +0 -1
- package/dist/loader.test.js +0 -65
- package/dist/loader.test.js.map +0 -1
- package/dist/parser.test.d.ts +0 -1
- package/dist/parser.test.js +0 -93
- package/dist/parser.test.js.map +0 -1
- package/dist/resolver.test.d.ts +0 -1
- package/dist/resolver.test.js +0 -184
- package/dist/resolver.test.js.map +0 -1
- package/dist/sanitize.test.d.ts +0 -1
- package/dist/sanitize.test.js +0 -38
- package/dist/sanitize.test.js.map +0 -1
- package/dist/status.test.d.ts +0 -1
- package/dist/status.test.js +0 -33
- package/dist/status.test.js.map +0 -1
- package/dist/ui-bootstrap.test.d.ts +0 -1
- package/dist/ui-bootstrap.test.js +0 -479
- package/dist/ui-bootstrap.test.js.map +0 -1
- package/dist/ui-builder.test.d.ts +0 -1
- package/dist/ui-builder.test.js +0 -272
- package/dist/ui-builder.test.js.map +0 -1
- package/dist/ui-command-quoting.test.d.ts +0 -1
- package/dist/ui-command-quoting.test.js +0 -95
- package/dist/ui-command-quoting.test.js.map +0 -1
- package/dist/ui-harness.d.ts +0 -20
- package/dist/ui-harness.js +0 -40
- package/dist/ui-harness.js.map +0 -1
- package/dist/ui-harness.test.d.ts +0 -1
- package/dist/ui-harness.test.js +0 -30
- package/dist/ui-harness.test.js.map +0 -1
- package/dist/ui-inline.test.d.ts +0 -1
- package/dist/ui-inline.test.js +0 -90
- package/dist/ui-inline.test.js.map +0 -1
- package/dist/ui-interactions.test.d.ts +0 -1
- package/dist/ui-interactions.test.js +0 -489
- package/dist/ui-interactions.test.js.map +0 -1
- package/dist/ui.test.d.ts +0 -1
- package/dist/ui.test.js +0 -283
- package/dist/ui.test.js.map +0 -1
package/README.md
CHANGED
|
@@ -28,6 +28,8 @@ Works as a **CLI** and as a **skill** in Claude Code, Copilot, Goose, and Bob.
|
|
|
28
28
|
|
|
29
29
|
## Install
|
|
30
30
|
|
|
31
|
+
Requires Node.js 22 or newer.
|
|
32
|
+
|
|
31
33
|
### CLI
|
|
32
34
|
|
|
33
35
|
```bash
|
|
@@ -40,9 +42,29 @@ Or just run it without installing:
|
|
|
40
42
|
npx @hivecommons/promptargs help
|
|
41
43
|
```
|
|
42
44
|
|
|
43
|
-
### As
|
|
45
|
+
### As an Agent Skill
|
|
46
|
+
|
|
47
|
+
promptargs ships an [Agent Skill](https://agentskills.io/specification) at [`skills/promptargs/SKILL.md`](skills/promptargs/SKILL.md), loaded by GitHub Copilot (CLI, cloud agent, VS Code agent mode) and Claude Code.
|
|
48
|
+
|
|
49
|
+
**With the GitHub CLI** (2.90.0 or later):
|
|
50
|
+
```bash
|
|
51
|
+
gh skill install hivecommons/promptargs promptargs
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Manually** (copy the `skills/promptargs/` directory):
|
|
55
|
+
```bash
|
|
56
|
+
# Copilot
|
|
57
|
+
mkdir -p ~/.copilot/skills
|
|
58
|
+
cp -r skills/promptargs ~/.copilot/skills/
|
|
59
|
+
|
|
60
|
+
# Claude Code
|
|
61
|
+
mkdir -p ~/.claude/skills
|
|
62
|
+
cp -r skills/promptargs ~/.claude/skills/
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Use `.github/skills/` or `.claude/skills/` inside a project instead to share it with your team.
|
|
44
66
|
|
|
45
|
-
|
|
67
|
+
### As a Slash Command (other tools)
|
|
46
68
|
|
|
47
69
|
**Claude Code:**
|
|
48
70
|
```bash
|
|
@@ -65,8 +87,6 @@ curl -o ~/.bob/skills/promptargs.md \
|
|
|
65
87
|
https://raw.githubusercontent.com/hivecommons/promptargs/main/.bob/skills/promptargs.md
|
|
66
88
|
```
|
|
67
89
|
|
|
68
|
-
**Copilot:** Automatically detected from `.github/copilot-instructions.md` when you clone this repo.
|
|
69
|
-
|
|
70
90
|
---
|
|
71
91
|
|
|
72
92
|
## Quick Start (3 steps)
|
|
@@ -122,7 +142,11 @@ A blank looks like this: `{{name}}`
|
|
|
122
142
|
|
|
123
143
|
A blank with a default looks like this: `{{name=hello}}` (promptargs extension)
|
|
124
144
|
|
|
125
|
-
Padding inside the braces is fine too — `{{ name }}` and `{{ name=hello }}` mean the same thing.
|
|
145
|
+
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).
|
|
146
|
+
|
|
147
|
+
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.
|
|
148
|
+
|
|
149
|
+
A default may appear on any occurrence of a blank (`{{name}} … {{name=hello}}`); if two occurrences give different defaults, the first one wins.
|
|
126
150
|
|
|
127
151
|
That's the basics. Mustache comments (`{{! ignore me}}`) work as documented and are safe to use.
|
|
128
152
|
|
|
@@ -204,6 +228,7 @@ Status lines showing iteration progress go to stderr:
|
|
|
204
228
|
|--------|-------------|
|
|
205
229
|
| `--file=a.go,b.go,c.go` | Comma-separated list |
|
|
206
230
|
| `--file="src/*.go"` | Glob pattern (expands to matching files) |
|
|
231
|
+
| `--file="src/**/*.go"` | Recursive glob (`**` matches any depth) |
|
|
207
232
|
| `--file=@list.txt` | Reads one value per line from a file |
|
|
208
233
|
|
|
209
234
|
### Multiple arrays: zip vs cross-product
|
|
@@ -222,6 +247,34 @@ promptargs "Review {{file}} for {{focus}}" \
|
|
|
222
247
|
✅ [3/3]: file=db.go focus=correctness
|
|
223
248
|
```
|
|
224
249
|
|
|
250
|
+
When arrays have different lengths, the number of runs is the length of the longest array, and shorter arrays repeat (cycle around):
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
promptargs "Review {{file}} for {{focus}}" \
|
|
254
|
+
--file=api.go,auth.go,db.go \
|
|
255
|
+
--focus=security
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
✅ [1/3]: file=api.go focus=security
|
|
260
|
+
✅ [2/3]: file=auth.go focus=security
|
|
261
|
+
✅ [3/3]: file=db.go focus=security
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Or with two unequal arrays:
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
promptargs "Review {{file}} for {{focus}}" \
|
|
268
|
+
--file=a.go,b.go,c.go \
|
|
269
|
+
--focus=x,y
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
✅ [1/3]: file=a.go focus=x
|
|
274
|
+
✅ [2/3]: file=b.go focus=y
|
|
275
|
+
✅ [3/3]: file=c.go focus=x
|
|
276
|
+
```
|
|
277
|
+
|
|
225
278
|
**Cross-product mode (`--cross`):** every combination of every value:
|
|
226
279
|
|
|
227
280
|
```bash
|
|
@@ -245,12 +298,6 @@ promptargs "Review {{file}} for {{focus}}" \
|
|
|
245
298
|
|
|
246
299
|
3 files × 3 focuses = 9 runs. Use `--cross` when you want the full matrix.
|
|
247
300
|
|
|
248
|
-
By default, array iterations run one at a time and print as they finish. Add `--parallel` to run every iteration at once and print all results together:
|
|
249
|
-
|
|
250
|
-
```bash
|
|
251
|
-
promptargs review --file=api.go,auth.go,db.go --parallel
|
|
252
|
-
```
|
|
253
|
-
|
|
254
301
|
---
|
|
255
302
|
|
|
256
303
|
## Where Templates Live
|
|
@@ -262,6 +309,8 @@ promptargs review --file=api.go,auth.go,db.go --parallel
|
|
|
262
309
|
|
|
263
310
|
Project templates override personal ones with the same name.
|
|
264
311
|
|
|
312
|
+
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).
|
|
313
|
+
|
|
265
314
|
---
|
|
266
315
|
|
|
267
316
|
## Auto-Magic Variables ✨
|
|
@@ -301,7 +350,7 @@ In the **Builder UI** (`promptargs ui`), click "Show terminal env" to see all av
|
|
|
301
350
|
|
|
302
351
|
Common useful env vars: `NODE_ENV`, `AWS_REGION`, `CI`, `USER`, `EDITOR`, `PATH`, `SHELL`.
|
|
303
352
|
|
|
304
|
-
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.
|
|
353
|
+
Credential-looking names are intentionally **excluded** from auto-detection: anything containing `TOKEN`, `SECRET`, `PASSWORD`/`PASSWD`/`PASSPHRASE`, `CREDENTIAL`/`CREDENTIALS`/`CREDS`, `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_…`, `hf_`, `pypi-`, `dop_v1_`, `lin_api_`, `shpat_`, `SG.`, `dapi`, `glc_`, `ya29.`, …). 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.
|
|
305
354
|
|
|
306
355
|
### Priority
|
|
307
356
|
|
|
@@ -350,7 +399,7 @@ Don't want to memorize flags? Open the visual builder:
|
|
|
350
399
|
promptargs ui
|
|
351
400
|
```
|
|
352
401
|
|
|
353
|
-
Opens a browser at `http://localhost:3700
|
|
402
|
+
Opens a browser at `http://localhost:3700/?t=<token>` — the token is random per run and printed at startup — with:
|
|
354
403
|
|
|
355
404
|
- **Preset examples** — 8 clickable templates (review, explain, fix, test, migrate, security, docs, refactor)
|
|
356
405
|
- **Template editor** — type your template, variables auto-populate below
|
|
@@ -373,12 +422,37 @@ promptargs ui --port=4000
|
|
|
373
422
|
|
|
374
423
|
promptargs 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.
|
|
375
424
|
|
|
376
|
-
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`)
|
|
425
|
+
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](#auto-magic-variables-)) — is never reachable from other machines on your network, nor from other accounts sharing the same machine's loopback interface.
|
|
426
|
+
|
|
427
|
+
**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.
|
|
377
428
|
|
|
378
429
|
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.
|
|
379
430
|
|
|
380
431
|
---
|
|
381
432
|
|
|
433
|
+
## Use as a Library
|
|
434
|
+
|
|
435
|
+
The package also exports its building blocks as an ES module (Node.js 22+). Install it first with `npm install @hivecommons/promptargs`.
|
|
436
|
+
|
|
437
|
+
```js
|
|
438
|
+
import { parseVars, expand } from '@hivecommons/promptargs';
|
|
439
|
+
|
|
440
|
+
const template = 'Review {{file}} for {{focus=correctness}} issues.';
|
|
441
|
+
|
|
442
|
+
parseVars(template);
|
|
443
|
+
// [{ name: 'file', ... }, { name: 'focus', defaultValue: 'correctness', ... }]
|
|
444
|
+
|
|
445
|
+
expand(template, { file: 'src/app.ts', focus: 'security' });
|
|
446
|
+
// 'Review src/app.ts for security issues.'
|
|
447
|
+
|
|
448
|
+
expand(template, { file: 'src/app.ts' });
|
|
449
|
+
// 'Review src/app.ts for correctness issues.' (defaults fill missing values)
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
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`.
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
382
456
|
## Write Your Own Template
|
|
383
457
|
|
|
384
458
|
Create a file in `.prompts/` with any name ending in `.md`:
|
|
@@ -415,13 +489,13 @@ promptargs review --file=src/main.ts --no-interactive | claude -p "do this revie
|
|
|
415
489
|
# Goose
|
|
416
490
|
promptargs review --file=src/main.ts --no-interactive | goose run
|
|
417
491
|
|
|
418
|
-
# Copilot
|
|
419
|
-
promptargs review --file=src/main.ts --no-interactive
|
|
492
|
+
# Copilot CLI (needs the standalone `copilot` CLI, installed and signed in)
|
|
493
|
+
copilot -p "$(promptargs review --file=src/main.ts --no-interactive)"
|
|
420
494
|
```
|
|
421
495
|
|
|
422
496
|
### As a skill inside your AI tool
|
|
423
497
|
|
|
424
|
-
If you installed the skill (see [Install](#as-
|
|
498
|
+
If you installed the skill (see [Install](#as-an-agent-skill)), use it directly inside your session:
|
|
425
499
|
|
|
426
500
|
**Claude Code:**
|
|
427
501
|
```
|
|
@@ -430,7 +504,7 @@ If you installed the skill (see [Install](#as-a-skill)), use it directly inside
|
|
|
430
504
|
|
|
431
505
|
**Goose / Bob:** The skill is automatically available after install — ask your agent to "use promptargs" or run a template.
|
|
432
506
|
|
|
433
|
-
**Copilot:**
|
|
507
|
+
**Copilot:** Installed skills load automatically; ask Copilot to use promptargs.
|
|
434
508
|
|
|
435
509
|
---
|
|
436
510
|
|
|
@@ -448,16 +522,28 @@ If you installed the skill (see [Install](#as-a-skill)), use it directly inside
|
|
|
448
522
|
| `promptargs env` | Show auto-detected variable values |
|
|
449
523
|
| `--no-interactive` | Skip questions, use defaults only |
|
|
450
524
|
| `--cross` | Cross-product mode (all combinations) |
|
|
451
|
-
| `--parallel` | Run array iterations in parallel |
|
|
452
525
|
| `--json` | Output as JSON |
|
|
453
526
|
| `--status` | Output status line only |
|
|
454
527
|
| `... \| claude -p "do this"` | Pipe to Claude |
|
|
455
528
|
| `... \| goose run` | Pipe to Goose |
|
|
456
529
|
|
|
530
|
+
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.
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## Contributing & Community
|
|
535
|
+
|
|
536
|
+
promptargs is part of [Hive Commons](https://hivecommons.dev), a family of tools for working with AI agents.
|
|
537
|
+
|
|
538
|
+
- Want to contribute? See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, checks, and pull request guidelines.
|
|
539
|
+
- Found a bug or have an idea? Open an [issue](https://github.com/hivecommons/promptargs/issues).
|
|
540
|
+
- Reporting a security vulnerability? Follow [SECURITY.md](SECURITY.md) to report it privately, not through public issues.
|
|
541
|
+
- Please follow the [Hive Commons Code of Conduct](https://github.com/hivecommons/.github/blob/main/CODE_OF_CONDUCT.md).
|
|
542
|
+
|
|
457
543
|
---
|
|
458
544
|
|
|
459
545
|
## License
|
|
460
546
|
|
|
461
547
|
Apache-2.0
|
|
462
548
|
|
|
463
|
-
Pirate flag icon: [Twemoji](https://
|
|
549
|
+
Pirate flag icon: [Twemoji](https://github.com/twitter/twemoji), [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/).
|
package/dist/autodetect.js
CHANGED
|
@@ -2,9 +2,20 @@
|
|
|
2
2
|
* Auto-detect variable values from the current environment.
|
|
3
3
|
*/
|
|
4
4
|
import { execSync } from 'node:child_process';
|
|
5
|
+
// gh is the only network call on the UI startup path; bound it so a stalled gh
|
|
6
|
+
// (hung proxy, expired auth) cannot hang startup.
|
|
7
|
+
const GH_TIMEOUT_MS = 5000;
|
|
8
|
+
// execSync's default 1 MiB maxBuffer makes `git diff` on a large staged change
|
|
9
|
+
// throw ENOBUFS, which the catch below turns into a silent "nothing detected"
|
|
10
|
+
// (#281). Raise it so large diffs are returned rather than dropped.
|
|
11
|
+
const GIT_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
|
|
5
12
|
function git(cmd) {
|
|
6
13
|
try {
|
|
7
|
-
const out = execSync(`git ${cmd}`, {
|
|
14
|
+
const out = execSync(`git ${cmd}`, {
|
|
15
|
+
encoding: 'utf8',
|
|
16
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
17
|
+
maxBuffer: GIT_MAX_BUFFER_BYTES,
|
|
18
|
+
}).trim();
|
|
8
19
|
// Success with empty output (detached HEAD for `branch --show-current`,
|
|
9
20
|
// clean tree for `diff`) is "nothing detected", not an empty value —
|
|
10
21
|
// otherwise it would override the template default and skip the prompt.
|
|
@@ -36,6 +47,7 @@ const DETECTORS = {
|
|
|
36
47
|
const out = execSync('gh pr view --json number --jq .number', {
|
|
37
48
|
encoding: 'utf8',
|
|
38
49
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
50
|
+
timeout: GH_TIMEOUT_MS,
|
|
39
51
|
}).trim();
|
|
40
52
|
return out || undefined;
|
|
41
53
|
}
|
|
@@ -44,7 +56,7 @@ const DETECTORS = {
|
|
|
44
56
|
}
|
|
45
57
|
},
|
|
46
58
|
user: () => git('config user.name'),
|
|
47
|
-
date: () => new Date().
|
|
59
|
+
date: () => new Date().toLocaleDateString('sv-SE'),
|
|
48
60
|
};
|
|
49
61
|
export const AUTODETECT_VARS = Object.keys(DETECTORS);
|
|
50
62
|
// Env var names that look like credentials. The implicit process.env fallback
|
|
@@ -55,23 +67,27 @@ export const AUTODETECT_VARS = Object.keys(DETECTORS);
|
|
|
55
67
|
// cwd) and AUTHOR stay detectable while GITHUB_PAT, SIGNING_KEY, MYSQL_PWD and
|
|
56
68
|
// AUTH_HEADER do not.
|
|
57
69
|
const SENSITIVE_ENV_PATTERN = new RegExp([
|
|
58
|
-
'TOKEN', 'SECRET', 'PASSWORD', 'PASSWD', 'PASSPHRASE', '
|
|
70
|
+
'TOKEN', 'SECRET', 'PASSWORD', 'PASSWD', 'PASSPHRASE', 'CREDENTIALS?',
|
|
59
71
|
'API_?KEY', 'ACCESS_KEY', 'PRIVATE_KEY', 'BEARER', 'COOKIE', 'WEBHOOK',
|
|
60
|
-
'JWT', 'HMAC', 'OAUTH', 'CONN(?:ECTION)?_?STR(?:ING)?',
|
|
72
|
+
'JWT', 'HMAC', 'OAUTH', 'AUTHORI[SZ]ATION', 'CONN(?:ECTION)?_?STR(?:ING)?',
|
|
61
73
|
'(?:^|_)AUTH(?:_|$)', '(?:^|_)KEYS?(?:_|$)', '_PWD(?:_|$)',
|
|
62
|
-
'(?:^|_)PAT(?:_|$)', '(?:^|_)PASS(?:_|$)', '(?:^|_)DSN(?:_|$)',
|
|
74
|
+
'(?:^|_)PAT(?:_|$)', '(?:^|_)PASS(?:_|$)', '(?:^|_)DSN(?:_|$)', '(?:^|_)CREDS(?:_|$)',
|
|
63
75
|
].join('|'), 'i');
|
|
64
76
|
export function isSensitiveEnvName(name) {
|
|
65
77
|
return SENSITIVE_ENV_PATTERN.test(name);
|
|
66
78
|
}
|
|
67
79
|
// Values that are credentials regardless of what the variable is called:
|
|
68
80
|
// a URL carrying a password in its userinfo (DATABASE_URL, REDIS_URL,
|
|
69
|
-
// MONGO_URI, SENTRY_DSN), PEM blocks, JWTs,
|
|
70
|
-
// stamp on their tokens so
|
|
81
|
+
// MONGO_URI, SENTRY_DSN), PEM blocks, JWTs, HTTP Authorization header values
|
|
82
|
+
// (Bearer/Basic), and the fixed prefixes vendors stamp on their tokens so
|
|
83
|
+
// scanners can recognise them (GitHub, GitLab, OpenAI, Stripe, Slack, AWS,
|
|
84
|
+
// Google, npm, Vault, Hugging Face, PyPI, DigitalOcean, Linear, Shopify,
|
|
85
|
+
// SendGrid, Databricks, Grafana).
|
|
71
86
|
const SENSITIVE_ENV_VALUE_PATTERN = new RegExp([
|
|
72
87
|
'^[a-z][a-z0-9+.-]*://[^/\\s:@]*:[^/\\s@]+@',
|
|
73
88
|
'-----BEGIN ',
|
|
74
89
|
'^eyJ[\\w-]+\\.eyJ[\\w-]+\\.',
|
|
90
|
+
'^(?:Bearer|Basic)\\s+\\S+',
|
|
75
91
|
'^(?:gh[pousr]_|github_pat_)[A-Za-z0-9_]{20,}',
|
|
76
92
|
'^glpat-[\\w-]{20,}',
|
|
77
93
|
'^sk-[A-Za-z0-9_-]{20,}',
|
|
@@ -81,22 +97,33 @@ const SENSITIVE_ENV_VALUE_PATTERN = new RegExp([
|
|
|
81
97
|
'^AIza[\\w-]{35}$',
|
|
82
98
|
'^npm_[A-Za-z0-9]{36}$',
|
|
83
99
|
'^hvs\\.[\\w-]{20,}',
|
|
100
|
+
'^hf_[A-Za-z0-9]{30,}',
|
|
101
|
+
'^pypi-AgEI[\\w-]{20,}',
|
|
102
|
+
'^dop_v1_[a-f0-9]{60,}',
|
|
103
|
+
'^lin_api_[A-Za-z0-9]{20,}',
|
|
104
|
+
'^shp(?:at|ss|ca|pa)_[a-f0-9]{30,}',
|
|
105
|
+
'^SG\\.[\\w-]{20,}\\.[\\w-]{20,}',
|
|
106
|
+
'^dapi[a-f0-9]{30,}',
|
|
107
|
+
'^glc_[A-Za-z0-9+/=]{30,}',
|
|
108
|
+
'^ya29\\.[\\w-]{20,}',
|
|
84
109
|
].join('|'), 'i');
|
|
85
110
|
export function isSensitiveEnvValue(value) {
|
|
86
111
|
return SENSITIVE_ENV_VALUE_PATTERN.test(value);
|
|
87
112
|
}
|
|
88
113
|
export function autodetect(varName) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
114
|
+
// Own-property check: {{constructor}} / {{toString}} must not resolve to
|
|
115
|
+
// Object.prototype members.
|
|
116
|
+
if (Object.hasOwn(DETECTORS, varName))
|
|
117
|
+
return DETECTORS[varName]();
|
|
92
118
|
// Fall back to terminal environment variables — but never implicitly expand
|
|
93
119
|
// credential-looking names ({{GITHUB_TOKEN}} in a repo template must not
|
|
94
120
|
// exfiltrate secrets into the generated prompt) or credential-shaped values
|
|
95
121
|
// under innocuous names ({{DATABASE_URL}}). Explicit --flags still work.
|
|
96
|
-
if (isSensitiveEnvName(varName))
|
|
122
|
+
if (isSensitiveEnvName(varName) || !Object.hasOwn(process.env, varName))
|
|
97
123
|
return undefined;
|
|
98
124
|
const value = process.env[varName];
|
|
99
|
-
|
|
125
|
+
// Treat empty env var as not detected, matching --FOO= flags and git detectors (see #91).
|
|
126
|
+
if (value === undefined || value === '' || isSensitiveEnvValue(value))
|
|
100
127
|
return undefined;
|
|
101
128
|
return value;
|
|
102
129
|
}
|
package/dist/autodetect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autodetect.js","sourceRoot":"","sources":["../src/autodetect.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,SAAS,GAAG,CAAC,GAAW;IACtB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,GAAG,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"autodetect.js","sourceRoot":"","sources":["../src/autodetect.ts"],"names":[],"mappings":"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"}
|