{"id":26230968,"url":"https://github.com/kazupon/args-tokens","last_synced_at":"2026-05-17T09:08:18.262Z","repository":{"id":276946737,"uuid":"930766423","full_name":"kazupon/args-tokens","owner":"kazupon","description":"parseArgs tokens compatibility and more high-performance parser","archived":false,"fork":false,"pushed_at":"2025-04-14T23:27:05.000Z","size":320,"stargazers_count":16,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-15T00:29:03.797Z","etag":null,"topics":["args","args-parser","cli","parseargs","tokens"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kazupon.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":"kazupon"},"created_at":"2025-02-11T07:11:06.000Z","updated_at":"2025-04-14T23:27:07.000Z","dependencies_parsed_at":"2025-04-06T03:20:18.012Z","dependency_job_id":"b5d4a31e-7456-490d-bbe9-8ea1c98e940e","html_url":"https://github.com/kazupon/args-tokens","commit_stats":null,"previous_names":["kazupon/args-tokens"],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kazupon%2Fargs-tokens","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kazupon%2Fargs-tokens/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kazupon%2Fargs-tokens/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kazupon%2Fargs-tokens/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kazupon","download_url":"https://codeload.github.com/kazupon/args-tokens/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249793922,"owners_count":21326629,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["args","args-parser","cli","parseargs","tokens"],"created_at":"2025-03-12T23:17:52.050Z","updated_at":"2026-05-17T09:08:18.253Z","avatar_url":"https://github.com/kazupon.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# args-tokens\n\n[![Version][npm-version-src]][npm-version-href]\n[![JSR][jsr-src]][jsr-href]\n[![InstallSize][install-size-src]][install-size-href]\n[![CI][ci-src]][ci-href]\n\n\u003e [`parseArgs` tokens](https://nodejs.org/api/util.html#parseargs-tokens) compatibility and more high-performance parser\n\n## ✨ Features\n\n- ✅ High performance\n- ✅ `util.parseArgs` token compatibility\n- ✅ ES Modules and modern JavaScript\n- ✅ Type safe\n- ✅ Zero dependencies\n- ✅ Universal runtime\n\n## 🐱 Motivation\n\n- Although Node.js [`parseArgs`](https://nodejs.org/api/util.html#utilparseargsconfig) can return tokens, that the short options are not in the format I expect. Of course, I recognize the background of [this issue](https://github.com/pkgjs/parseargs/issues/78).\n- `parseArgs` gives the command line args parser a useful util, so the resolution of the options values and the parsing of the tokens are tightly coupled. As a result, Performance is sacrificed. Of course, I recognize that's the trade-off.\n\n## ⏱️ Benchmark\n\nWith [mitata](https://github.com/evanwashere/mitata):\n\n```sh\npnpm bench:mitata\n\n\u003e args-tokens@0.0.0 bench:mitata /path/to/projects/args-tokens\n\u003e node --expose-gc bench/mitata.js\n\nclk: ~2.87 GHz\ncpu: Apple M1 Max\nruntime: node 18.19.1 (arm64-darwin)\n\nbenchmark                                       avg (min … max) p75 / p99    (min … top 1%)\n--------------------------------------------------------------- -------------------------------\nutil.parseArgs                                     4.16 µs/iter   4.20 µs █\n                                            (4.09 µs … 4.29 µs)   4.28 µs ██ ▅▅▅       ▅\n                                        (  1.36 kb …   1.52 kb)   1.37 kb ██▁████▅▅█▅▁██▁▁▅▁█▅█\n\nargs-tokens parse (equivalent to util.parseArgs)   1.65 µs/iter   1.66 µs    █\n                                            (1.61 µs … 1.80 µs)   1.79 µs ▅▃ █▂ ▄\n                                        (  1.95 kb …   2.66 kb)   1.97 kb █████▆█▄▃▃▅▃▁▃▃▁▄▁▁▁▂\n\nargs-tokens parseArgs                            729.56 ns/iter 734.11 ns         █\n                                        (697.43 ns … 797.08 ns) 774.93 ns        ▂█▅▂\n                                        (  2.87 kb …   3.54 kb)   3.11 kb ▂▂▃▇▆▅▆████▃▃▄▂▂▂▂▂▁▂\n\nargs-tokens resolveArgs                          886.78 ns/iter 887.70 ns       █\n                                        (853.96 ns … 978.89 ns) 957.24 ns       █\n                                        (  2.51 kb …   2.87 kb)   2.79 kb ▂▃█▃▄▅█▄▃▂▂▃▃▂▂▂▂▂▁▁▁\n\n                                                 ┌                                            ┐\n                                  util.parseArgs ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 4.16 µs\nargs-tokens parse (equivalent to util.parseArgs) ┤■■■■■■■■■ 1.65 µs\n                           args-tokens parseArgs ┤ 729.56 ns\n                         args-tokens resolveArgs ┤■■ 886.78 ns\n                                                 └                                            ┘\n```\n\nWith [vitest](https://vitest.dev/guide/features.html#benchmarking):\n\n```sh\npnpm bench:vitest\n\n\u003e args-tokens@0.0.0 bench:vitest /path/to/projects/args-tokens\n\u003e vitest bench --run\n\nBenchmarking is an experimental feature.\nBreaking changes might not follow SemVer, please pin Vitest's version when using it.\n\n RUN  v3.0.5 /path/to/projects/args-tokens\n\n\n ✓ bench/vitest.bench.js \u003e parse and resolve 1350ms\n     name                       hz     min     max    mean     p75     p99    p995    p999     rme  samples\n   · util.parseArgs     221,285.36  0.0041  0.2700  0.0045  0.0044  0.0054  0.0063  0.0629  ±0.38%   110643\n   · args-tokens parse  527,127.11  0.0017  0.2153  0.0019  0.0019  0.0023  0.0027  0.0055  ±0.38%   263564   fastest\n\n ✓ bench/vitest.bench.js \u003e parseArgs 1434ms\n     name                   hz     min     max    mean     p75     p99    p995    p999     rme  samples\n   · node:util      235,217.05  0.0039  0.2665  0.0043  0.0042  0.0048  0.0058  0.0139  ±0.43%   117609\n   · args-tokens  1,307,135.24  0.0006  0.1737  0.0008  0.0008  0.0009  0.0010  0.0016  ±0.43%   653568   fastest\n\n BENCH  Summary\n\n  args-tokens parse - bench/vitest.bench.js \u003e parse and resolve\n    2.38x faster than util.parseArgs\n\n  args-tokens - bench/vitest.bench.js \u003e parseArgs\n    5.56x faster than node:util\n\n```\n\n## ❓ What's different about `parseArgs` tokens?\n\nThe token output for the short option `-x=v` is different:\n\n```js\nimport { parseArgs as parseArgsNode } from 'node:util'\nimport { parseArgs } from 'args-tokens'\n\n// Node.js parseArgs tokens\nconst { tokens: tokensNode } = parseArgsNode({\n  allowPositionals: true,\n  strict: false,\n  args: ['-a=1'],\n  tokens: true\n})\nconsole.log(tokensNode)\n\n//   ({\n//     kind: 'option',\n//     name: 'a',\n//     rawName: '-a',\n//     index: 0,\n//     value: undefined,\n//     inlineValue: undefined\n//   },\n//   {\n//     kind: 'option',\n//     name: '=',\n//     rawName: '-=',\n//     index: 0,\n//     value: undefined,\n//     inlineValue: undefined\n//   },\n//   {\n//     kind: 'option',\n//     name: '1',\n//     rawName: '-1',\n//     index: 0,\n//     value: undefined,\n//     inlineValue: undefined\n//   })\n// ]\n\n// args-tokens parseArgs tokens\nconst tokens = parseArgs(['-a=1'])\nconsole.log(tokens)\n\n// [\n//   {\n//     kind: 'option',\n//     name: 'a',\n//     rawName: '-a',\n//     index: 0,\n//     value: undefined,\n//     inlineValue: undefined\n//   },\n//   { kind: 'option', index: 0, value: '1', inlineValue: true }\n// ]\n```\n\n## 💿 Installation\n\n```sh\n# npm\nnpm install --save args-tokens\n\n## yarn\nyarn add args-tokens\n\n## pnpm\npnpm add args-tokens\n```\n\n### 🦕 Deno\n\n```sh\ndeno add jsr:@kazupon/args-tokens\n```\n\n### 🥟 Bun\n\n```sh\nbun add args-tokens\n```\n\n## 🚀 Usage\n\n### Parse args to tokens\n\n`parseArgs` will transform arguments into tokens. This function is useful if you want to analyze arguments yourself based on the tokens. It's faster than `parseArgs` of `node:util` because it only focuses on token transformation.\n\n```js\nimport { parseArgs } from 'args-tokens' // for Node.js and Bun\n// import { parseArgs } from 'jsr:@kazupon/args-tokens' // for Deno\n\nconst tokens = parseArgs(['--foo', 'bar', '-x', '--bar=baz'])\n// do something with using tokens\n// ...\nconsole.log('tokens:', tokens)\n```\n\n## Resolve args values with tokens and arg option schema\n\n`resolveArgs` is a useful function when you want to resolve values from the tokens obtained by `parseArgs`.\n\n```js\nimport { parseArgs, resolveArgs } from 'args-tokens' // for Node.js and Bun\n// import { parseArgs, resolveArgs } from 'jsr:@kazupon/args-tokens' // for Deno\n\nconst args = ['dev', '-p=9131', '--host=example.com', '--mode=production']\nconst tokens = parseArgs(args)\nconst { values, positionals } = resolveArgs(\n  {\n    help: {\n      type: 'boolean',\n      short: 'h'\n    },\n    version: {\n      type: 'boolean',\n      short: 'v'\n    },\n    port: {\n      type: 'number',\n      short: 'p',\n      default: 8080\n    },\n    mode: {\n      type: 'string',\n      short: 'm'\n    },\n    host: {\n      type: 'string',\n      short: 'o',\n      required: true\n    }\n  },\n  tokens\n)\nconsole.log('values:', values)\nconsole.log('positionals:', positionals)\n```\n\n## Convenient argument parsing\n\nUsing the `parse` you can transform the arguments into tokens and resolve the argument values once:\n\n```js\nimport { parse } from 'args-tokens' // for Node.js and Bun\n// import { parse } from 'jsr:@kazupon/args-tokens' // for Deno\n\nconst args = ['dev', '-p=9131', '--host=example.com', '--mode=production']\nconst { values, positionals } = parse(args, {\n  options: {\n    help: {\n      type: 'boolean',\n      short: 'h'\n    },\n    version: {\n      type: 'boolean',\n      short: 'v'\n    },\n    port: {\n      type: 'number',\n      short: 'p',\n      default: 8080\n    },\n    mode: {\n      type: 'string',\n      short: 'm'\n    },\n    host: {\n      type: 'string',\n      short: 'o',\n      required: true\n    }\n  }\n})\nconsole.log('values:', values)\nconsole.log('positionals:', positionals)\n```\n\n## Node.js `parseArgs` tokens compatible\n\nIf you want to use the same short options tokens as returned Node.js `parseArgs`, you can use `allowCompatible` parse option on `parseArgs`:\n\n```js\nimport { parseArgs as parseArgsNode } from 'node:util'\nimport { parseArgs } from 'args-tokens'\nimport { deepStrictEqual } from 'node:assert'\n\nconst args = ['-a=1', '2']\n\n// Node.js parseArgs tokens\nconst { tokens: tokensNode } = parseArgsNode({\n  allowPositionals: true,\n  strict: false,\n  args,\n  tokens: true\n})\n\n// args-tokens parseArgs tokens\nconst tokens = parseArgs(['-a=1'], { allowCompatible: true }) // add `allowCompatible` option\n\n// validate\ndeepStrictEqual(tokensNode, tokens)\n```\n\n## `ArgSchema` Reference\n\nThe `ArgSchema` interface defines the configuration for command-line arguments. This schema is similar to Node.js `util.parseArgs` but with extended features.\n\n### Schema Properties\n\n#### `type` (required)\n\nType of the argument value:\n\n- `'string'`: Text value (default if not specified)\n- `'boolean'`: True/false flag (can be negatable with `--no-` prefix)\n- `'number'`: Numeric value (parsed as integer or float)\n- `'enum'`: One of predefined string values (requires `choices` property)\n- `'positional'`: Non-option argument by position\n- `'custom'`: Custom parsing with user-defined `parse` function\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  name: { type: 'string' },        // --name value\n  verbose: { type: 'boolean' },     // --verbose or --no-verbose\n  port: { type: 'number' },         // --port 3000\n  level: { type: 'enum', choices: ['debug', 'info'] },\n  file: { type: 'positional' },     // first positional arg\n  config: { type: 'custom', parse: JSON.parse }\n}\n```\n\n#### `short` (optional)\n\nSingle character alias for the long option name. Allows users to use `-x` instead of `--extended-option`.\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  verbose: {\n    type: 'boolean',\n    short: 'v'  // Enables both --verbose and -v\n  },\n  port: {\n    type: 'number',\n    short: 'p'  // Enables both --port 3000 and -p 3000\n  }\n}\n```\n\n#### `description` (optional)\n\nHuman-readable description used for help text generation and documentation.\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  config: {\n    type: 'string',\n    description: 'Path to configuration file'\n  },\n  timeout: {\n    type: 'number',\n    description: 'Request timeout in milliseconds'\n  }\n}\n```\n\n#### `required` (optional)\n\nMarks the argument as required. When `true`, the argument must be provided or an `ArgResolveError` will be thrown.\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  input: {\n    type: 'string',\n    required: true,  // Must be provided: --input file.txt\n    description: 'Input file path'\n  },\n  source: {\n    type: 'positional',\n    required: true   // First positional argument must exist\n  }\n}\n```\n\n#### `multiple` (optional)\n\nAllows the argument to accept multiple values. The resolved value becomes an array.\n\n- For options: can be specified multiple times (`--tag foo --tag bar`)\n- For positional: collects remaining positional arguments\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  tags: {\n    type: 'string',\n    multiple: true,  // --tags foo --tags bar → ['foo', 'bar']\n    description: 'Tags to apply'\n  },\n  files: {\n    type: 'positional',\n    multiple: true   // Collects all remaining positional args\n  }\n}\n```\n\n#### `negatable` (optional)\n\nEnables negation for boolean arguments using `--no-` prefix. Only applicable to `type: 'boolean'`.\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  color: {\n    type: 'boolean',\n    negatable: true,\n    default: true,\n    description: 'Enable colorized output'\n  }\n  // Usage: --color (true), --no-color (false)\n}\n```\n\n#### `choices` (optional)\n\nArray of allowed string values for enum-type arguments. Required when `type: 'enum'`.\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  logLevel: {\n    type: 'enum',\n    choices: ['debug', 'info', 'warn', 'error'],\n    default: 'info',\n    description: 'Logging verbosity level'\n  },\n  format: {\n    type: 'enum',\n    choices: ['json', 'yaml', 'toml'],\n    description: 'Output format'\n  }\n}\n```\n\n#### `default` (optional)\n\nDefault value used when the argument is not provided. The type must match the argument's `type` property.\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  host: {\n    type: 'string',\n    default: 'localhost'  // string default\n  },\n  verbose: {\n    type: 'boolean',\n    default: false        // boolean default\n  },\n  port: {\n    type: 'number',\n    default: 8080         // number default\n  },\n  level: {\n    type: 'enum',\n    choices: ['low', 'high'],\n    default: 'low'        // must be in choices\n  }\n}\n```\n\n#### `toKebab` (optional)\n\nConverts the argument name from camelCase to kebab-case for CLI usage. A property like `maxCount` becomes available as `--max-count`.\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  maxRetries: {\n    type: 'number',\n    toKebab: true,        // Accessible as --max-retries\n    description: 'Maximum retry attempts'\n  },\n  enableLogging: {\n    type: 'boolean',\n    toKebab: true         // Accessible as --enable-logging\n  }\n}\n```\n\n#### `parse` (optional)\n\nCustom parsing function for `type: 'custom'` arguments. Required when `type: 'custom'`. Should throw an Error if parsing fails.\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  config: {\n    type: 'custom',\n    parse: (value) =\u003e {\n      try {\n        return JSON.parse(value)  // Parse JSON config\n      } catch {\n        throw new Error('Invalid JSON configuration')\n      }\n    },\n    description: 'JSON configuration object'\n  },\n  date: {\n    type: 'custom',\n    parse: (value) =\u003e {\n      const date = new Date(value)\n      if (isNaN(date.getTime())) {\n        throw new Error('Invalid date format')\n      }\n      return date\n    }\n  }\n}\n```\n\n#### `conflicts` (optional)\n\nSpecifies other options that cannot be used together with this option. When conflicting options are provided together, an `ArgResolveError` will be thrown.\n\nConflicts only need to be defined on one side - if option A defines a conflict with option B, the conflict is automatically detected when both are used.\n\n\u003c!-- eslint-skip --\u003e\n\n```js\n{\n  // Single conflict\n  port: {\n    type: 'number',\n    conflicts: 'socket'  // Cannot use --port with --socket\n  },\n  socket: {\n    type: 'string'\n    // No need to define conflicts: 'port' here\n  }\n}\n\n// Multiple conflicts (mutually exclusive options)\n{\n  tcp: {\n    type: 'number',\n    conflicts: ['udp', 'unix']  // Cannot use with --udp or --unix\n  },\n  udp: {\n    type: 'number',\n    conflicts: ['tcp', 'unix']\n  },\n  unix: {\n    type: 'string',\n    conflicts: ['tcp', 'udp']\n  }\n}\n```\n\n## 🧪 Parser Combinators (Experimental)\n\n\u003c!-- eslint-disable markdown/no-missing-label-refs --\u003e\n\n\u003e [!NOTE]\n\u003e Parser combinators are experimental and may change in future versions.\n\n\u003c!-- eslint-enable markdown/no-missing-label-refs --\u003e\n\nParser combinators provide composable factory functions that generate `ArgSchema` objects. Instead of writing schema objects manually, you can use combinators for type-safe, composable argument definitions.\n\n### Basic Usage\n\n\u003c!-- eslint-skip --\u003e\n\n```js\nimport { parseArgs, resolveArgs } from 'args-tokens'\nimport {\n  args,\n  string,\n  integer,\n  boolean,\n  positional,\n  choice,\n  withDefault,\n  multiple,\n  required,\n  short,\n  describe,\n  unrequired,\n  map,\n  merge,\n  extend\n} from 'args-tokens/combinators'\n\n// Define reusable schema groups with args()\nconst common = args({\n  help: short(boolean(), 'h'),\n  verbose: boolean()\n})\n\nconst network = args({\n  port: short(withDefault(integer({ min: 1, max: 65535 }), 8080), 'p'),\n  host: required(short(string({ minLength: 1 }), 'o'))\n})\n\n// Compose schemas with merge()\nconst schema = merge(\n  common,\n  network,\n  args({\n    command: positional()\n  })\n)\n\nconst argv = ['dev', '--port', '9131', '--host', 'example.com', '--verbose']\nconst tokens = parseArgs(argv)\nconst { values } = resolveArgs(schema, tokens)\n```\n\n### Available Combinators\n\n#### Base Combinators\n\n- `string(opts?)` — String with optional validation (`minLength`, `maxLength`, `pattern`)\n- `number(opts?)` — Number with optional range (`min`, `max`)\n- `integer(opts?)` — Integer only, with optional range\n- `float(opts?)` — Float with optional range, rejects `NaN`/`Infinity`\n- `boolean(opts?)` — Boolean flag, supports `negatable`\n- `positional()` — Positional argument (resolves to string)\n- `positional(parser)` — Typed positional (e.g., `positional(integer())`)\n- `choice(values)` — Enum-like with literal type inference\n\n#### Modifier Combinators\n\n- `describe(schema, text)` — Set a human-readable description for help text generation\n- `short(schema, alias)` — Set a single-character short alias (e.g., `-v` for `--verbose`)\n- `required(schema)` — Mark as required (error if not provided)\n- `unrequired(schema)` — Mark as not required (override `required: true`)\n- `withDefault(schema, defaultValue)` — Set a default value\n- `multiple(schema)` — Accept multiple values (resolves to array)\n- `map(schema, transform)` — Transform the parsed value\n\n#### Schema Combinators\n\n- `args(fields)` — Type-safe schema factory (no `satisfies Args` needed)\n- `merge(...schemas)` — Compose multiple schemas into one\n- `extend(base, overrides)` — Override or add fields to a schema\n\n#### Custom Combinators\n\n- `combinator(config)` — Custom argument with user-defined `parse` function (uses `type: 'custom'`)\n\n\u003c!-- eslint-skip --\u003e\n\n```js\nimport { parseArgs, resolveArgs } from 'args-tokens'\nimport { combinator, required, withDefault, multiple, short, map } from 'args-tokens/combinators'\n\n// Date parser\nconst date = combinator({\n  parse: value =\u003e {\n    const d = new Date(value)\n    if (isNaN(d.getTime())) {\n      throw new Error('Invalid date format')\n    }\n    return d\n  },\n  metavar: 'date'\n})\n\n// JSON parser\nconst json = combinator({\n  parse: value =\u003e {\n    try {\n      return JSON.parse(value)\n    } catch {\n      throw new Error('Invalid JSON')\n    }\n  },\n  metavar: 'json'\n})\n\n// Compose with modifier combinators\nconst schema = {\n  since: required(date), // --since 2024-01-15 (required)\n  until: withDefault(date, new Date()), // --until 2024-12-31 (optional with default)\n  config: short(json, 'c'), // -c '{\"key\":\"value\"}' or --config '...'\n  timestamps: multiple(date), // --timestamps 2024-01-01 --timestamps 2024-06-01\n  days: map(date, d =\u003e d.getDay()) // --days 2024-01-15 → 1 (Monday)\n}\n\nconst tokens = parseArgs(['--since', '2024-01-15', '--days', '2024-01-15'])\nconst { values } = resolveArgs(schema, tokens)\n// values.since → Date object\n// values.days → 1\n```\n\n## 📚 API References\n\nSee the [API References](./docs/index.md)\n\n## 🙌 Contributing guidelines\n\nIf you are interested in contributing to `args-tokens`, I highly recommend checking out [the contributing guidelines](/CONTRIBUTING.md) here. You'll find all the relevant information such as [how to make a PR](/CONTRIBUTING.md#pull-request-guidelines), [how to setup development](/CONTRIBUTING.md#development-setup)) etc., there.\n\n## 💖 Credits\n\nThis project is inspired by:\n\n- [`util.parseArgs`](https://nodejs.org/api/util.html#utilparseargsconfig), created by Node.js contributors and [OpenJS Foundation](https://openjsf.org/)\n- [`pkgjs/parseargs`](https://github.com/pkgjs/parseargs), created by Node.js CLI package maintainers and Node.js community.\n\n## 🤝 Sponsors\n\nThe development of Gunshi is supported by my OSS sponsors!\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://cdn.jsdelivr.net/gh/kazupon/sponsors/sponsors.svg\"\u003e\n    \u003cimg alt=\"sponsor\" src=\"https://cdn.jsdelivr.net/gh/kazupon/sponsors/sponsors.svg\"/\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## ©️ License\n\n[MIT](http://opensource.org/licenses/MIT)\n\n\u003c!-- Badges --\u003e\n\n[npm-version-src]: https://img.shields.io/npm/v/args-tokens?style=flat\n[npm-version-href]: https://npmjs.com/package/args-tokens\n[jsr-src]: https://jsr.io/badges/@kazupon/args-tokens\n[jsr-href]: https://jsr.io/@kazupon/args-tokens\n[install-size-src]: https://pkg-size.dev/badge/install/35082\n[install-size-href]: https://pkg-size.dev/args-tokens\n[ci-src]: https://github.com/kazupon/args-tokens/actions/workflows/ci.yml/badge.svg\n[ci-href]: https://github.com/kazupon/args-tokens/actions/workflows/ci.yml\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkazupon%2Fargs-tokens","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkazupon%2Fargs-tokens","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkazupon%2Fargs-tokens/lists"}