Skip to content

Commit fd206c7

Browse files
takemi-ohamaclaude
andauthored
docs: README/getting-started のクイックスタート整理 + issues 追加 (#54)
* docs: README/getting-started のクイックスタートを整理 (冗長表現削減・章立て再構成) - ワンライナーのサブシェル仕組み解説など過剰説明を削除 - build ショートカット例外の実装詳細は CLI リファレンスへ委譲 - curl|bash 確認手順を README から除去 (getting-started には安全案内として残置) - クイックスタートを「1.インストール(ワンライナー/手動) → 2.プラグイン導入・起動」に再構成し、ワンライナー後の手順を明確化 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs: issues に i31 指示書と PLAN31_2 (list TUI 統合UI化) 設計書を追加 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 76a048f commit fd206c7

4 files changed

Lines changed: 239 additions & 20 deletions

File tree

README.md

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,24 @@ devbaseは、Docker Composeを使った再現性の高い開発環境を提供
1515
- **データ永続化**: 名前付きボリュームでコンテナ再起動後もデータを保持
1616
- **スナップショット管理**: `/home/ubuntu` 共通ボリュームの増分バックアップ・復元・世代管理
1717
- **環境変数の自動収集**: `devbase env init`でAWS/Git/GCP認証情報を対話的に設定
18-
- **対話的なプロジェクト選択**: `devbase list` で矢印キー移動・名前での絞り込みに対応した TUI メニューから起動対象を選べます。起動中のプロジェクトは「再起動 (up) / 再ビルド (rebuild) / 停止 (down)」を選択できます
18+
- **対話的なプロジェクト選択**: `devbase list` TUI メニュー(矢印キー移動・名前絞り込み対応)から起動対象を選択。起動中なら再起動 (up) / 再ビルド (rebuild) / 停止 (down) も選べます
1919
- **キャッシュ無効リビルド**: `devbase rebuild [name]``docker compose build --no-cache` 相当のイメージ再ビルドができます
2020

2121
## クイックスタート
2222

23-
### ワンライナーインストール(推奨)
23+
devbase 本体を**インストール**し、続けて**プラグインを導入してプロジェクトを起動**します。インストールはワンライナー(推奨)か手動のどちらかを選んでください。
24+
25+
### 1. インストール
26+
27+
#### ワンライナー(推奨)
2428

2529
```bash
2630
curl -fsSL https://dl.basex.jp/i | bash && . ~/devbase/bin/rc
2731
```
2832

29-
`~/devbase` に clone(既存なら更新) `devbase init` まで自動実行(uv の自動導入・PATH/補完の登録・`plugins.yml` 生成を含む)したうえで、末尾の `&& . ~/devbase/bin/rc`**いま開いている端末**にも devbase を通します(`&&` 以降はパイプのサブシェルではなく呼び出し元シェルで実行されるため、その場で `devbase` が使えます)。新しく開くターミナルは init の rc 追記により自動で有効です
33+
`~/devbase` に clone(既存なら更新)して `devbase init` まで自動実行します(uv の自動導入・PATH/補完の登録・`plugins.yml` 生成を含む)末尾の `. ~/devbase/bin/rc`**いま開いている端末**でも `devbase` が即使えます(新しく開くターミナルは自動で有効)
3034

31-
> 配置先を `DEVBASE_INSTALL_DIR` で変えた場合は後半の `~/devbase/bin/rc` も同じパスに合わせてください。`. ~/devbase/bin/rc` を省いた `... | bash` だけでも導入は完了します(その場合は完了メッセージの案内に従ってください)
35+
> 配置先を `DEVBASE_INSTALL_DIR` で変えた場合は `~/devbase/bin/rc` も同じパスに合わせてください。`. ~/devbase/bin/rc` を省いた `... | bash` だけでも導入は完了します。
3236
3337
環境変数で挙動を上書きできます。
3438

@@ -44,29 +48,26 @@ DEVBASE_INSTALL_DIR=~/work/devbase DEVBASE_INSTALL_REF=v1.2.3 \
4448
bash -c "$(curl -fsSL https://dl.basex.jp/i)"
4549
```
4650

47-
> **`curl | bash` を実行する前に**: 中身を確認したい場合は、いったん保存してから実行してください。
48-
>
49-
> ```bash
50-
> curl -fsSL https://dl.basex.jp/i -o install.sh
51-
> less install.sh # 内容を確認
52-
> bash install.sh
53-
> ```
54-
55-
### 手動セットアップ
51+
#### 手動
5652

5753
```bash
58-
# 1. クローンと初期化
5954
git clone https://github.com/devbasex/devbase.git
6055
cd devbase
6156
./bin/devbase init
6257
. ./bin/rc # いまのシェルで devbase を有効化(PATH / 補完)
58+
```
6359

64-
# 2. Pluginのインストール
60+
### 2. プラグインの導入とプロジェクト起動
61+
62+
インストール方法を問わず、以降の手順は共通です。
63+
64+
```bash
65+
# プラグインのインストール
6566
devbase plugin repo add user/repo # リポジトリ登録(init でサンプルレジストリ devbasex/devbase-samples は自動登録済み)
6667
devbase plugin install <name> # Plugin名でインストール
6768

68-
# 3. プロジェクトの起動
69-
cd projects/your-project
69+
# プロジェクトの起動
70+
cd ~/devbase/projects/your-project # 手動セットアップでは clone 先 (例: ./projects/your-project)
7071
devbase env init # 環境変数の設定(初回のみ)
7172
devbase up # コンテナを起動(初回はイメージビルドを含むため時間がかかります)
7273
devbase login # コンテナにログイン
@@ -118,7 +119,7 @@ devbaseのコマンドは4つのグループにまとめられています。
118119

119120
> **`container`(略記 `ct`)グループは非推奨です。** `devbase project <sub>` のエイリアスとして当面動作しますが、非推奨警告を表示します。新しいコマンドは `project` を使用してください。
120121
121-
- **ショートカット**: `up [name]`, `down [name]`, `login [index]`, `build [image]`, `ps [name]`, `scale [name] <num>`, `list` はトップレベルから直接使用可能(`project` グループへ自動転送。`logs` はシノニムを持ちません)。ただし `build` のみ例外で、`project` グループ(Python 実装)ではなく `bin/devbase` のシェル実装 `cmd_build` へ直接委譲されます(詳細は [CLI リファレンス](docs/user/cli-reference.md#ショートカットコマンド)
122+
- **ショートカット**: `up [name]`, `down [name]`, `login [index]`, `build [image]`, `ps [name]`, `scale [name] <num>`, `list` はトップレベルから直接使用可能(`project` グループへ自動転送。`logs` はシノニムを持ちません)。なお `build` のみ挙動が一部異なります(詳細は [CLI リファレンス](docs/user/cli-reference.md#ショートカットコマンド)
122123
- **プレフィックス略記**: `devbase p l``devbase plugin list`
123124
- **トップレベルコマンド**: `init`, `status`
124125

docs/user/getting-started.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ curl -fsSL https://dl.basex.jp/i | bash && . ~/devbase/bin/rc
2929

3030
1. `~/devbase` に devbase を clone します(既に devbase が clone 済みなら `git pull --ff-only` で更新)。
3131
2. clone 先で `devbase init` を 1 回実行します(uv の自動導入・PATH/補完の登録・`plugins.yml` 生成を含む)。
32-
3. 末尾の `&& . ~/devbase/bin/rc`**いま開いている端末**で実行し`&&` 以降はパイプのサブシェルではなく呼び出し元シェルで動くため)、その端末で即座に `devbase`(PATH / 補完)が使える状態にします。新しく開くターミナルは init の rc 追記により自動で有効です。
32+
3. 末尾の `&& . ~/devbase/bin/rc`**いま開いている端末**で実行し、その端末で即座に `devbase`(PATH / 補完)が使える状態にします。新しく開くターミナルは init の rc 追記により自動で有効です。
3333

3434
`env init`(手順 7)は対話が必要なため、ワンライナーでは**実行せず案内のみ**です。完了後に手動で実行してください。配置先を `DEVBASE_INSTALL_DIR` で変えた場合は、`~/devbase/...` を同じパスに合わせてください。
3535

@@ -82,7 +82,7 @@ cd devbase
8282
. ./bin/rc
8383
```
8484

85-
`bin/rc` を source すると、いま開いているシェルに devbase の PATH と補完がその場で適用されます(`init` が rc ファイルに追記する内容と同じ有効化を、現在のシェルへ即時反映します)。`devbase` 前提シェルである bash / zsh のどちらでも同じく `.`(= `source`)で読み込めます。
85+
`bin/rc` を source すると、`init` が rc ファイルに追記するのと同じ有効化(devbase の PATH と補完)が現在のシェルへ即時反映されます。bash / zsh のどちらでも `.`(= `source`)で読み込めます。
8686

8787
> **Note:** 新しいターミナルを開いた場合は `init` が rc に追記したブロックで自動的に有効化されるため、この手順は不要です。
8888
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
# PLAN31_2: `devbase list` TUI の統合UI化
2+
3+
> 元 issue: `issues/i31.md` 第2項
4+
> ステータス: 着手可(設計確定 2026-06-09・既存コード精読済み)
5+
> 関連: PLAN31_1 (init は installer に吸収)、PLAN06 (`project` 群)
6+
> 関連 skill: `/ndf:issue-plan-strategy`, `/ndf:implementation-plan`
7+
8+
## 1. 背景と目的
9+
10+
現状の `devbase list` TUI(`lib/devbase/commands/project.py`)は
11+
**プロジェクト選択 → up/rebuild/down サブメニュー**まで(i29〜i32 の到達点)。
12+
ゴールは **`devbase` のほぼ全操作を TUI から実行可能**にすること。`init`
13+
PLAN31_1 に吸収のため対象外。範囲は **全コマンド群を階層メニューでフル統合**
14+
(ユーザー確認済み 2026-06-09)。
15+
16+
## 2. 既存コード調査結果(実装の核心)
17+
18+
### 2.1 全ハンドラは `args.subcommand` + `getattr(args, …)` 駆動
19+
20+
CLI の実体は argparse だが、各グループハンドラは Namespace を
21+
`subcommand` で分岐し属性を `getattr` で読むだけ。**TUI は `types.SimpleNamespace`
22+
を組んで既存ハンドラを直接呼べる**(ロジック二重実装不要)。実証パターンが既にある:
23+
24+
```python
25+
# project.py:174-185 _start_project_action
26+
from devbase.commands.container import cmd_project
27+
return cmd_project(types.SimpleNamespace(subcommand=action, name=name, scale=None))
28+
```
29+
30+
### 2.2 ハンドラのシグネチャと委譲経路
31+
32+
| カテゴリ | エントリ | シグネチャ | 出典 |
33+
|---|---|---|---|
34+
| project ライフサイクル | `cmd_project(args)``_dispatch_lifecycle` | `args`(Namespace) | `container.py:309-311`, `265-306` |
35+
| env | `cmd_env(devbase_root, args)` | `(Path, Namespace)` | `env.py:18-` |
36+
| plugin | `cmd_plugin(devbase_root, args)` | `(Path, Namespace)` | `plugin.py:23-` |
37+
| snapshot | `cmd_snapshot(devbase_root, args)` | `(Path, Namespace)` | `snapshot.py:22-` |
38+
| status | `cmd_status(devbase_root)` | `(Path,)` 引数なし | `status.py:184` |
39+
40+
> 重要な発見: `_dispatch_lifecycle``getattr(args,'name',None)` が真なら
41+
> **subcommand を問わず** `_resolve_project_name` で対象 `projects/<name>`
42+
> `chdir` する(`container.py:278-284`, `205-262`)。つまり TUI は project 系で
43+
> **一律 `name=<選択プロジェクト>` を渡せば chdir が効く**`login`/`build`
44+
> parser に `name` が無い(`cli.py:89-110`)が、Namespace に `name` を載せれば
45+
> chdir は発動するので問題なし。
46+
47+
### 2.3 各サブコマンドが読む属性(cli.py parser 定義より逆算)
48+
49+
TUI が組む `SimpleNamespace` に必要な属性。CLI 実行と差異を出さないための契約表。
50+
51+
| サブコマンド | 必要属性(既定) | 出典 (cli.py) | scope |
52+
|---|---|---|---|
53+
| project up | `name`, `scale`(None) | `_dispatch_lifecycle:288` | CWD(name で chdir) |
54+
| project down | `name` | `:290` | 〃 / 破壊的 |
55+
| project login | `name`, `index`("1") | `:291`, `99` ||
56+
| project ps | `name`, `all`(False) | `:292`, `167-169` ||
57+
| project logs | `name`, `follow`(False), `tail`(None) | `:293`, `171-174` ||
58+
| project scale | `name`, `new_scale`(int) | `:295`, `178-180` ||
59+
| project build | `name`, `image`(None) | `:297`, `110` ||
60+
| project rebuild | `name` | `:298`, `188-190` ||
61+
| env init | `reset`(False) | `env.py:23`, `cli:219-220` | global .env / 対話 |
62+
| env list | `global_only`,`project_only`,`reveal`,`keys_only` | `env.py:25-29`, `cli:224-231` | global+project |
63+
| env set | `assignment`("K=V"), `project`(False) | `env.py:30-31`, `cli:233-235` | `--project` 時 CWD |
64+
| env get/delete | `key` | `env.py:32-33`, `cli:237-241` | global |
65+
| env edit/sync/project | (なし) | `cli:222,243-244` | edit/project は CWD |
66+
| env export/import | `dest`/`source` 他多数 | `env.py:392-430`, `cli:246-328` | global+project |
67+
| plugin list | `available`(False) | `plugin.py:29`, `cli:337-338` | global |
68+
| plugin install | `source`, `link`, `install_all` | `plugin.py:31-33`, `cli:341-345` | global |
69+
| plugin uninstall/info | `name` | `plugin.py:34,36`, `cli:348-355` | global / 破壊的(uninstall) |
70+
| plugin update | `name`(None) | `plugin.py:35`, `cli:351-352` | global |
71+
| plugin sync/migrate | (なし) | `cli:357-360` | global |
72+
| plugin repo add | `repo_command='add'`, `url`, `name`(None) | `plugin.py:176,185`, `cli:366-368` | global |
73+
| plugin repo remove | `repo_command='remove'`, `name`, `force` | `cli:370-373` | global / 破壊的 |
74+
| plugin repo list/refresh | `repo_command`, (`name` for refresh) | `cli:375-378` | global |
75+
| snapshot create | `name`(None), `full`(False) | `snapshot.py:29-30`, `cli:387-389` | global |
76+
| snapshot restore | `name`, `point`(None) | `snapshot.py:33-34`, `cli:393-395` | global / 破壊的 |
77+
| snapshot copy | `name`, `new_name` | `snapshot.py:36-37`, `cli:398-400` | global |
78+
| snapshot delete | `name` | `snapshot.py:38`, `cli:402-403` | global / 破壊的 |
79+
| snapshot rotate | `keep`(3) | `snapshot.py:39`, `cli:405-406` | global |
80+
81+
### 2.4 既存 TUI 資産(PR1 で再利用・移送する)
82+
83+
- questionary は任意依存。未導入時はフォールバック (`project.py:26-31`, `319-331`)。
84+
- メニュー部品: `_show_menu`/`_show_action_menu`/`_with_escape_cancel`/`_with_escape_back`/
85+
`_add_escape_binding`/`_MENU_BACK` 番兵(`project.py:195-289`)。
86+
- ナビ規約: **Esc=トップ復帰**(`_with_escape_cancel`), **←=1階層戻る**(`_with_escape_back`,
87+
Left+Esc)(`project.py:214-245`)。Ctrl-C=中止(rc=0)。
88+
- 非 TTY 判定 → 一覧表示フォールバック(`project.py:391-394`)。
89+
- プロジェクト一覧と状態: `list_projects`/`_print_table``project.py:75-130`)、
90+
状態は `docker ps` 1 回集計 `status._running_counts_by_project``project.py:105`)。
91+
92+
## 3. 設計方針
93+
94+
### 3.1 アーキテクチャ(モジュール切り出し)
95+
96+
`project.py` 肥大化を避け `lib/devbase/tui/` パッケージへ分離:
97+
98+
```text
99+
lib/devbase/tui/
100+
menu.py # questionary ラッパ・_MENU_BACK・escape binding・引数収集ヘルパ
101+
# (text/select/confirm/int/path + 入力検証ループ)
102+
app.py # トップ階層メニュー & カテゴリ routing。devbase_root を保持
103+
dispatch.py # SimpleNamespace 生成 + 既存ハンドラ呼び出しの薄い共通関数
104+
actions_project.py / actions_env.py / actions_plugin.py
105+
actions_snapshot.py / actions_status.py
106+
```
107+
108+
- `cmd_project_list``project.py:378`)は **`tui.app.run(devbase_root, args)` への入口**に置換。
109+
- `dispatch.py``_start_project_action``project.py:174-185`)を一般化:
110+
`dispatch_lifecycle(subcommand, name, **attrs)` / `dispatch_group(handler, devbase_root, subcommand, **attrs)`
111+
- questionary 不在 / 非 TTY 時は現状フォールバック(project 一覧の番号入力)を維持し、
112+
全 TUI を要求された場合は「CLI を使ってください」と縮退案内。
113+
114+
### 3.2 `devbase list` の入口挙動(後方互換に配慮)
115+
116+
`devbase list` は新トップメニューを開く。互換性のため **「プロジェクト操作」を
117+
先頭・既定ハイライト**にし、Enter 連打で従来の project 選択フローに到達できるようにする
118+
(PR1 のレビュー観点に「既存挙動の非回帰」を明記)。`--no-interactive`/`--plain`
119+
従来どおり一覧テーブルのみ。
120+
121+
### 3.3 project スコープ依存の扱い
122+
123+
`env set --project` / `env project` / `env edit` は CWD(プロジェクトディレクトリ)で
124+
動く。これらを TUI から実行する場合は **先にプロジェクトを選ばせて chdir**(2.2 の
125+
name→chdir 機構、または `os.chdir`)してからハンドラを呼ぶ。env/plugin/snapshot の
126+
global 操作は DEVBASE_ROOT 上で動くため chdir 不要。
127+
128+
### 3.4 破壊的操作の確認
129+
130+
`down`/`env delete`/`plugin uninstall`/`plugin repo remove`/`snapshot delete`/
131+
`snapshot restore` は実行前に `menu.confirm()` で確認(2.3 の「破壊的」印)。
132+
133+
### 3.5 状態遷移
134+
135+
```mermaid
136+
stateDiagram-v2
137+
[*] --> Top
138+
Top --> Project: プロジェクト操作(既定)
139+
Top --> Env: 環境変数
140+
Top --> Plugin: プラグイン
141+
Top --> Snapshot: スナップショット
142+
Top --> Status: ステータス
143+
Project --> Arg: 引数/確認が必要
144+
Env --> Arg
145+
Plugin --> Arg
146+
Snapshot --> Arg
147+
Arg --> Exec: 確定
148+
Arg --> Project: ← キャンセル
149+
Exec --> Top: 完了後 復帰
150+
Project --> Top: Esc
151+
Env --> Top: Esc
152+
Plugin --> Top: Esc
153+
Snapshot --> Top: Esc
154+
Status --> Top: Esc
155+
Top --> [*]: Esc / Ctrl-C
156+
```
157+
158+
## 4. PR 分割計画
159+
160+
PR1 で土台(`tui/` + メニューエンジン + 既存挙動の移送)。PR2〜5 は release 上で
161+
並行(各カテゴリは別 `actions_*.py` で衝突しにくい)。
162+
163+
| PR # | branch 名 | 概要 | 主な変更 | 依存 | 並行 |
164+
|---|---|---|---|---|---|
165+
| 1 | `feature/PLAN31_2-tui-framework` | `tui/` 新設・`menu`/`dispatch`/`app`・トップ階層メニュー・Esc/←/Ctrl-C 規約移送・引数収集ヘルパ・**既存 project up/down/rebuild を非回帰移送**`cmd_project_list` を入口に置換 | `tui/*`, `project.py` | なし ||
166+
| 2 | `feature/PLAN31_2-project-ops` | project に login/ps/logs/scale/build 追加(index/all/follow+tail/new_scale(int 検証)/image(`containers/` から選択)) | `tui/actions_project.py` | PR1 | × |
167+
| 3 | `feature/PLAN31_2-env-ops` | env: init/list/set/get/delete/edit/sync/project/export/import。project スコープ系は事前 chdir | `tui/actions_env.py` | PR1 ||
168+
| 4 | `feature/PLAN31_2-plugin-ops` | plugin: list/install/uninstall/update/info/sync/migrate + repo add/remove/list/refresh | `tui/actions_plugin.py` | PR1 ||
169+
| 5 | `feature/PLAN31_2-snapshot-status` | snapshot: create/list/restore/copy/delete/rotate + status 閲覧 | `tui/actions_snapshot.py`, `actions_status.py` | PR1 ||
170+
171+
```text
172+
release branch: release/PLAN31_2
173+
base branch: main
174+
```
175+
176+
## 5. テスト計画
177+
178+
- **単体(monkeypatch)**: 既存テストが `_show_menu`/`_show_action_menu`
179+
monkeypatch する手法(`project.py` docstring 参照)を踏襲。`menu.*` を差し替えて
180+
選択値を注入し、各 action が **2.3 の契約どおりの `SimpleNamespace`** を組んで
181+
ハンドラを呼ぶことを検証(ハンドラは mock)。状態遷移(Esc 復帰 / ← 戻り /
182+
Ctrl-C 中止 / 完了後トップ復帰)も検証。
183+
- **非 TTY / questionary 不在**: 一覧フォールバック・縮退案内に落ちること。
184+
- **破壊的操作**: confirm を介すこと(拒否で実行されない)。
185+
- **結合(release)**: list→project up、env set→get、plugin list、snapshot create→list
186+
を実コンテナ / dummy plugin で通し確認。既存 pytest(400+ passed)非回帰維持。
187+
188+
## 6. 留意点 / リスク
189+
190+
- **引数契約の同期**: 2.3 の表は cli.py parser と一対一。CLI 側で引数が変わると TUI が
191+
壊れるため、PR ごとに該当 parser を再確認(PLAN06 で `login=index`/`build=image`
192+
整理済みの曖昧さに注意)。可能なら契約を 1 箇所に定数化し parser との同期テストを足す。
193+
- **入口挙動変更**: `devbase list` がトップメニュー化する点は破壊的変更なので、PR1 で
194+
「プロジェクト操作」既定ハイライトと `--plain` 維持により muscle-memory を保全。
195+
- **切り出しの競合**: `project.py` は i29〜i32 で頻繁に更新。PR1 は現行ロジックを保全
196+
移送し、差分レビューしやすい単位を維持する。

0 commit comments

Comments
 (0)