{"id":20884850,"url":"https://github.com/topcli/prompts","last_synced_at":"2026-04-11T12:12:42.963Z","repository":{"id":114215386,"uuid":"609995317","full_name":"TopCli/prompts","owner":"TopCli","description":"Node.js user prompt library for command-line interfaces.","archived":false,"fork":false,"pushed_at":"2025-08-01T12:06:10.000Z","size":580,"stargazers_count":32,"open_issues_count":2,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-08-01T14:36:50.929Z","etag":null,"topics":["cli","nodejs","prompt","prompts"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TopCli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-03-05T20:53:52.000Z","updated_at":"2025-08-01T12:06:13.000Z","dependencies_parsed_at":"2023-10-03T02:11:23.005Z","dependency_job_id":"21237b3a-c733-452b-b97e-b20574b44848","html_url":"https://github.com/TopCli/prompts","commit_stats":{"total_commits":108,"total_committers":9,"mean_commits":12.0,"dds":"0.41666666666666663","last_synced_commit":"507a335e51337898097e9473c48e11d4a9daa9c7"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/TopCli/prompts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TopCli%2Fprompts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TopCli%2Fprompts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TopCli%2Fprompts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TopCli%2Fprompts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TopCli","download_url":"https://codeload.github.com/TopCli/prompts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TopCli%2Fprompts/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268348704,"owners_count":24236302,"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","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cli","nodejs","prompt","prompts"],"created_at":"2024-11-18T08:11:45.623Z","updated_at":"2026-04-11T12:12:42.957Z","avatar_url":"https://github.com/TopCli.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"./public/banner.png\" alt=\"@topcli/prompts\"\u003e\n\n  ![version](https://img.shields.io/badge/dynamic/json.svg?style=for-the-badge\u0026url=https://raw.githubusercontent.com/TopCli/prompts/main/package.json\u0026query=$.version\u0026label=Version)\n  [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg?style=for-the-badge)](https://github.com/TopCli/prompts/commit-activity)\n  [![isc](https://img.shields.io/badge/License-ISC-blue.svg?style=for-the-badge)](https://github.com/TopCli/prompts/blob/main/LICENSE)\n  [![scorecard](https://api.securityscorecards.dev/projects/github.com/TopCli/prompts/badge?style=for-the-badge)](https://ossf.github.io/scorecard-visualizer/#/projects/github.com/TopCli/prompts)\n  ![build](https://img.shields.io/github/actions/workflow/status/TopCli/prompts/node.js.yml?style=for-the-badge)\n\n  \u003cimg src=\"./public/topcli.gif\" alt=\"demo\"\u003e\n\u003c/div\u003e\n\n## Requirements\n- [Node.js](https://nodejs.org/en/) v22 or higher\n\n## Getting Started\n\nThis package is available in the Node Package Repository and can be easily installed with [npm](https://docs.npmjs.com/getting-started/what-is-npm) or [yarn](https://yarnpkg.com).\n\n```bash\n$ npm i @topcli/prompts\n# or\n$ yarn add @topcli/prompts\n```\n\n## Usage exemple\n\nYou can locally run `node ./demo.js`\n\n```js\nimport { question, confirm, select, multiselect } from \"@topcli/prompts\";\n\nconst kTestRunner = [\"node\", \"tap\", \"tape\", \"vitest\", \"mocha\", \"ava\"];\n\nconst name = await question(\"Project name ?\", { defaultValue: \"foo\" });\nconst runner = await select(\"Choose a test runner\", { choices: kTestRunner, maxVisible: 5 });\nconst isCLI = await confirm(\"Your project is a CLI ?\", { initial: true });\nconst os = await multiselect(\"Choose OS\", {\n  choices: [\"linux\", \"mac\", \"windows\"],\n  preSelectedChoices: [\"linux\"]\n});\n\nconsole.log(name, runner, isCLI, os);\n```\n\n## API\n\n### `question()`\n\n```ts\nquestion\u003cT = string\u003e(message: string, options?: QuestionOptions\u003cT\u003e): Promise\u003cT\u003e\n```\n\nSimple prompt, similar to `rl.question()` with an improved UI.\n\nUse `options.defaultValue` to set a default value.\n\nUse `options.hint` to display a hint alongside the question.\n\nUse `options.secure` if you need to hide both input and answer. You can provide either a **boolean** or an **object** which allows to configure a `placeholder` such as `*`.\n\nUse `options.signal` to set an `AbortSignal` (throws a [AbortError](#aborterror)).\n\nUse `options.validators` to validate user input and re-prompt on failure.\n\nUse `options.transformer` to parse and validate user input in a single step, returning a typed value. **Mutually exclusive with `validators`.**\n\nUse `options.skip` to skip prompt. It will return `options.defaultValue` if given, `\"\"` otherwise.\n\n**Validators examples**\n\n```js\nconst packageName = await question('Package name', {\n  validators: [\n    {\n      validate: (value) =\u003e {\n        if (fs.existsSync(path.join(process.cwd(), value))) {\n          return `Folder ${value} already exists`;\n        }\n      }\n    }\n  ]\n});\n```\n\nValidators can also be async, for example to validate against an API:\n\n```js\nconst userId = await question('User ID', {\n  validators: [\n    {\n      validate: async(userId) =\u003e {\n        const res = await fetch(`https://api.com/users/${userId}`);\n        if (!res.ok) {\n          return {\n            isValid: false,\n            error: `User '${userId}' not found`\n          }\n        }\n      }\n    }\n  ]\n});\n```\n\n**Transformers examples**\n\n```js\nimport { question, transformers } from \"@topcli/prompts\";\n\nconst port = await question(\"Port\", { transformer: transformers.number() });\n```\n\nCustom transformer:\n\n```js\nconst date = await question(\"Choose date (YYYY-MM-DD)\", {\n  transformer: {\n    transform: (input) =\u003e {\n      const date = new Date(input);\n\n      if (isNaN(date.getTime())) {\n        return { isValid: false, error: \"invalid date\" };\n      }\n\n      return { isValid: true, transformed: date };\n    }\n  }\n});\n```\n\n**Built-in validators**\n\n- `validators.required()` : rejects empty input\n\n```js\nimport { question, validators } from \"@topcli/prompts\";\n\nconst name = await question(\"What's your name ?\", {\n  validators: [validators.required()]\n});\n```\n\n**Built-in transformers**\n\n- `transformers.number()`: parses input as a number, rejects non-numeric and empty strings\n- `transformers.integer()`: parses input as an integer, rejects floats, non-numeric and empty strings\n- `transformers.url()`: parses input as a `URL` object, rejects invalid URLs\n\n```js\nimport { question, transformers } from \"@topcli/prompts\";\n\nconst count = await question(\"Count\", { transformer: transformers.integer() });\nconst url = await question(\"Url\", { transformer: transformers.url() });\n```\n\n### `select()`\n\n```ts\nselect\u003cT extends string\u003e(message: string, options: SelectOptions\u003cT\u003e): Promise\u003cT\u003e\n```\n\nScrollable select depending `maxVisible` (default `8`).\n\nUse `options.ignoreValues` to skip result render \u0026 clear lines after a selected one.\n\nUse `options.validators` to handle user input.\n\nUse `options.autocomplete` to allow filtered choices. This can be useful for a large list of choices.\n\nUse `options.caseSensitive` to make autocomplete filters case sensitive. Default `false`\n\nUse `options.signal` to set an `AbortSignal` (throws a [AbortError](#aborterror)).\n\nUse `options.skip` to skip prompt. It will return the first non-separator choice.\n\nUse `Separator` items in `choices` to visually group options. Separators are not selectable and are skipped during keyboard navigation. When `autocomplete` is active and the user has typed a filter, separators are hidden.\n\n```js\nimport { select } from \"@topcli/prompts\";\n\nconst framework = await select(\"Choose a framework\", {\n  choices: [\n    { type: \"separator\", label: \"Frontend\" },\n    { value: \"react\", label: \"React\" },\n    { value: \"vue\", label: \"Vue\" },\n    { type: \"separator\", label: \"Backend\" },\n    { value: \"express\", label: \"Express\" },\n    { value: \"fastify\", label: \"Fastify\" },\n  ]\n});\n```\n\nUse `choice.disabled` to mark a choice as non-selectable.\n\n```js\nconst runner = await select(\"Choose a runner\", {\n  choices: [\n    { value: \"node\", label: \"Node.js\" },\n    { value: \"bun\", label: \"Bun\", disabled: \"not available\" },\n    { value: \"deno\", label: \"Deno\", disabled: true }\n  ]\n});\n```\n\n### `multiselect()`\n\n```ts\nmultiselect\u003cT extends string\u003e(message: string, options: MultiselectOptions\u003cT\u003e): Promise\u003cT[]\u003e\n```\n\nScrollable multiselect depending `options.maxVisible` (default `8`).\u003cbr\u003e\nUse `options.preSelectedChoices` to pre-select choices.\n\nUse `options.validators` to handle user input.\n\nUse `options.showHint: false` to disable hint (this option is truthy by default).\n\nUse `options.autocomplete` to allow filtered choices. This can be useful for a large list of choices.\n\nUse `options.caseSensitive` to make autocomplete filters case sensitive. Default `false`.\n\nUse `options.signal` to set an `AbortSignal` (throws a [AbortError](#aborterror)).\n\nUse `options.skip` to skip prompt. It will return `options.preSelectedChoices` if given, `[]` otherwise.\n\nUse `Separator` items in `choices` to visually group options. Separators are not selectable and are skipped during keyboard navigation. When `autocomplete` is active and the user has typed a filter, separators are hidden.\n\nUse `choice.disabled` to mark a choice as non-selectable.\n\n### `confirm()`\n\n```ts\nconfirm(message: string, options?: ConfirmOptions): Promise\u003cboolean\u003e\n```\n\nBoolean prompt, default to `options.initial` (`false`).\n\n\u003e [!TIP]\n\u003e You can answer pressing \u003ckbd\u003eY\u003c/kbd\u003e or \u003ckbd\u003eN\u003c/kbd\u003e\n\nUse `options.signal` to set an `AbortSignal` (throws a [AbortError](#aborterror)).\n\nUse `options.skip` to skip prompt. It will return `options.initial` (`false` by default)\n\n### `PromptAgent`\n\nThe `PromptAgent` class allows to programmatically set the next answers for any prompt function, this can be useful for testing.\n\n```ts\nconst agent = PromptAgent.agent();\nagent.nextAnswer(\"John\");\n\nconst input = await question(\"What's your name?\");\nassert.equal(input, \"John\");\n```\n\n\u003e [!WARNING]\n\u003e Answers set with `PromptAgent` will **bypass** any logical \u0026 validation rules.\n\u003e Examples:\n\u003e - When using `question()`, `validators` functions will not be executed.\n\u003e - When using `select()`, the answer can be different from the available choices.\n\u003e - When using `confirm()`, the answer can be any type other than boolean.\n\u003e - etc\u003cbr\u003e\n\u003e **Use with caution**\n\n## Errors\n\n### `AbortError`\n\n```ts\nexport class AbortError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"AbortError\";\n  }\n}\n```\n\n## Interfaces\n\n```ts\ntype Stdin = NodeJS.ReadStream \u0026 {\n  fd: 0;\n};\n\ntype Stdout = NodeJS.WriteStream \u0026 {\n  fd: 1;\n}\n\nexport interface AbstractPromptOptions {\n  stdin?: Stdin;\n  stdout?: Stdout;\n  message: string;\n  skip?: boolean;\n  signal?: AbortSignal;\n}\n\nexport interface PromptValidator\u003cT extends string | string[]\u003e {\n  validate: (input: T) =\u003e ValidationResponse | Promise\u003cValidationResponse\u003e;\n}\n\nexport interface PromptTransformer\u003cT\u003e {\n  transform: (input: string) =\u003e TransformationResponse\u003cT\u003e | Promise\u003cTransformationResponse\u003cT\u003e\u003e;\n}\n\nexport type ValidTransformationResponse\u003cT\u003e = {\n  isValid: true;\n  transformed: T;\n};\n\nexport type TransformationResponse\u003cT\u003e = InvalidResponse | ValidTransformationResponse\u003cT\u003e;\n\nexport interface QuestionOptions\u003cT = string\u003e extends AbstractPromptOptions {\n  defaultValue?: string;\n  hint?: string;\n  validators?: PromptValidator\u003cstring\u003e[];\n  transformer?: PromptTransformer\u003cT\u003e;\n  secure?: boolean | { placeholder: string };\n}\n\nexport interface Choice\u003cT = any\u003e {\n  value: T;\n  label: string;\n  description?: string;\n  disabled?: boolean | string;\n}\n\nexport interface Separator {\n  type: \"separator\";\n  label?: string;\n}\n\nexport interface SelectOptions\u003cT extends string\u003e extends AbstractPromptOptions {\n  choices: (Choice\u003cT\u003e | T | Separator)[];\n  maxVisible?: number;\n  ignoreValues?: (T | number | boolean)[];\n  validators?: PromptValidator\u003cstring\u003e[];\n  autocomplete?: boolean;\n  caseSensitive?: boolean;\n}\n\nexport interface MultiselectOptions\u003cT extends string\u003e extends AbstractPromptOptions {\n  choices: (Choice\u003cT\u003e | T | Separator)[];\n  maxVisible?: number;\n  preSelectedChoices?: (Choice\u003cT\u003e | T)[];\n  validators?: PromptValidator\u003cstring[]\u003e[];\n  autocomplete?: boolean;\n  caseSensitive?: boolean;\n  showHint?: boolean;\n}\n\nexport interface ConfirmOptions extends AbstractPromptOptions {\n  initial?: boolean;\n}\n```\n\n## Contributing\n\nPlease read [CONTRIBUTING.md](./CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.\n\nOpen an issue if you want to provide feedback such as bug reports or enchancements.\n\n## Contributors\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/PierreDemailly\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/39910767?v=4?s=100\" width=\"100px;\" alt=\"PierreDemailly\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePierreDemailly\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/TopCli/prompts/commits?author=PierreDemailly\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/TopCli/prompts/commits?author=PierreDemailly\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://www.linkedin.com/in/thomas-gentilhomme/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/4438263?v=4?s=100\" width=\"100px;\" alt=\"Gentilhomme\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eGentilhomme\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/TopCli/prompts/pulls?q=is%3Apr+reviewed-by%3Afraxken\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e \u003ca href=\"https://github.com/TopCli/prompts/commits?author=fraxken\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/TopCli/prompts/commits?author=fraxken\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://tonygo.dev\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/22824417?v=4?s=100\" width=\"100px;\" alt=\"Tony Gorez\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTony Gorez\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/TopCli/prompts/pulls?q=is%3Apr+reviewed-by%3Atony-go\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://sofiand.github.io/portfolio-client/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/39944043?v=4?s=100\" width=\"100px;\" alt=\"Yefis\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eYefis\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/TopCli/prompts/commits?author=SofianD\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/TopCli/prompts/commits?author=SofianD\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://justie.dev\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/7118300?v=4?s=100\" width=\"100px;\" alt=\"Ben\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eBen\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/TopCli/prompts/commits?author=JUSTIVE\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#maintenance-JUSTIVE\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/ncukondo\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/17022138?v=4?s=100\" width=\"100px;\" alt=\"Takeshi Kondo\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTakeshi Kondo\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#maintenance-ncukondo\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/FredGuiou\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/99122562?v=4?s=100\" width=\"100px;\" alt=\"FredGuiou\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eFredGuiou\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/TopCli/prompts/commits?author=FredGuiou\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/TopCli/prompts/commits?author=FredGuiou\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"https://github.com/TopCli/prompts/commits?author=FredGuiou\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/noxify\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/521777?v=4?s=100\" width=\"100px;\" alt=\"Marcus Reinhardt\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMarcus Reinhardt\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/TopCli/prompts/commits?author=noxify\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/TopCli/prompts/commits?author=noxify\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"https://github.com/TopCli/prompts/commits?author=noxify\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/ItsHarper\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/10224994?v=4?s=100\" width=\"100px;\" alt=\"Harper Andrews\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eHarper Andrews\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/TopCli/prompts/commits?author=ItsHarper\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftopcli%2Fprompts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftopcli%2Fprompts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftopcli%2Fprompts/lists"}