prompts の使い方

Lightweight, beautiful and user-friendly prompts

v2.4.2/週MITCLI
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

prompts の使い方 — 軽量で美しいCLI対話プロンプトライブラリ

一言でいうと

prompts は、CLIアプリケーションでユーザーに対話的な入力を求めるための軽量なNode.jsライブラリです。Promise ベースの API で、テキスト入力・数値入力・選択メニューなど多彩なプロンプトタイプを統一的なインターフェースで提供します。

どんな時に使う?

  • CLIツールの対話的セットアップcreate-xxx 系のスキャフォールディングツールで、プロジェクト名や設定をユーザーに質問する
  • バッチ処理の確認ステップ — デプロイスクリプトやマイグレーション実行前に「本当に実行しますか?」と確認を挟む
  • 設定ファイルの対話的生成 — 複数の選択肢や入力値を順番に聞いて、設定ファイル(.envconfig.json)を生成する

インストール

# npm
npm install prompts

# yarn
yarn add prompts

# pnpm
pnpm add prompts

TypeScript の型定義も別途インストールします。

npm install -D @types/prompts

基本的な使い方

最もシンプルなパターンは、プロンプトオブジェクトを1つ渡して await するだけです。

import prompts from 'prompts';

const response = await prompts({
  type: 'text',
  name: 'projectName',
  message: 'プロジェクト名を入力してください',
  initial: 'my-app'
});

console.log(response.projectName); // => "my-app" またはユーザーの入力値

複数の質問を配列で渡すと、順番に質問されます。戻り値は全回答をまとめたオブジェクトです。

import prompts from 'prompts';

const questions: prompts.PromptObject[] = [
  {
    type: 'text',
    name: 'username',
    message: 'GitHubユーザー名は?'
  },
  {
    type: 'number',
    name: 'age',
    message: '年齢は?',
    validate: (value: number) => value > 0 ? true : '正の数を入力してください'
  },
  {
    type: 'confirm',
    name: 'agreed',
    message: '利用規約に同意しますか?',
    initial: true
  }
];

const response = await prompts(questions);
// => { username: 'terkelg', age: 30, agreed: true }

注意: ユーザーが Ctrl+CEsc でキャンセルした場合、キャンセルされたプロンプト以降のプロパティは返却オブジェクトに含まれません。

よく使うAPI — prompts の主要機能と使い方

