Guide for AI

AI に構成を作ってもらうためのガイド

RetainProcess を知らない AI(ChatGPT・Claude など)にこのページを渡すと、構成の JSON やスタックのファイル(retainprocess.yml)を、書式どおりに書いてもらえます。

使い方(人向け)

  1. 下の「ガイドを全文コピー」を押し、AI との会話に貼り付けます。AI がウェブを読めるなら、このページの URL を渡すだけでもかまいません。
  2. 続けて、動かしたいコマンドを AI に伝えます(例:「~/src/blog で npm run dev しているのを登録したい」)。IntelliJ・VS Code・Cursor などで使っているプロジェクトなら、プロジェクトのフォルダを指定するだけで、そこにある起動構成から構成を作ってもらえます(ファイルを読める AI の場合。読めない AI には .vscode/launch.json などの中身を貼り付けます)。
  3. AI が出した JSON をコピーし、RetainProcess のポップアップの左ペインの ⤓ → Import from Clipboard で取り込みます。retainprocess.yml が出てきたら、プロジェクトのディレクトリに保存して retain-process up します。
次のガイドに従って、RetainProcess(macOS のメニューバーアプリ)の構成を作ってください。
分からない項目(作業ディレクトリ、ポート、環境変数など)は推測せず、先に私に質問してください。
最後に、取り込み用の JSON(またはスタックの retainprocess.yml)を 1 つのコードブロックで出してください。

登録したいもの:
- (ここに、動かしたいコマンドと場所を書く)
  例: ~/src/shop の IntelliJ(または VS Code)の起動構成から作って
  例: まず試したいので、Mac に最初から入っているコマンドで「スリープさせない」構成を作って

RetainProcess の構成を作る AI へのガイド

