Prepare npm publish with README and MIT license

This commit is contained in:
David Ibia
2026-01-12 10:46:12 +01:00
parent 578365a667
commit 40dbd4432f
3 changed files with 213 additions and 3 deletions

189
README.md Normal file
View File

@@ -0,0 +1,189 @@
# envsitter
Safely inspect and match `.env` secrets **without ever printing values**.
`envsitter` is designed for LLM/agent workflows where you want to:
- List keys present in an env source (`.env` file or external provider)
- Check whether a keys value matches a candidate value you provide at runtime ("outside-in")
- Do bulk matching (one candidate against many keys, or candidates-by-key)
- Produce deterministic fingerprints for comparisons/auditing
## Security model (what this tool does and does not do)
- Values are read in-process for comparisons, but **never returned** by the library API and **never printed** by the CLI.
- Deterministic matching uses **HMAC-SHA-256** with a local pepper.
- This avoids publishing raw SHA-256 hashes that are easy to dictionary-guess.
- Candidate secrets should be passed via stdin (`--candidate-stdin`) to avoid shell history.
Non-goals:
- This tool is not a secret manager.
- This tool does not encrypt or relocate `.env` values; it operates on sources in-place.
## Install
```bash
npm install envsitter
```
Or run the CLI without installing globally:
```bash
npx envsitter keys --file .env
```
## Pepper (required for deterministic fingerprints)
`envsitter` uses a local "pepper" as the HMAC key.
Resolution order:
1. `process.env.ENVSITTER_PEPPER` (or `ENV_SITTER_PEPPER`)
2. Pepper file at `.envsitter/pepper` (auto-created if missing)
The pepper file is created with mode `0600` when possible, and `.envsitter/` is gitignored.
## CLI usage
### List keys
```bash
envsitter keys --file .env
```
Filter by key name (regex):
```bash
envsitter keys --file .env --filter-regex "/(KEY|TOKEN|SECRET)/i"
```
### Fingerprint a single key
```bash
envsitter fingerprint --file .env --key OPENAI_API_KEY
```
Outputs JSON containing the keys fingerprint and metadata (never the value).
### Match a candidate against a single key (recommended via stdin)
```bash
node -e "process.stdout.write('candidate-secret')" \
| envsitter match --file .env --key OPENAI_API_KEY --candidate-stdin --json
```
Exit codes:
- `0` match found
- `1` no match
- `2` error/usage
### Match one candidate against multiple keys
```bash
node -e "process.stdout.write('candidate-secret')" \
| envsitter match --file .env --keys OPENAI_API_KEY,ANTHROPIC_API_KEY --candidate-stdin --json
```
### Match one candidate against all keys
```bash
node -e "process.stdout.write('candidate-secret')" \
| envsitter match --file .env --all-keys --candidate-stdin --json
```
### Match candidates-by-key (bulk assignment)
Provide a JSON object mapping key -> candidate value.
```bash
envsitter match-by-key --file .env \
--candidates-json '{"OPENAI_API_KEY":"sk-...","ANTHROPIC_API_KEY":"sk-..."}'
```
For safer input, pass the JSON via stdin:
```bash
cat candidates.json | envsitter match-by-key --file .env --candidates-stdin
```
### Scan for value shapes (no values returned)
```bash
envsitter scan --file .env --detect jwt,url,base64
```
Optionally restrict which keys to scan:
```bash
envsitter scan --file .env --keys-regex "/(JWT|URL)/" --detect jwt,url
```
## Library API
### Basic usage
```ts
import { EnvSitter } from 'envsitter';
const es = EnvSitter.fromDotenvFile('.env');
const keys = await es.listKeys();
const fp = await es.fingerprintKey('OPENAI_API_KEY');
const match = await es.matchCandidate('OPENAI_API_KEY', 'candidate-secret');
```
### Bulk matching
```ts
import { EnvSitter } from 'envsitter';
const es = EnvSitter.fromDotenvFile('.env');
// One candidate tested against a set of keys
const matches = await es.matchCandidateBulk(['OPENAI_API_KEY', 'ANTHROPIC_API_KEY'], 'candidate-secret');
// Candidates-by-key
const byKey = await es.matchCandidatesByKey({
OPENAI_API_KEY: 'sk-...',
ANTHROPIC_API_KEY: 'sk-...'
});
```
### External sources (hooks)
You can load dotenv-formatted output from another tool/secret provider:
```ts
import { EnvSitter } from 'envsitter';
const es = EnvSitter.fromExternalCommand('my-secret-provider', ['export', '--format=dotenv']);
const keys = await es.listKeys();
```
## Development
```bash
npm install
npm run typecheck
npm test
```
Run a single test file:
```bash
npm run build
node --test dist/test/envsitter.test.js
```
Run a single test by name:
```bash
npm run build
node --test --test-name-pattern "outside-in" dist/test/envsitter.test.js
```
## License
MIT. See `LICENSE`.