1. テキスト入力(text

最も基本的な自由入力プロンプトです。

import prompts from 'prompts';

const { name } = await prompts({
  type: 'text',
  name: 'name',
  message: 'あなたの名前は?',
  initial: '太郎',
  validate: (value: string) => value.length === 0 ? '名前を入力してください' : true
});

2. 選択(select / multiselect

単一選択と複数選択のメニューです。

import prompts from 'prompts';

// 単一選択
const { framework } = await prompts({
  type: 'select',
  name: 'framework',
  message: 'フレームワークを選択してください',
  choices: [
    { title: 'Next.js', description: 'Reactベースのフルスタック', value: 'next' },
    { title: 'Nuxt', description: 'Vueベースのフルスタック', value: 'nuxt' },
    { title: 'SvelteKit', description: 'Svelteベースのフルスタック', value: 'sveltekit' }
  ],
  initial: 0
});

// 複数選択
const { features } = await prompts({
  type: 'multiselect',
  name: 'features',
  message: '有効にする機能を選択してください',
  choices: [
    { title: 'TypeScript', value: 'ts', selected: true },
    { title: 'ESLint', value: 'eslint', selected: true },
    { title: 'Prettier', value: 'prettier' },
    { title: 'Vitest', value: 'vitest' }
  ]
});
// features => ['ts', 'eslint'] など

3. 確認(confirm

Yes/No の二択プロンプトです。

import prompts from 'prompts';

const { shouldDeploy } = await prompts({
  type: 'confirm',
  name: 'shouldDeploy',
  message: '本番環境にデプロイしますか?',
  initial: false
});

if (!shouldDeploy) {
  console.log('デプロイをキャンセルしました');
  process.exit(0);
}

4. 動的プロンプト(条件分岐)

type プロパティに関数を渡すと、前の回答に基づいてプロンプトを動的にスキップできます。type が falsy な値を返すとそのプロンプトはスキップされます。

import prompts from 'prompts';

const response = await prompts([
  {
    type: 'select',
    name: 'database',
    message: 'データベースを選択してください',
    choices: [
      { title: 'PostgreSQL', value: 'postgres' },
      { title: 'MySQL', value: 'mysql' },
      { title: 'SQLite', value: 'sqlite' }
    ]
  },
  {
    // SQLite以外の場合のみホスト名を聞く
    type: (prev: string) => prev !== 'sqlite' ? 'text' : null,
    name: 'host',
    message: 'データベースホストを入力してください',
    initial: 'localhost'
  },
  {
    type: (prev: string, values: Record<string, any>) =>
      values.database !== 'sqlite' ? 'number' : null,
    name: 'port',
    message: 'ポート番号を入力してください',
    initial: (prev: string, values: Record<string, any>) =>
      values.database === 'postgres' ? 5432 : 3306
  }
]);

5. onSubmit / onCancel コールバックと override / inject

プロンプトチェーンの制御やテスト用のユーティリティです。

import prompts from 'prompts';

// onSubmit: 各回答後に呼ばれる。trueを返すとチェーンを中断
const response = await prompts(
  [
    { type: 'text', name: 'first', message: '名前は?' },
    { type: 'text', name: 'last', message: '苗字は?' }
  ],
  {
    onSubmit: (prompt, answer, answers) => {
      console.log(`${prompt.name}: ${answer}`);
      // return true; // ここでtrueを返すと残りの質問をスキップ
    },
    onCancel: (prompt, answers) => {
      console.log('キャンセルされました。収集済みの回答:', answers);
      return false; // falseを返す(またはundefined)とプロンプトチェーン全体が終了
    }
  }
);
// override: CLIの引数で事前に回答を渡す(yargsなどと組み合わせ)
import prompts from 'prompts';

prompts.override({ projectName: 'my-app', framework: 'next' });

const response = await prompts([
  { type: 'text', name: 'projectName', message: 'プロジェクト名は?' },
  { type: 'text', name: 'framework', message: 'フレームワークは?' }
]);
// overrideで渡した値があるプロンプトはスキップされる
// => { projectName: 'my-app', framework: 'next' }
// inject: テスト用に回答をプログラム的に注入
import prompts from 'prompts';

prompts.inject(['my-app', 'next']);

const response = await prompts([
  { type: 'text', name: 'projectName', message: 'プロジェクト名は?' },
  { type: 'text', name: 'framework', message: 'フレームワークは?' }
]);
// => { projectName: 'my-app', framework: 'next' }

// Errorインスタンスを注入するとキャンセルをシミュレートできる
prompts.inject([new Error('cancel')]);

類似パッケージとの比較

特徴promptsinquirerenquirer@clack/prompts
依存パッケージ数少ない(2個)多い少ない少ない
バンドルサイズ軽量大きめ中程度軽量
Promise対応✅ ネイティブ✅(v9+はESM)
TypeScript型定義@types/prompts同梱(v9+)@types/enquirer同梱
プロンプトタイプ数15種類豊富(プラグイン拡張可)豊富少なめ(基本に特化)
テスト用injectinject()なし(別途モック必要)なしなし
メンテナンス状況安定(低頻度更新)活発(v9でESM化)低頻度活発
見た目の美しさ◎(スピナー等も統合)

選定の目安:

  • 軽量さ・シンプルさ重視prompts
  • 豊富なプラグインエコシステムinquirer
  • モダンなUI・スピナー統合@clack/prompts

注意点・Tips

キャンセル時のハンドリングは必須

ユーザーが Ctrl+C でキャンセルすると、未回答のプロパティは返却オブジェクトに含まれません。これを考慮しないとランタイムエラーの原因になります。

const response = await prompts({
  type: 'text',
  name: 'name',
  message: '名前は?'
});

// キャンセルされた場合 response.name は undefined
if (!response.name) {
  console.log('入力がキャンセルされました');
  process.exit(1);
}

ESM環境での import

prompts は CommonJS パッケージです。ESM("type": "module")環境では、デフォルトインポートが正しく動作しない場合があります。

// うまくいかない場合
import prompts from 'prompts';

// 以下を試す
import prompts from 'prompts';
// もしくは
const prompts = (await import('prompts')).default;

validate の戻り値

validate 関数は true を返すと検証成功、文字列を返すとその文字列がエラーメッセージとして表示されます。false を返すとデフォルトのエラーメッセージが表示されます。

{
  type: 'text',
  name: 'email',
  message: 'メールアドレスは?',
  validate: (value: string) => {
    if (!value.includes('@')) return 'メールアドレスの形式が正しくありません';
    return true; // ← false ではなく true を返す
  }
}

CI環境での自動応答

CI/CD パイプラインでは対話プロンプトが止まってしまいます。overrideinject を使って自動応答させましょう。

if (process.env.CI) {
  prompts.override({
    projectName: 'default-app',
    shouldContinue: true
  });
}

autocomplete タイプの活用

選択肢が多い場合は autocomplete タイプが便利です。ユーザーが文字を入力すると候補が絞り込まれます。

const { timezone } = await prompts({
  type: 'autocomplete',
  name: 'timezone',
  message: 'タイムゾーンを選択してください',
  choices: [
    { title: 'Asia/Tokyo', value: 'Asia/Tokyo' },
    { title: 'America/New_York', value: 'America/New_York' },
    { title: 'Europe/London', value: 'Europe/London' },
    // ... 多数の選択肢
  ],
  suggest: (input: string, choices: prompts.Choice[]) =>
    choices.filter(c => c.title.toLowerCase().includes(input.toLowerCase()))
});

まとめ

prompts は、依存が少なく軽量でありながら、15種類のプロンプトタイプと動的な条件分岐をサポートする実用的なCLIプロンプトライブラリです。Promise ベースの統一的なAPIと inject によるテスタビリティの高さが特徴で、CLIツール開発の定番選択肢として安心して使えます。より新しいUIが必要な場合は @clack/prompts