{"_id":"mint-id","_rev":"4-8abf61fc7aea3fbd5b705d024d554aae","name":"mint-id","dist-tags":{"alpha":"0.0.1-alpha","latest":"1.0.2"},"versions":{"0.0.1-alpha":{"name":"mint-id","version":"0.0.1-alpha","keywords":["id","identifier","token","llm","csprng","wordlist","diceware"],"author":{"name":"Abir Taheer"},"license":"MIT","_id":"mint-id@0.0.1-alpha","maintainers":[{"name":"abir-taheer","email":"abir@taheer.me"}],"homepage":"https://github.com/abir-taheer/mint-id#readme","bugs":{"url":"https://github.com/abir-taheer/mint-id/issues"},"dist":{"shasum":"96d87bf5afd8acdbc3d3191af8b3f072b9cb09fd","tarball":"https://registry.npmjs.org/mint-id/-/mint-id-0.0.1-alpha.tgz","fileCount":14,"integrity":"sha512-X3xCDdmprsEgGpKU4OzdMKZkac5qZiVSey1p/kWwXHmfD598fZmk8cuZ4/dwPoVtOcI82Y/MFWs4axBP4TkHNg==","signatures":[{"sig":"MEQCIHC6g9u6swOjuyfOin9XiXCfKFS97M1TlkZDp0CP7WH9AiAOF4DsMr39p+2JciwEqR111mAO5OlltDWenoOKg+lHOg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":14255986},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=14.10.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./extended":{"types":"./dist/extended.d.ts","import":"./dist/extended.js","require":"./dist/extended.cjs"}},"gitHead":"83eee8a146504262eb490782711f4f8ef4ea60e7","scripts":{"test":"vitest run","build":"tsup","type-check":"tsc --noEmit"},"_npmUser":{"name":"abir-taheer","email":"abir@taheer.me"},"repository":{"url":"git+https://github.com/abir-taheer/mint-id.git","type":"git"},"_npmVersion":"10.8.2","description":"Cryptographically secure identifiers using single-token dictionary words","directories":{},"_nodeVersion":"20.18.3","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.3"},"_npmOperationalInternal":{"tmp":"tmp/mint-id_0.0.1-alpha_1771047250764_0.17651987213336695","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"mint-id","version":"1.0.0","keywords":["id","identifier","token","llm","csprng","wordlist","diceware"],"author":{"name":"Abir Taheer"},"license":"MIT","_id":"mint-id@1.0.0","maintainers":[{"name":"abir-taheer","email":"abir@taheer.me"}],"homepage":"https://github.com/abir-taheer/mint-id#readme","bugs":{"url":"https://github.com/abir-taheer/mint-id/issues"},"dist":{"shasum":"42888abb1938ab8c525b9db10da2b15f1de8b314","tarball":"https://registry.npmjs.org/mint-id/-/mint-id-1.0.0.tgz","fileCount":14,"integrity":"sha512-I8XD2QBl3lQek4t81gY5wgCU7C+SnfAte2zqA3wyJYdwyZAj3KUvFtcek+5svKXmsVI3K28ijeBqUg6Ow377mg==","signatures":[{"sig":"MEUCIQDH8+3xaEqmD1NLFD12pgluBYJVc71XKxbrSLkvkAlPkgIgLap/1Wr5BinVdUY+Syo6StajF3BVF9x0lCOpWmlDHQk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/mint-id@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":14255980},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=14.10.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./extended":{"types":"./dist/extended.d.ts","import":"./dist/extended.js","require":"./dist/extended.cjs"}},"gitHead":"1b2724683e9dcf1a96ca38fd8627da51c4b9a22a","scripts":{"test":"vitest run","build":"tsup","type-check":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:296a0796-7714-4491-890a-bb7090d7168a"}},"repository":{"url":"git+https://github.com/abir-taheer/mint-id.git","type":"git"},"_npmVersion":"11.6.2","description":"Cryptographically secure identifiers using single-token dictionary words","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.3"},"_npmOperationalInternal":{"tmp":"tmp/mint-id_1.0.0_1771047790575_0.9546098630730293","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"mint-id","version":"1.0.1","keywords":["id","identifier","token","llm","csprng","wordlist","diceware"],"author":{"name":"Abir Taheer"},"license":"MIT","_id":"mint-id@1.0.1","maintainers":[{"name":"abir-taheer","email":"abir@taheer.me"}],"homepage":"https://github.com/abir-taheer/mint-id#readme","bugs":{"url":"https://github.com/abir-taheer/mint-id/issues"},"dist":{"shasum":"616a731854872c4e7d8e05acaa712e416bc89177","tarball":"https://registry.npmjs.org/mint-id/-/mint-id-1.0.1.tgz","fileCount":14,"integrity":"sha512-qkG0052qOL+eZqERq7YbF2bFYjAL2v4nDXqYQPi2qdXo3YxSwUmJChn9pQbLVikaj176T434ueChEXy6OrM4Vw==","signatures":[{"sig":"MEYCIQDpMjXMuHCCJFQQAdI1WvT9x5S9ytr83XfMzsNA854mQAIhAPfEdFZG+gS+p3L1p1g1HYxqsyUDuGBxi0xAkJP1iu2b","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/mint-id@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":14255980},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=14.10.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./extended":{"types":"./dist/extended.d.ts","import":"./dist/extended.js","require":"./dist/extended.cjs"}},"gitHead":"d19c8bb4ec5a0e188dc009106deb32a8ccd0bb71","scripts":{"test":"vitest run","build":"tsup","type-check":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:296a0796-7714-4491-890a-bb7090d7168a"}},"repository":{"url":"git+https://github.com/abir-taheer/mint-id.git","type":"git"},"_npmVersion":"11.6.2","description":"Cryptographically secure identifiers using single-token dictionary words","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.3"},"_npmOperationalInternal":{"tmp":"tmp/mint-id_1.0.1_1771048019144_0.07342042291737383","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"mint-id","version":"1.0.2","description":"Cryptographically secure identifiers using single-token dictionary words","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","require":"./dist/index.cjs","import":"./dist/index.js"},"./extended":{"types":"./dist/extended.d.ts","require":"./dist/extended.cjs","import":"./dist/extended.js"}},"typesVersions":{"*":{"extended":["./dist/extended.d.ts"]}},"scripts":{"build":"tsup","test":"vitest run","type-check":"tsc --noEmit"},"keywords":["id","identifier","token","llm","csprng","wordlist","diceware"],"author":{"name":"Abir Taheer"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/abir-taheer/mint-id.git"},"engines":{"node":">=14.10.0"},"devDependencies":{"@types/node":"^25.2.3","tsup":"^8.5.1","typescript":"^5.9.3","vitest":"^4.0.18"},"gitHead":"d2314e90c64f9a87affd7104df119abf6e22deea","_id":"mint-id@1.0.2","bugs":{"url":"https://github.com/abir-taheer/mint-id/issues"},"homepage":"https://github.com/abir-taheer/mint-id#readme","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-/1TDahvR8lvLLG2tS03MGFJEbVfP7OEUsTiRWBSPN3F9q+XCInWtRGloeYu+BEpJvO3A0/fcAQtPjAnBxWE4dA==","shasum":"386973546d278bc25c68dc8598e371f18264fef9","tarball":"https://registry.npmjs.org/mint-id/-/mint-id-1.0.2.tgz","fileCount":14,"unpackedSize":14256082,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/mint-id@1.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAVq069hDiQ6Isc0UoM1x6/m2dcD4fe9eZ3VQT+wmyfjAiBxfvd+Fl9ADDNilUHOeOsPilJdqQZgBJfojWeO4By8vw=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:296a0796-7714-4491-890a-bb7090d7168a"}},"directories":{},"maintainers":[{"name":"abir-taheer","email":"abir@taheer.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mint-id_1.0.2_1775277617018_0.3426696061853427"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-14T05:34:10.699Z","modified":"2026-04-04T04:40:17.516Z","0.0.1-alpha":"2026-02-14T05:34:11.016Z","1.0.0":"2026-02-14T05:43:10.806Z","1.0.1":"2026-02-14T05:46:59.365Z","1.0.2":"2026-04-04T04:40:17.260Z"},"bugs":{"url":"https://github.com/abir-taheer/mint-id/issues"},"author":{"name":"Abir Taheer"},"license":"MIT","homepage":"https://github.com/abir-taheer/mint-id#readme","keywords":["id","identifier","token","llm","csprng","wordlist","diceware"],"repository":{"type":"git","url":"git+https://github.com/abir-taheer/mint-id.git"},"description":"Cryptographically secure identifiers using single-token dictionary words","maintainers":[{"name":"abir-taheer","email":"abir@taheer.me"}],"readme":"# mint-id\n\nCryptographically secure identifiers using single-token dictionary words. Zero runtime dependencies. Works in Node, Cloudflare Workers, Deno, and browsers.\n\n```typescript\nimport { mintId } from 'mint-id';\n\nmintId();\n// → \"guide_pull_rich_deep_fast_sale_club_warm_bold_true_gain_plan\"\n```\n\nEvery word in the output tokenizes to exactly **1 token** across all major LLM tokenizers. A pre-signed S3 URL costs 229 tokens. A mint-id with equivalent entropy costs 24.\n\n## Install\n\n```bash\nnpm install mint-id\n```\n\n## Quick Start\n\n```typescript\nimport { mintId, entropy, wordlist } from 'mint-id';\n\n// Default: 12 words, ~133 bits entropy, universal compatibility\nmintId();\n\n// Optimize for a specific model (larger wordlist = more entropy per word)\nmintId({ model: 'claude-opus-4-6' });\n\n// Target a minimum entropy level\nmintId({ minEntropy: 256 });\n\n// Customize format\nmintId({ words: 8, delimiter: '-' });\n```\n\n## Extended Mode\n\nNeed a larger word pool? Import from `mint-id/extended` to unlock `maxTokens`:\n\n```typescript\nimport { mintId, wordlist } from 'mint-id/extended';\n\n// Allow words up to 2 tokens each — much larger pool\nmintId({ maxTokens: 2 });\n\nwordlist({ maxTokens: 1 }).length;  // 2,220 (same as base)\nwordlist({ maxTokens: 2 }).length;  // ~100k words\nwordlist({ maxTokens: 3 }).length;  // ~195k words\n```\n\nThe extended entry point includes all 234k dictionary words with per-tokenizer token counts. **Tree-shakeable** — your bundler only includes the extended data if you import from `mint-id/extended`.\n\n| Entry point | Bundle size | Word pool | `maxTokens` |\n|-------------|-------------|-----------|-------------|\n| `mint-id` | ~173 KB | 10k single-token words | N/A (always 1) |\n| `mint-id/extended` | ~6.6 MB | 234k words | 1–∞ |\n\n## API\n\n### `mintId(options?): string`\n\nGenerate a cryptographically secure identifier.\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `words` | `number` | `12` | Number of words. Ignored if `minEntropy` is set. |\n| `minEntropy` | `number` | — | Minimum bits of entropy. Overrides `words`. |\n| `delimiter` | `string` | `'_'` | Separator between words. |\n| `model` | `string \\| string[]` | — | Model(s) to optimize for. |\n| `tokenizer` | `string \\| string[]` | — | Tokenizer(s) to target. Takes precedence over `model`. |\n| `maxTokens` | `number` | `1` | Max tokens per word. **Extended only.** |\n\nWhen no `model` or `tokenizer` is specified, uses the **universal** wordlist (words that meet the token threshold in all supported tokenizers).\n\nWhen multiple models or tokenizers are specified, uses words that meet the threshold in **all** of them (intersection).\n\n### `entropy(options?): EntropyInfo`\n\nCalculate entropy for a given configuration without generating an ID.\n\n```typescript\nentropy();\n// → { bits: 133.4, poolSize: 2220, bitsPerWord: 11.12, words: 12 }\n\nentropy({ model: 'claude-opus-4-6' });\n// → { bits: 154.8, poolSize: 7629, bitsPerWord: 12.9, words: 12 }\n```\n\n### `wordlist(options?): string[]`\n\nGet the raw wordlist for a model/tokenizer configuration.\n\n```typescript\nwordlist().length;                             // 2220 (universal)\nwordlist({ model: 'claude-opus-4-6' }).length; // 7629\nwordlist({ tokenizer: 'gpt2' }).length;        // 3495\n```\n\n## Error Classes\n\nAll errors extend `MintIdError` for easy catch-all handling:\n\n```typescript\nimport { UnknownModelError, UnknownTokenizerError, EmptyWordlistError } from 'mint-id';\n\ntry {\n  mintId({ model: 'nonexistent' });\n} catch (e) {\n  if (e instanceof UnknownModelError) {\n    console.log(e.model); // \"nonexistent\"\n  }\n}\n```\n\n| Class | Thrown when |\n|-------|-----------|\n| `UnknownModelError` | Unrecognized model name |\n| `UnknownTokenizerError` | Unrecognized tokenizer name |\n| `EmptyWordlistError` | Wordlist is empty after filtering |\n\n## Supported Models & Tokenizers\n\n| Model | Tokenizer | Pool size | Bits/word |\n|-------|-----------|-----------|-----------|\n| `claude-opus-4-6`, `claude-sonnet-4-5`, `claude-haiku-4-5`, etc. | `claude` | 7,629 | 12.90 |\n| `gpt-4`, `gpt-4-turbo`, `gpt-3.5-turbo` | `cl100k_base` | 4,914 | 12.26 |\n| `gpt-4o`, `gpt-5`, `o1`, `o3`, `o4-mini`, etc. | `o200k_base` | 5,640 | 12.46 |\n| `gpt-2`, `gpt-3` | `gpt2` | 3,495 | 11.77 |\n| *(default — all models)* | universal | 2,220 | 11.12 |\n\n**Tokenizer aliases**: `o200k_harmony` → `o200k_base`, `p50k_base`/`p50k_edit`/`r50k_base` → `gpt2`\n\n## Why Single-Token Words?\n\nLLM tokenizers split text into tokens. Most English words tokenize to 1 token, but random hex/UUIDs tokenize poorly:\n\n| Identifier type | Example | Tokens | Entropy (bits) | Bits/token |\n|-----------------|---------|--------|----------------|------------|\n| Pre-signed S3 URL | `https://bucket.s3...&Signature=abc123` | 229 | ~330 | 1.44 |\n| UUID v4 | `550e8400-e29b-41d4-a716-446655440000` | 25 | 122 | 4.88 |\n| SHA-256 (hex) | `e3b0c44298fc1c149afb...` | 43 | 256 | 5.95 |\n| **mint-id (12 words)** | `guide_pull_rich_deep_fast_sale_...` | **24** | **133** | **5.56** |\n| **mint-id (6 words, claude)** | `guide_pull_rich_deep_fast_sale` | **12** | **77** | **6.44** |\n\nSingle-token words achieve **5.5–6.4 bits per token** vs UUIDs at 4.9 bits/token. Over thousands of API calls, this saves significant token budget.\n\n### Token Budget Formula\n\n```\nTotal tokens = base_tokens + (2 × word_count)\n```\n\nWhere `base_tokens` accounts for the delimiter overhead. For underscore-delimited IDs:\n- 6-word ID: ~12 tokens\n- 12-word ID: ~24 tokens\n\n## Entropy Guide\n\n| Words | Bits (universal) | Comparable to | Use case |\n|-------|-----------------|---------------|----------|\n| 4 | 44.5 | — | Short-lived, internal |\n| 6 | 66.7 | — | Temporary URLs, session IDs |\n| 8 | 89.0 | — | API keys, medium-term |\n| 10 | 111.2 | — | Long-lived identifiers |\n| 12 | 133.4 | UUID v4 (122 bits) | **Default.** General purpose |\n| 16 | 177.9 | — | High security |\n| 23 | 255.8 | SHA-256 | Maximum security |\n\n## Security\n\n- **CSPRNG**: Uses `crypto.randomInt()` exclusively. No `Math.random()`.\n- **Diceware principle**: Security depends on pool size and word count, not on keeping the wordlist secret.\n- **What an attacker knows**: The wordlist (it's public), the number of words, the delimiter.\n- **What an attacker doesn't know**: Which words were selected (chosen by OS CSPRNG).\n- **Brute force**: 2,220^12 ≈ 2^133 combinations at default settings.\n\n## Runtime Compatibility\n\nNo `fs` or Node.js-specific APIs beyond `crypto.randomInt()`. Works in:\n\n- **Node.js** >= 14.10\n- **Cloudflare Workers** (with `nodejs_compat`)\n- **Deno**\n- **Bun**\n\n## Data Source\n\nWordlists are generated from `/usr/share/dict/words` (macOS, 235,976 entries), filtered by token count. Token counts are verified against:\n\n- **Claude**: Anthropic token counting API\n- **cl100k_base**: tiktoken (GPT-4, GPT-3.5)\n- **o200k_base**: tiktoken (GPT-4o, GPT-5, o-series)\n- **gpt2**: tiktoken (GPT-2, GPT-3)\n\nSource data and export scripts live in [token-counter](https://github.com/abir-taheer/token-counter).\n\n## License\n\nMIT\n","readmeFilename":"README.md"}