このガイドは、RetainProcess を初めて扱う AI アシスタント向けです。利用者の代わりに、RetainProcess に登録する「構成」を書くための書式と規則をまとめています。これは RetainProcess 1.0 の仕様です(出典: https://foo-tec.com/retainprocess/)。

1. RetainProcess とは

2. 出力の選び方(JSON か YAML か)

状況出すもの利用者の反映方法
単独のコマンドを 1 つ以上登録したい構成の JSON(配列)ポップアップの ⤓ → Import from Clipboard(または Import from File…)
1 つのプロジェクトの複数のサービスを、依存の順に起動したい(DB → API → フロントなど)retainprocess.ymlプロジェクトのディレクトリに保存し、そこで retain-process up

しないこと: ~/Library/Application Support/RetainProcess/config.json を直接編集させない。アプリは起動時にしか読まず、動いているアプリが次に保存したときに上書きされて消える。

3. 利用者に確かめること

次の項目が会話から分からなければ、推測せずに質問する。プロジェクトのフォルダを示されたら、先に IDE の起動構成を読む(4 章)と、多くはそこで分かる。

  1. 動かすコマンドそのもの(ターミナルで打っているとおりに)
  2. どのディレクトリで動かすか(絶対パスか ~/ から)
  3. 必要な環境変数、または読む .env ファイル
  4. 落ちたときに自動で起動し直したいか(no / on-failure / always)
  5. 複数のサービスに依存関係があるか。あるなら、準備完了をポートか HTTP で判定できるか
  6. (任意)案件ごとにまとめる名前(ワークスペース)

4. IDE の起動構成から作る(IntelliJ・VS Code・Cursor など)

利用者がプロジェクトのフォルダを示したら、そこにある IDE の起動構成(Run Configuration / launch.json / tasks.json)を読み、RetainProcess の構成に変換できる。コマンド・引数・作業ディレクトリ・環境変数を聞き直さずに済む。

探す場所

IDEファイル備考
JetBrains(IntelliJ IDEA・WebStorm・PyCharm・RustRover・GoLand など).run/*.run.xml
.idea/runConfigurations/*.xml
.idea/workspace.xml の <component name="RunManager">
1 つの <configuration> が 1 つの起動構成。name と type 属性を見る
VS Code・Cursor(Cursor は VS Code と同じファイル).vscode/launch.json
.vscode/tasks.json
*.code-workspace の launch / tasks
JSON にコメントや末尾のカンマがあってよい(JSONC)
(IDE 以外の手がかり)package.json の scripts、Procfile、Makefile、docker-compose.ymlIDE の構成が無いときの候補

選び方

変数の置き換え

元の書き方置き換え備考
$PROJECT_DIR$、${workspaceFolder}プロジェクトのフォルダのパス(~/… の形)JetBrains の file://$PROJECT_DIR$ は file:// を外す
$USER_HOME$、${userHome}~args の中では ~ が展開されないので、そこだけは絶対パスにする
$MODULE_DIR$、$MODULE_WORKING_DIR$そのモジュールのフォルダ分からなければ利用者に聞く
${env:NAME}書かない(ログインシェルの環境から引き継がれる)ログインシェルに無い変数なら利用者に値を聞く
${file}、${input:…}、${command:…}変換しない開いているファイルや入力に依存する構成は対象外として伝える

JetBrains の起動構成の読み方(type ごと)

type変換読む項目
ShConfigurationType(シェルスクリプト)EXECUTE_SCRIPT_FILE が true: executable_path = INTERPRETER_PATH、args = INTERPRETER_OPTIONS + SCRIPT_PATH + SCRIPT_OPTIONS
false: executable_path = /bin/zsh、args = -lc 'exec <SCRIPT_TEXT>'
SCRIPT_WORKING_DIRECTORY → working_dir、<envs> → env_text
js.build_tools.npm(npm / pnpm / yarn)executable_path = <package-manager> の名前(無ければ npm)、args = <command> + <scripts> + <arguments>(例 run dev)<package-json> のフォルダ → working_dir、<envs>
CargoCommandRunConfigurationexecutable_path = cargo、args = command の値(例 run --bin api)workingDirectory、<envs>
MAKEFILE_TARGET_RUN_CONFIGURATIONexecutable_path = make、args = target + argumentsworkingDirectory。ビルドだけのターゲットは変換しない
Python・Node.js・Go の実行構成インタプリタ(Python は SDK のパス、例 .venv/bin/python)+ スクリプトまたは -m モジュール + 引数作業ディレクトリ・環境変数・引数の項目。Python には PYTHONUNBUFFERED=1 を足す
Java の Application・Spring Bootクラスパスが IDE 任せなので直接は変換できない。./gradlew bootRun や ./mvnw spring-boot:run などの代わりを提案し、利用者に確かめるGradle / Maven の構成があればそのタスク名

VS Code・Cursor の読み方

例

JetBrains の .idea/runConfigurations/dev.xml:

<configuration default="false" name="dev" type="js.build_tools.npm">
  <package-json value="$PROJECT_DIR$/package.json" />
  <command value="run" />
  <scripts><script value="dev" /></scripts>
  <package-manager value="/opt/homebrew/bin/pnpm" />
  <envs><env name="PORT" value="3000" /></envs>
</configuration>

VS Code の .vscode/launch.json:

{
  "configurations": [
    {
      "name": "API",
      "type": "debugpy",
      "request": "launch",
      "module": "uvicorn",
      "args": ["app.main:app", "--reload"],
      "cwd": "${workspaceFolder}/api",
      "envFile": "${workspaceFolder}/api/.env"
    }
  ]
}

プロジェクトのフォルダが ~/src/shop なら、変換結果は次のとおり。

[
  {
    "name": "dev",
    "executable_path": "pnpm",
    "args": "run dev",
    "working_dir": "~/src/shop",
    "env_text": "PORT=3000\n",
    "workspace": "shop"
  },
  {
    "name": "API",
    "executable_path": ".venv/bin/python",
    "args": "-m uvicorn app.main:app --reload",
    "working_dir": "~/src/shop/api",
    "env_text": "PYTHONUNBUFFERED=1\n",
    "env_files": [".env"],
    "workspace": "shop"
  }
]

補足: pnpm は名前で書けば、ログインシェルの PATH で見つかる(元の構成の /opt/homebrew/bin/pnpm のような絶対パスでもよい)。Python の仮想環境の場所(.venv)が構成に書かれていなければ、フォルダの中を確かめるか利用者に聞く。

5. 構成の JSON の書式

取り込みは次の 3 つの形を受け付ける。形 1(構成の配列)を使うこと。

  1. 構成の配列 [ {…}, {…} ](推奨)
  2. 構成 1 件のオブジェクト { "name": …, … }
  3. config.json 全体({"version": 1, "configs": [ … ]}。settings は取り込まれない)

すべてのフィールドに既定値があり、省略してよい。既定値と同じなら書かないほうが読みやすい。id は書かない(取り込み時に必ず新しく採番される)。

キー型既定値意味・規則
name文字列""表示名。空なら Untitled。重複してよい。CLI では名前(大文字小文字を区別しない)で指定するので、短く一意にするとよい
executable_path文字列""必須。実行ファイル。コマンド名(npm)・絶対パス・相対パス(作業ディレクトリ基準)。先頭の ~/ は展開。コマンド名はログインシェルの PATH で探す
args文字列""引数を 1 本の文字列で。空白区切り、"…" / '…' でくくれる、\ でエスケープ。シェルを通さない(下の 6 章)
working_dir文字列""作業ディレクトリ。空ならホーム。先頭の ~/ は展開。存在しなければ起動に失敗する
env_text文字列""環境変数。KEY=VALUE を \n で区切る。# で始まる行と空行は無視。KEY は [A-Za-z_][A-Za-z0-9_]*。値の引用符は外されない(A="x" は値が "x" になる)。$VAR は展開しない
env_files文字列の配列[]読む .env ファイル。~ を展開、相対なら作業ディレクトリ基準。Run のたびに読む。書式は KEY=VALUE、export 可、"…" / '…' の引用符は外す、${VAR} は展開しない
workspace文字列""まとめて表示を絞り込むための名前。空 = どこにも属さない
restart文字列"no"自動再起動。"no" / "on-failure"(異常終了時)/ "always"(正常終了でも)。間隔は 1 秒から倍々で最大 30 秒、60 秒未満の終了が 10 回続くと諦める
tty真偽値false疑似端末で動かす。出力がバッファされず、色も出る。stdout と stderr は 1 本にまとまる。入力は送れない
stop_grace_secs整数5Stop で SIGTERM を送ってから SIGKILL までの秒数。0〜300
log_enabled真偽値trueログをファイル(~/Library/Logs/RetainProcess/<id>/current.log)に保存するか
log_max_size_mb整数51 ファイルの上限(MB)。1〜1024
log_max_files整数3残す世代数。0〜50。あふれた分は退避先へ移す(退避先が無ければ削除)
log_file_per_run真偽値trueRun のたびに新しいログファイルで始める
archive_dir文字列 / nullnullあふれたログの退避先(絶対パス)。通常は書かない(利用者がアプリのダイアログで選ぶ。未設定ならアプリ全体の退避先を使う)

全項目を書いた例(実際の構成)

RetainProcess で使っている Ollama の構成を、全項目のまま載せる。省略した項目は表の既定値になるので、普段はここまで書かなくてよい。

{
  "id": "8e01a5a9-2f9c-4b4f-a977-5b90bfa5e6dd",
  "name": "Ollama",
  "executable_path": "ollama",
  "args": "serve",
  "working_dir": "",
  "env_text": "# OLLAMA_HOST=127.0.0.1:11434\n# OLLAMA_MODELS=~/.ollama/models\n",
  "env_files": [],
  "workspace": "AI",
  "stop_grace_secs": 10,
  "log_enabled": true,
  "log_max_size_mb": 5,
  "log_max_files": 3,
  "log_file_per_run": false,
  "archive_dir": null,
  "restart": "no",
  "tty": false
}

環境変数は次の順に重ね、後のものが勝つ: ログインシェルの環境 → env_files(書いた順)→ env_text。子プロセスには RETAIN_PROCESS=1 も渡る。

6. コマンドの起動のされ方(つまずきやすい点)

7. JSON の例

次の配列をそのまま取り込める(1 件だけでも配列にする)。

[
  {
    "name": "Blog Dev",
    "executable_path": "npm",
    "args": "run dev -- --port 4321",
    "working_dir": "~/src/blog",
    "env_text": "NODE_ENV=development\nFORCE_COLOR=1\n",
    "workspace": "Blog"
  },
  {
    "name": "API (uvicorn)",
    "executable_path": ".venv/bin/python",
    "args": "-m uvicorn app.main:app --reload --port 8000",
    "working_dir": "~/src/shop/api",
    "env_text": "PYTHONUNBUFFERED=1\n",
    "env_files": [".env"],
    "restart": "on-failure"
  },
  {
    "name": "Ollama",
    "executable_path": "ollama",
    "args": "serve",
    "env_text": "OLLAMA_HOST=127.0.0.1:11434\n",
    "stop_grace_secs": 10
  },
  {
    "name": "Docker Stack",
    "executable_path": "docker",
    "args": "compose up",
    "working_dir": "~/src/shop",
    "stop_grace_secs": 30
  },
  {
    "name": "Worker (shell)",
    "executable_path": "/bin/zsh",
    "args": "-lc 'source ./env.sh && exec bundle exec sidekiq'",
    "working_dir": "~/src/shop/backend",
    "tty": true,
    "restart": "always"
  }
]

補足: docker compose up の場合、CPU・メモリに出るのは docker の CLI の分だけで、コンテナ自体(Docker の VM の中)は含まれない。

8. スタック(retainprocess.yml)の書式

docker compose のファイルの部分集合。プロジェクトのディレクトリに retainprocess.yml(.yaml も可)として置く。ファイルが正で、アプリ側では編集しない(変えたらファイルを直す)。

トップレベル

サービスのキー(これ以外は読み飛ばされ、警告が出る)

キー書き方
command必須。文字列(JSON の args と同じ分割)か配列。先頭の語が実行ファイル。シェルは通さない
working_dirこのファイルのディレクトリからの相対パス、または絶対パス。省略時はファイルのディレクトリ
environmentマップ(KEY: value)か配列(- KEY=value)
env_file文字列か配列。相対パスは このファイルのディレクトリ基準(working_dir 基準ではない)
depends_on配列(= 起動したら次へ)、またはマップで condition: service_started / service_healthy(準備完了を待つ)
healthcheckport: 5432(そのポートで待ち受けたら準備完了。any なら何かのポート)か http: http://localhost:8080/health(2xx で準備完了。ホストは localhost / 127.0.0.1 / [::1] だけ、リダイレクトは追わない)。interval(既定 1s)、timeout(準備完了を待つ上限、既定 60s)
stop_grace_period既定 5s
restartno / on-failure / always(unless-stopped は always と同じ)
ttytrue / false
x-retainprocessRetainProcess 独自の設定: log_enabled / log_max_size_mb / log_max_files / log_file_per_run / archive_dir / workspace(意味は JSON と同じ)

例

name: shop
services:
  db:
    command: postgres -D ./data -p 5432
    working_dir: backend
    healthcheck:
      port: 5432
      timeout: 1m30s
    stop_grace_period: 15s
  api:
    command: [.venv/bin/python, -m, uvicorn, "app.main:app", --port, "8000"]
    working_dir: api
    env_file: api/.env
    environment:
      PYTHONUNBUFFERED: "1"
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      http: http://localhost:8000/health
    restart: on-failure
  web:
    command: npm run dev
    working_dir: web
    tty: true
    depends_on: [api]
    x-retainprocess:
      workspace: Shop

Up は依存の順に起動し(service_healthy なら準備完了を待つ)、Down は逆順に止める。

9. Mac に最初から入っているもので試す例

利用者が「まず試したい」「何を登録すればよいか分からない」ときは、インストール不要の macOS 標準のコマンドで例を作る。どれも前景で動き続け、Stop で止まる。

やりたいことコマンド見どころ
Mac をスリープさせない(Run 中だけ)/usr/bin/caffeinate -d -iRun でスリープ防止、Stop で元に戻る。トグルのように使える
アプリのログを流し見る/usr/bin/log stream --style compact --predicate 'process == "Finder"'Logs タブと検索の練習。出力が多いのでログの世代交代も確かめられる
ネットワークの疎通を見張る/sbin/ping -i 10 www.apple.com10 秒ごとに 1 行。途切れたら Logs で分かる
メモリの状況を記録する/usr/bin/vm_stat 601 分ごとの記録がログファイルに残る
ポートで待ち受ける/usr/bin/nc -lk 127.0.0.1 9000ヘッダーに :9000 が出る。別のターミナルで echo hello | nc 127.0.0.1 9000 とすると Logs に出る
定期的に何かする(シェルのループ)/bin/zsh -c 'while true; do date; sleep 60; done'シェルの構文が要るときの書き方の例

JSON の例

[
  {
    "name": "Keep Awake",
    "executable_path": "/usr/bin/caffeinate",
    "args": "-d -i",
    "log_enabled": false
  },
  {
    "name": "Finder Log",
    "executable_path": "/usr/bin/log",
    "args": "stream --style compact --predicate 'process == \"Finder\"'",
    "log_max_size_mb": 2,
    "log_max_files": 2
  },
  {
    "name": "Ping Watch",
    "executable_path": "/sbin/ping",
    "args": "-i 10 www.apple.com"
  },
  {
    "name": "Memory Stats",
    "executable_path": "/usr/bin/vm_stat",
    "args": "60",
    "workspace": "Monitor"
  },
  {
    "name": "Port 9000",
    "executable_path": "/usr/bin/nc",
    "args": "-lk 127.0.0.1 9000"
  },
  {
    "name": "Clock",
    "executable_path": "/bin/zsh",
    "args": "-c 'while true; do date; sleep 60; done'"
  }
]

スタックの例(依存と準備完了を試す)

listener がポート 9000 で待ち受けてから、sender が 5 秒ごとに時刻を送る。retain-process up で順に起動し、listener の Logs に時刻が流れる。

name: mac-demo
services:
  listener:
    command: /usr/bin/nc -lk 127.0.0.1 9000
    healthcheck:
      port: 9000
  sender:
    command: [/bin/zsh, -c, "while true; do date | /usr/bin/nc -w 1 127.0.0.1 9000; sleep 5; done"]
    depends_on:
      listener:
        condition: service_healthy
    restart: on-failure

できないこと: Safari・ミュージック・メモなどの GUI アプリ(open -a …)は管理できない(open はすぐ終わり、監視も停止もできない)。sudo が要るもの(powermetrics、fs_usage など)も使えない。python3 / ruby / git は Command Line Tools が無い Mac ではインストールを促すダイアログが出るだけなので、「標準のコマンド」の例には使わない。

log は zsh の組み込みコマンドと名前が重なる。RetainProcess はシェルを通さないので log でも /usr/bin/log が動くが、例では絶対パスで書くと誤解が無い。

10. 出す前のチェックリスト

11. 利用者に伝える反映のしかた

JSON の場合

  1. JSON をコピーする。
  2. メニューバーの RetainProcess のアイコンをクリックし、ポップアップの左ペインの ⤓ → Import from Clipboard。ファイルに保存したなら Import from File…。
  3. 構成は一覧の末尾に追加される(既存の構成は変わらない。同じものを 2 回取り込むと 2 件になる)。自動では起動しないので、選んで ▶ Run。
  4. 直すときは Configuration タブで編集する(自動で保存される。動いている間の変更は次の Run から効く)。

YAML の場合

  1. retainprocess.yml をプロジェクトのディレクトリに保存する。
  2. そのディレクトリで retain-process up(初回はスタックの登録も行う)。状態は retain-process ps、停止は retain-process down。
  3. ファイルを直したら、もう一度 retain-process up(または、ポップアップのスタックの表示で Reload)。

CLI の retain-process は、アプリが起動していないと終了コード 2 で「RetainProcess is not running」と返す。その場合は open -a RetainProcess で起動してもらう。