pan-stack-cli 0.1.4 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +572 -23
- package/bin/pan.js +206 -20
- package/lib/ai-skills.js +829 -0
- package/lib/create.js +22 -4
- package/lib/discover.js +69 -2
- package/lib/git/git-checkout.js +395 -0
- package/lib/git/git-clone.js +163 -28
- package/lib/git/git-fetch-all.js +100 -33
- package/lib/git/git-grv.js +68 -37
- package/lib/git/git-gst.js +97 -26
- package/lib/git/git-mr.js +546 -0
- package/lib/git/git-pull.js +104 -43
- package/lib/git/git-push.js +150 -41
- package/lib/git/git-sync-main.js +334 -0
- package/lib/git/helpers/bulk-report.js +202 -0
- package/lib/git/helpers/cli.js +41 -5
- package/lib/git/helpers/colors.js +19 -0
- package/lib/git/helpers/git.js +74 -0
- package/lib/git/helpers/manifest.js +93 -0
- package/lib/git/helpers/repo-select.js +416 -0
- package/lib/git/helpers/repo-summary.js +161 -0
- package/lib/i18n.js +61 -0
- package/lib/inquirer-theme.js +20 -0
- package/lib/language.js +121 -0
- package/lib/languages.js +14 -0
- package/lib/manifest.js +115 -14
- package/lib/menu-prompt.js +201 -0
- package/lib/menu.js +134 -0
- package/lib/messages.js +647 -0
- package/lib/run-command.js +173 -52
- package/lib/select.js +0 -0
- package/lib/serve.js +75 -0
- package/lib/skill-registry-client.js +173 -0
- package/lib/stats/aggregate.js +51 -0
- package/lib/stats/identity.js +20 -0
- package/lib/stats/index.js +189 -0
- package/lib/stats/parse.js +46 -0
- package/lib/stats/range.js +38 -0
- package/lib/stats/report.js +264 -0
- package/lib/stats/review.js +157 -0
- package/lib/stats/scan.js +92 -0
- package/lib/stats/serve.js +25 -0
- package/lib/ui/api.js +202 -0
- package/lib/ui/clone.js +115 -0
- package/lib/ui/config.js +182 -0
- package/lib/ui/diff.js +128 -0
- package/lib/ui/export-gate.js +79 -0
- package/lib/ui/gen-react-mobile-code.js +6 -0
- package/lib/ui/gen-react-web-code.js +75 -0
- package/lib/ui/index.js +89 -0
- package/lib/ui/init.js +252 -0
- package/lib/ui/login.js +128 -0
- package/lib/ui/logout.js +22 -0
- package/lib/ui/palettes.js +103 -0
- package/lib/ui/published-html.js +24 -0
- package/lib/ui/sync.js +137 -0
- package/lib/ui/workspace.js +213 -0
- package/package.json +10 -3
- package/templates/workspace/.claude/skills/writing-guidelines/SKILL.md +0 -48
- package/templates/workspace/.codex/skills/writing-guidelines/SKILL.md +0 -48
- package/templates/workspace/.cursor/skills/writing-guidelines/SKILL.md +0 -48
- package/templates/workspace/.pan.yaml +0 -25
- package/templates/workspace/.project.yaml +0 -15
- package/templates/workspace/README.md +0 -35
package/README.md
CHANGED
|
@@ -40,12 +40,12 @@ skill pre-installed for all three agent folders.
|
|
|
40
40
|
## Requirements
|
|
41
41
|
|
|
42
42
|
- Node.js 18+
|
|
43
|
-
- Git (for `pan clone`, `pull`, `fetch`, `push`, `grv`, `gst`)
|
|
43
|
+
- Git (for `pan clone`, `pull`, `sync-main`, `fetch`, `push`, `grv`, `gst`, `stats`)
|
|
44
44
|
|
|
45
45
|
## Windows support
|
|
46
46
|
|
|
47
|
-
Built-in commands (`create`, `clone`, `pull`, `push`, `fetch`, `
|
|
48
|
-
Windows, macOS, and Linux. Notes for Windows:
|
|
47
|
+
Built-in commands (`create`, `clone`, `pull`, `sync-main`, `push`, `fetch`, `mr`, `checkout`,
|
|
48
|
+
`grv`, `gst`) run on Windows, macOS, and Linux. Notes for Windows:
|
|
49
49
|
|
|
50
50
|
- `shell:` blocks in `.pan.yaml` run through **bash** on all platforms (Git Bash on
|
|
51
51
|
Windows, system bash on macOS/Linux). Use `exec:` for simple one-liners (`npm test`)
|
|
@@ -72,14 +72,236 @@ pan install
|
|
|
72
72
|
|
|
73
73
|
`pan create` fails if the target folder already exists.
|
|
74
74
|
|
|
75
|
+
**Cần registry server**: scaffold template (`workspace`) không còn bundle sẵn trong
|
|
76
|
+
`pan-stack-cli` — `pan create` tải template qua `apps/pan-agent-skill-registry`
|
|
77
|
+
(`PAN_SKILL_REGISTRY_URL`, mặc định `http://localhost:4600`), giống cơ chế
|
|
78
|
+
`pan ai install`. Server không chạy được → `pan create` báo lỗi rõ, không scaffold
|
|
79
|
+
được (không có fallback local).
|
|
80
|
+
|
|
81
|
+
## Agent skills — `pan ai`
|
|
82
|
+
|
|
83
|
+
Builtin (không cần khai báo trong `.pan.yaml`). Quét skill ở **workspace root**
|
|
84
|
+
(thư mục chứa `.project.yaml`): `.claude/skills`, `.cursor/skills`, `.codex/skills`.
|
|
85
|
+
Gộp theo tên skill — bật/tắt đồng bộ cả ba agent folder. Disable đổi tên
|
|
86
|
+
`SKILL.md` → `SKILL.md.disabled` (và `AGENTS.md` tương tự); enable đổi ngược lại.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pan ai # tương tác: Disable | Enable | List | Install | Update
|
|
90
|
+
pan ai --list # chỉ xem trạng thái
|
|
91
|
+
pan ai --disable writing-guidelines
|
|
92
|
+
pan ai --enable writing-guidelines
|
|
93
|
+
pan ai --disable ux-audit --dry-run
|
|
94
|
+
pan skills --list # alias
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
> Menu tương tác của `pan ai` theo đúng [quy ước chung](#quy-ước-chung-cho-mọi-menu-tương-tác-trong-pan):
|
|
98
|
+
> `x` thoát ở mọi bước, `b` quay lại menu action từ bước chọn skill, `a`/`i` khi chọn nhiều skill.
|
|
99
|
+
|
|
100
|
+
### Install / Update — cài & cập nhật skill/agent từ registry server
|
|
101
|
+
|
|
102
|
+
Hai action mới trong menu `pan ai` gọi tới registry server (`apps/pan-agent-skill-registry`)
|
|
103
|
+
để tải skill/agent đóng gói dạng zip:
|
|
104
|
+
|
|
105
|
+
- **Install**: liệt kê package chưa cài (từ `GET {baseUrl}/api/registry`), cho chọn nhiều,
|
|
106
|
+
tự phát hiện agent dir sẵn có (`.claude`/`.cursor`/`.codex` đã tồn tại ở workspace root) để
|
|
107
|
+
cài luôn; nếu chưa có agent dir nào thì hỏi chọn agent đích trước khi cài. Nếu server báo có
|
|
108
|
+
bản cập nhật cho package đã cài, item đầu danh sách cho phép nhảy sang luồng Update.
|
|
109
|
+
- **Update**: liệt kê package đã cài nhưng có version mới hơn, cho chọn (hoặc "Update all"),
|
|
110
|
+
tải lại đúng các agent dir đã cài trước đó (ghi trong lockfile).
|
|
111
|
+
|
|
112
|
+
Config base URL bằng env `PAN_SKILL_REGISTRY_URL` (mặc định `http://localhost:4600`).
|
|
113
|
+
Trạng thái "đã cài gì, version nào, cài vào agent dir nào" lưu ở
|
|
114
|
+
`<workspaceRoot>/.pan/skills-lock.json` (không commit — thêm vào `.gitignore` nếu cần).
|
|
115
|
+
|
|
116
|
+
Nếu chạy `pan ai` mà KHÔNG đứng trong 1 workspace pan-stack (không tìm thấy `.project.yaml`
|
|
117
|
+
walk-up từ cwd) và đang ở TTY tương tác, CLI hỏi có muốn tạo dự án mới ngay tại thư mục hiện
|
|
118
|
+
tại không — lựa chọn **"Không" luôn đứng trước "Có"** trong menu. Chọn "Có" thì tạo ngay
|
|
119
|
+
`.project.yaml` (3 dòng: `project`, `language: vi`, `managed_by` lấy từ `git config user.name`
|
|
120
|
+
|
|
121
|
+
- `user.email`, thiếu thì ghi `YourName`) rồi tiếp tục `pan ai` như đang ở trong workspace đó.
|
|
122
|
+
|
|
123
|
+
## `pan language` (`pan lang`) — đổi ngôn ngữ CLI
|
|
124
|
+
|
|
125
|
+
Danh sách ngôn ngữ available định nghĩa ở 2 nơi (đi cùng nhau khi thêm ngôn ngữ mới):
|
|
126
|
+
|
|
127
|
+
- `lib/messages.js` — nguồn thật của **mã ngôn ngữ hợp lệ** (1 object con `en: {...}`,
|
|
128
|
+
`vi: {...}`, … — mỗi key là 1 message theo mã đó). `availableLangs()` (`lib/i18n.js`)
|
|
129
|
+
đọc `Object.keys(messages.js)`.
|
|
130
|
+
- `lib/languages.js` — **tên hiển thị** cho mỗi mã (vd `vi` → "Tiếng Việt"), dùng bởi
|
|
131
|
+
menu `pan language`. Thiếu dòng ở đây thì menu vẫn hiện, chỉ dùng luôn mã thay tên.
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
pan language # menu tương tác: chọn ngôn ngữ (đánh dấu ngôn ngữ hiện tại)
|
|
135
|
+
pan language vi # đặt trực tiếp, không cần menu
|
|
136
|
+
pan lang en # alias
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Ghi `language: <mã>` vào `.project.yaml` gần nhất (walk-up từ cwd); chưa có key → thêm,
|
|
140
|
+
đã có → cập nhật. Không có `.project.yaml` → `pan language <mã>` báo lỗi (cần workspace
|
|
141
|
+
để lưu), còn `pan language` (xem/không đổi) vẫn chạy, dùng mã mặc định/env (`PAN_LANG`).
|
|
142
|
+
|
|
143
|
+
Menu chọn ngôn ngữ theo đúng [quy ước chung](#quy-ước-chung-cho-mọi-menu-tương-tác-trong-pan):
|
|
144
|
+
`↑↓` di chuyển · gõ chữ nhảy tới item · `Enter` chọn (áp dụng ngay) · `b` quay lại (không đổi
|
|
145
|
+
gì) · `x` thoát hẳn CLI.
|
|
146
|
+
|
|
147
|
+
## `pan ui` — đồng bộ Pan Studio
|
|
148
|
+
|
|
149
|
+
Đồng bộ dự án panui giữa **local ↔ Pan Studio backend**: đăng nhập, clone, đẩy thay
|
|
150
|
+
đổi lên, publish HTML, sinh mã React.
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
pan ui # menu tương tác
|
|
154
|
+
pan ui login # đăng nhập (mở trình duyệt, device-flow)
|
|
155
|
+
pan ui logout # đăng xuất, xóa key local
|
|
156
|
+
pan ui clone # tải dự án về local
|
|
157
|
+
pan ui sync # đẩy thay đổi local → backend
|
|
158
|
+
pan ui published-html # publish trang HTML công khai
|
|
159
|
+
pan ui gen-react-web-code # sinh mã React web (.tar.gz)
|
|
160
|
+
pan ui gen-react-mobile-code # coming soon — chỉ in "Đang phát triển"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
> Menu `pan ui` (chọn subcommand) và cascade 4 bước của `pan ui init` (Design System → loại →
|
|
164
|
+
> template → bảng màu) theo [quy ước chung](#quy-ước-chung-cho-mọi-menu-tương-tác-trong-pan): `x`
|
|
165
|
+
> thoát mọi bước, `b` quay lại bước trước trong `pan ui init`.
|
|
166
|
+
|
|
167
|
+
### `init` — tạo dự án panui mẫu
|
|
168
|
+
|
|
169
|
+
Vì hiện có **2 design system**, bước đầu tiên của `pan ui init` luôn là **chọn Design
|
|
170
|
+
System** — trước cả bước chọn loại/template/bảng màu:
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
? Chọn Design System:
|
|
174
|
+
❯ shadcn ui (Recommended)
|
|
175
|
+
antd
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
- **`shadcn ui` (Recommended)** — đứng đầu danh sách, là lựa chọn mặc định.
|
|
179
|
+
- **`antd`** — lựa chọn thứ hai.
|
|
180
|
+
|
|
181
|
+
Sau khi chọn Design System, cascade tiếp tục như cũ: **loại** (Web landing / Mobile /
|
|
182
|
+
CMS) → **template** → **bảng màu** → nhập tên/đường dẫn dự án. `b` quay lại bước trước
|
|
183
|
+
(kể cả quay lại bước chọn Design System từ bước chọn loại), `x` thoát hẳn — theo
|
|
184
|
+
[quy ước chung](#quy-ước-chung-cho-mọi-menu-tương-tác-trong-pan).
|
|
185
|
+
|
|
186
|
+
**Cần registry server**: các template pan-ui (landing-glass, mobile-app,...) không còn
|
|
187
|
+
bundle sẵn — danh sách loại/template lấy từ `apps/pan-agent-skill-registry`
|
|
188
|
+
(`PAN_SKILL_REGISTRY_URL`, mặc định `http://localhost:4600`); chỉ tải zip của
|
|
189
|
+
ĐÚNG template user chọn (không tải hết). Server không chạy được → báo lỗi rõ.
|
|
190
|
+
|
|
191
|
+
### `login` — đăng nhập (device-flow)
|
|
192
|
+
|
|
193
|
+
Giống `claude` / `gh auth login`: không nhập user/password trong terminal. CLI gọi
|
|
194
|
+
`POST /auth/device/start`, mở trình duyệt tại trang `/cli-auth` để đăng nhập + bấm
|
|
195
|
+
"Approve" (fallback: dán URL tay nếu không tự mở được browser), rồi poll
|
|
196
|
+
`/auth/device/poll` tới khi được duyệt. Key nhận về dạng `pmcp_...`, hạn dùng 90
|
|
197
|
+
ngày, lưu tại `~/.pan/credentials.json` (quyền file `600`). Hết hạn → chạy lại
|
|
198
|
+
`pan ui login`. (`pan ui init` vẫn chạy được như alias của `login`.)
|
|
199
|
+
|
|
200
|
+
Đã có key **còn hạn** cho đúng `apiUrl` hiện tại → `pan ui login` KHÔNG tự chạy lại
|
|
201
|
+
device-flow, chỉ in info (email + hạn dùng) và hướng dẫn:
|
|
202
|
+
`pan ui logout` rồi `pan ui login` lại, hoặc `pan ui login --force` (`-f`) để
|
|
203
|
+
đăng nhập lại ngay, ghi đè key hiện tại.
|
|
204
|
+
|
|
205
|
+
### `logout`
|
|
206
|
+
|
|
207
|
+
Xóa key local (`~/.pan/credentials.json`) cho API hiện tại. Token trên backend vẫn
|
|
208
|
+
còn hạn — thu hồi ở UI/`me/mcp-tokens` nếu cần.
|
|
209
|
+
|
|
210
|
+
### `clone`
|
|
211
|
+
|
|
212
|
+
Chọn dự án theo danh sách lấy từ backend (key phải hợp lệ), sau đó hỏi **thư mục
|
|
213
|
+
đích** (mặc định `pan-ui`). Nếu thư mục đã tồn tại → **báo lỗi, không tự xóa** —
|
|
214
|
+
phải xóa thủ công rồi chạy lại. Tải toàn bộ cây file về local và ghi
|
|
215
|
+
`backend: { id, apiUrl }` vào `app.panui.yaml` (định danh dự án dùng cho `sync`
|
|
216
|
+
sau này).
|
|
217
|
+
|
|
218
|
+
### `sync` — push local → backend
|
|
219
|
+
|
|
220
|
+
Đọc `backend.id` trong `app.panui.yaml` (thiếu → gợi ý chạy `clone` trước). So
|
|
221
|
+
sánh (diff) local với backend: file thêm / đổi / xóa. Trước khi đẩy sẽ:
|
|
222
|
+
|
|
223
|
+
1. Hiện tên + id dự án và hỏi xác nhận **đúng dự án** (tránh đẩy nhầm).
|
|
224
|
+
2. Hiện bảng diff và hỏi xác nhận **trước khi đẩy**.
|
|
225
|
+
3. File xóa ở local → hỏi riêng trước khi xóa trên backend.
|
|
226
|
+
|
|
227
|
+
Đây hiện là chiều **push-only** (local → backend); pull để sau.
|
|
228
|
+
|
|
229
|
+
### `published-html` / `gen-react-web-code` — publish & sinh mã
|
|
230
|
+
|
|
231
|
+
Cả hai đều **GATE bằng sync**: nếu local khác backend, CLI báo và hỏi sync ngay
|
|
232
|
+
(hoặc dừng để bạn tự `pan ui sync`) trước khi build. Chỉ khi local đã khớp
|
|
233
|
+
backend mới build tiếp.
|
|
234
|
+
|
|
235
|
+
- `published-html`: gọi build HTML trên backend, chờ xong, in URL công khai
|
|
236
|
+
dạng `<apiUrl>/p/<prefix>`.
|
|
237
|
+
- `gen-react-web-code`: gọi build React trên backend, chờ xong, tải `.tar.gz` và
|
|
238
|
+
giải nén vào thư mục đích (mặc định `pan-ui-react`; đã tồn tại → báo lỗi, không
|
|
239
|
+
tự xóa). Máy không có lệnh `tar` hệ thống → chỉ lưu file `.tar.gz` và in hướng
|
|
240
|
+
dẫn giải nén thủ công.
|
|
241
|
+
- `gen-react-mobile-code`: chưa làm — chỉ in "Đang phát triển".
|
|
242
|
+
|
|
243
|
+
Mỗi lần build tạo một `ExportVersion` mới trên backend (version bump); artifact
|
|
244
|
+
build không đè lên file nguồn.
|
|
245
|
+
|
|
246
|
+
### Cấu hình
|
|
247
|
+
|
|
248
|
+
`PAN_STUDIO_API_URL` / `PAN_STUDIO_WEB_URL` — ưu tiên (cao → thấp):
|
|
249
|
+
|
|
250
|
+
1. biến môi trường (`PAN_STUDIO_API_URL=...`)
|
|
251
|
+
2. file `.pan-env-build.yaml` ở workspace root:
|
|
252
|
+
```yaml
|
|
253
|
+
PAN_STUDIO_API_URL: http://localhost:3001
|
|
254
|
+
PAN_STUDIO_WEB_URL: http://localhost:3001
|
|
255
|
+
```
|
|
256
|
+
3. Trỏ về Pan Studio backend dev
|
|
257
|
+
|
|
258
|
+
`PAN_STUDIO_WEB_URL` thiếu ở cả 3 mức trên thì lấy luôn giá trị `PAN_STUDIO_API_URL`
|
|
259
|
+
đã resolve.
|
|
260
|
+
|
|
261
|
+
### Monorepo — nhiều dự án panui
|
|
262
|
+
|
|
263
|
+
`sync`/`published-html`/`gen-react-web-code` quét mọi `app.panui.yaml` từ
|
|
264
|
+
`.project.yaml` root, tối đa **5 cấp** thư mục (bỏ qua `node_modules`, `.git`,
|
|
265
|
+
`dist`). Tìm thấy nhiều dự án → hỏi chọn; chỉ 1 dự án → dùng luôn, không hỏi.
|
|
266
|
+
|
|
267
|
+
> ⚠️ Lưu ý: block `.html` (liên kết html-ui) chỉ được đặt trong thư mục
|
|
268
|
+
> `components/` của dự án panui.
|
|
269
|
+
|
|
270
|
+
## Static server — `pan serve`
|
|
271
|
+
|
|
272
|
+
Phục vụ một thư mục build tĩnh qua HTTP (SPA mode). Hữu ích để xem web demo do
|
|
273
|
+
`pnpm panui:gen` (Pan Design System) sinh ra, hoặc bất kỳ thư mục `dist` nào.
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
pan serve <dir> [options]
|
|
277
|
+
|
|
278
|
+
pan serve ./panui-demo # → http://localhost:3000
|
|
279
|
+
pan serve ./panui-demo -p 8080 # đổi cổng
|
|
280
|
+
pan serve # phục vụ thư mục hiện tại
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Options: `-p, --port <port>` (mặc định 3000) · `-h, --help`.
|
|
284
|
+
|
|
285
|
+
Bọc package [`serve`](https://www.npmjs.com/package/serve) với cờ `-s` (single-page:
|
|
286
|
+
route sâu / refresh vẫn trả `index.html`). Ưu tiên bản cài trong pan-stack-cli; nếu
|
|
287
|
+
chưa cài thì tự chạy qua `npx serve` (tải lần đầu). Chạy trên Windows/macOS/Linux.
|
|
288
|
+
|
|
289
|
+
Ví dụ luồng "build + xem" web demo panui:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
# trong repo Pan Design System:
|
|
293
|
+
pnpm panui:gen pan-design-system-markdown/examples/blog-project -o ./panui-demo
|
|
294
|
+
pan serve ./panui-demo
|
|
295
|
+
```
|
|
296
|
+
|
|
75
297
|
## Configuration files
|
|
76
298
|
|
|
77
299
|
Two files drive the CLI. Keep responsibilities separate:
|
|
78
300
|
|
|
79
|
-
| File
|
|
80
|
-
|
|
301
|
+
| File | Role |
|
|
302
|
+
| --------------- | ----------------------------------------------------------------------------- |
|
|
81
303
|
| `.project.yaml` | Workspace manifest — lists `repositories` (name, url, path). **No commands.** |
|
|
82
|
-
| `.pan.yaml`
|
|
304
|
+
| `.pan.yaml` | `pan` commands — at workspace root and/or inside each child repo |
|
|
83
305
|
|
|
84
306
|
### `.project.yaml` example
|
|
85
307
|
|
|
@@ -101,6 +323,29 @@ repositories:
|
|
|
101
323
|
path: apps/api
|
|
102
324
|
```
|
|
103
325
|
|
|
326
|
+
### `.project.local.yaml` — repo riêng, không commit
|
|
327
|
+
|
|
328
|
+
Muốn tự thêm repo riêng (thử nghiệm, fork cá nhân, repo nội bộ chỉ mình bạn cần…)
|
|
329
|
+
mà không đụng `.project.yaml` chung của team? Tạo `.project.local.yaml` cùng thư
|
|
330
|
+
mục — chỉ cần field `repositories:` (không cần `project:`/`stack:`/gì khác):
|
|
331
|
+
|
|
332
|
+
```yaml
|
|
333
|
+
# .project.local.yaml — KHÔNG commit (đã có trong .gitignore của 'pan create')
|
|
334
|
+
repositories:
|
|
335
|
+
- name: my-experiment
|
|
336
|
+
url: https://github.com/you/my-experiment.git
|
|
337
|
+
path: apps/my-experiment
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Mọi lệnh đọc `repositories` (`pan clone|pull|push|fetch|grv|gst|sync-main|mr|checkout`,
|
|
341
|
+
`pan stats`, và cả danh sách lệnh `.pan.yaml` theo từng repo) tự động **gộp thêm**
|
|
342
|
+
repo từ file này vào `.project.yaml` chung — không cần khai báo/sửa gì thêm ở
|
|
343
|
+
nơi khác. Có repo local → mỗi lần chạy in 1 dòng gợi ý `ℹ️ +N repo từ
|
|
344
|
+
.project.local.yaml` để bạn biết đang có repo riêng đang hoạt động.
|
|
345
|
+
|
|
346
|
+
`pan create` scaffold sẵn `.gitignore` chứa dòng `.project.local.yaml` — workspace
|
|
347
|
+
cũ (tạo trước khi có tính năng này) tự thêm dòng đó vào `.gitignore` của mình.
|
|
348
|
+
|
|
104
349
|
### `.pan.yaml` — workspace root
|
|
105
350
|
|
|
106
351
|
Orchestration commands. Paths are relative to the workspace root. Use
|
|
@@ -150,18 +395,146 @@ commands:
|
|
|
150
395
|
|
|
151
396
|
Aliases: `alias: i` or `aliases: i, ins` (comma-separated).
|
|
152
397
|
|
|
398
|
+
### `sequence` — gom nhiều lệnh lẻ chạy TUẦN TỰ (vd "build all")
|
|
399
|
+
|
|
400
|
+
Có nhiều lệnh `exec`/`shell` lẻ (build-fe, build-be, build-extension, …) trong CÙNG 1
|
|
401
|
+
file `.pan.yaml`, muốn có thêm 1 lệnh "chạy tất cả theo thứ tự" mà không copy lại
|
|
402
|
+
script? Khai báo field `sequence` (thay cho `exec`/`shell`) — mỗi dòng 1 bước, chạy
|
|
403
|
+
đúng thứ tự viết, dừng ngay khi 1 bước lỗi:
|
|
404
|
+
|
|
405
|
+
```yaml
|
|
406
|
+
commands:
|
|
407
|
+
build-fe:
|
|
408
|
+
exec: pnpm --filter web build
|
|
409
|
+
|
|
410
|
+
build-be:
|
|
411
|
+
default: dev
|
|
412
|
+
targets:
|
|
413
|
+
dev:
|
|
414
|
+
exec: pnpm --filter api build:dev
|
|
415
|
+
prod:
|
|
416
|
+
exec: pnpm --filter api build:prod
|
|
417
|
+
|
|
418
|
+
build-extension:
|
|
419
|
+
shell: |
|
|
420
|
+
cd tools/vscode-pan-uispec && npm run package
|
|
421
|
+
|
|
422
|
+
build-all:
|
|
423
|
+
description: Build FE + BE(prod) + extension theo đúng thứ tự
|
|
424
|
+
sequence: |
|
|
425
|
+
build-fe
|
|
426
|
+
MODE=prod build-be:prod
|
|
427
|
+
build-extension?
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Cú pháp 1 dòng: `[KEY=VAL ...] tênLệnh[:target][?]`
|
|
431
|
+
|
|
432
|
+
- **`tênLệnh`** — phải là 1 command khác **đã khai báo trong cùng file `.pan.yaml`
|
|
433
|
+
này** (không gọi chéo sang `.pan.yaml` của repo khác).
|
|
434
|
+
- **`:target`** — chọn target nếu lệnh đó có `targets:` (giống cách gọi `pan build-be prod`).
|
|
435
|
+
- **`KEY=VAL ...`** (đặt trước tên lệnh) — biến môi trường chỉ áp dụng cho **riêng bước
|
|
436
|
+
đó**, không ảnh hưởng các bước khác hay sequence gọi nó.
|
|
437
|
+
- **`?`** cuối tên lệnh — bước lỗi (exit code ≠ 0) chỉ in cảnh báo rồi **chạy tiếp**
|
|
438
|
+
bước sau, thay vì dừng cả sequence (mặc định KHÔNG có `?` = lỗi là dừng ngay, exit
|
|
439
|
+
code của sequence = exit code bước lỗi đó).
|
|
440
|
+
- Cũng chấp nhận 1 dòng, phân tách bởi `,` khi không cần set biến: `sequence: build-fe, build-be`.
|
|
441
|
+
- `pan build-all` chạy như 1 lệnh bình thường (không có tham số riêng cho sequence);
|
|
442
|
+
từng bước bên trong dùng target/biến đã khai báo sẵn trong `sequence:`.
|
|
443
|
+
|
|
444
|
+
### Interactive select — chọn nhiều/một khi chạy lệnh
|
|
445
|
+
|
|
446
|
+
Bất kỳ command nào (mọi stack: Node/Java/.NET…) khai báo `select*` → `pan` **render picker tương tác**
|
|
447
|
+
(checkbox @inquirer, ⭐TẤT CẢ trên đỉnh) và truyền lựa chọn vào `shell`/`exec` qua **env `PAN_SELECTED`**
|
|
448
|
+
(mỗi dòng 1 giá trị) + `PAN_SELECTED_COUNT`. Script chỉ là shell THUẦN — không cần thêm dependency.
|
|
449
|
+
|
|
450
|
+
| Field | Ý nghĩa |
|
|
451
|
+
| --------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
452
|
+
| `selectFrom` | Lệnh shell; **mỗi dòng stdout = 1 choice** (`label<TAB>value` để đặt nhãn riêng). Vd `ls -1 *.yaml`, `oc get deploy -o name`. |
|
|
453
|
+
| `selectChoices` | Danh sách tĩnh, phân tách bởi `,` hoặc newline (thay cho `selectFrom`). |
|
|
454
|
+
| `selectMessage` | Câu hỏi hiển thị. |
|
|
455
|
+
| `selectMulti` | `true` (mặc định, checkbox nhiều) · `false` (chọn một). |
|
|
456
|
+
| `selectAll` | `true` (mặc định, thêm ⭐TẤT CẢ) · `false`. |
|
|
457
|
+
|
|
458
|
+
`all` (arg) / `PAN_ALL=1` / non-TTY (CI) ⇒ **chọn hết** (bỏ qua picker). Không chọn gì ⇒ thoát.
|
|
459
|
+
|
|
460
|
+
```yaml
|
|
461
|
+
commands:
|
|
462
|
+
deploy:
|
|
463
|
+
description: "Apply manifest (chọn) — hoặc: pan deploy all"
|
|
464
|
+
selectMessage: "Chọn manifest apply:"
|
|
465
|
+
selectFrom: "ls -1 k8s/*.yaml"
|
|
466
|
+
shell: |
|
|
467
|
+
set -euo pipefail
|
|
468
|
+
while IFS= read -r f; do [ -n "$f" ] && kubectl apply -f "$f"; done <<< "${PAN_SELECTED:-}"
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Primitive `pan select`** — cho script chủ động bắt lựa chọn qua stdout (picker render trên stderr):
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
sel=$(pan select --multi --all --from "ls -1 k8s/*.yaml" --message "Chọn manifest:")
|
|
475
|
+
for f in $sel; do kubectl apply -f "$f"; done
|
|
476
|
+
# pan select --single a b c # chọn một trong inline choices
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Quy ước chung cho MỌI menu tương tác trong `pan`
|
|
480
|
+
|
|
481
|
+
Toàn bộ picker/menu trong CLI (menu gốc `pan` trống, `pan ai`, `pan ui`, `pan mr`, `pan checkout`,
|
|
482
|
+
git repo picker, v.v.) đều dùng chung 2 prompt nội bộ `menuSelect`/`menuCheckbox`
|
|
483
|
+
(`lib/menu-prompt.js`, cần `@inquirer/core`) và tuân theo cùng một bộ phím:
|
|
484
|
+
|
|
485
|
+
| Phím | Ý nghĩa | Áp dụng |
|
|
486
|
+
| ---------------- | ------------------------------------------------------ | ------------------------------------- |
|
|
487
|
+
| `Enter` | Xác nhận lựa chọn hiện tại | Mọi menu |
|
|
488
|
+
| `↑`/`↓` + gõ chữ | Di chuyển / gõ nhảy tới item | Mọi menu |
|
|
489
|
+
| `b` | **Quay lại** menu cấp trước (không thoát chương trình) | Menu cấp con (sau khi đã chọn ≥1 cấp) |
|
|
490
|
+
| `x` | **Thoát hẳn** CLI (`process.exit(0)` sạch) | Mọi menu, kể cả menu gốc |
|
|
491
|
+
| `space` | Tick/bỏ tick 1 dòng | Menu chọn nhiều (`menuCheckbox`) |
|
|
492
|
+
| `a` | Chọn tất cả / bỏ chọn tất cả (toggle) | Menu chọn nhiều |
|
|
493
|
+
| `i` | Đảo chọn (invert) | Menu chọn nhiều |
|
|
494
|
+
|
|
495
|
+
Thiếu `@inquirer/core` (dep không cài) → mọi picker fallback sang `@inquirer/prompts`
|
|
496
|
+
(`select`/`checkbox` thô) + thêm item ẩn ở cuối danh sách cho `b`/`x` (không phải hotkey nhấn-1-phím,
|
|
497
|
+
nhưng vẫn chọn được bằng Enter) để giữ đúng hành vi quay lại/thoát dù thiếu dependency.
|
|
498
|
+
|
|
499
|
+
Không có nơi nào trong CLI tự chế cách chọn riêng (loop `readline` tay chỉ còn là fallback CUỐI CÙNG
|
|
500
|
+
khi thiếu cả `@inquirer/core` lẫn `@inquirer/prompts`). `pan ai`, `pan ui` (kể cả cascade
|
|
501
|
+
loại→template→bảng màu của `pan ui init`), `pan mr`, `pan checkout` đều đã áp dụng quy ước này —
|
|
502
|
+
nếu bạn thấy hành vi phím tắt khác trước đây (vd `pan mr`/`pan checkout` giờ có thêm `x` thoát ở
|
|
503
|
+
bước chọn repo, `pan ui init` giờ có `b` quay lại giữa 3 bước chọn), đó là do đồng bộ theo quy ước
|
|
504
|
+
chung này.
|
|
505
|
+
|
|
506
|
+
## `pan git` — menu chọn lệnh git (đỡ nhớ tên/xem help dài)
|
|
507
|
+
|
|
508
|
+
Các lệnh git ở dưới đây (clone/pull/push/fetch/sync-main/mr/checkout/grv/gst) và cả
|
|
509
|
+
`stats` (cũng là 1 dạng thống kê Git từ log) nằm **rải rác** — không nhớ hết tên thì
|
|
510
|
+
gõ `pan git` để xem menu chọn:
|
|
511
|
+
|
|
512
|
+
```bash
|
|
513
|
+
pan git # TTY: menu tương tác chọn 1 lệnh git rồi chạy ngay (x thoát)
|
|
514
|
+
# không TTY: in danh sách lệnh rồi thoát (không lỗi)
|
|
515
|
+
pan git pull # có sẵn tên → chạy thẳng, y hệt gõ 'pan pull' (chỉ là lối gõ khác)
|
|
516
|
+
pan git -h # in danh sách lệnh + mô tả
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
Đây chỉ là **lối vào phụ** (discoverability) — hành vi/tham số của từng lệnh (`--dry-run`,
|
|
520
|
+
`--base-dir`, target tương tác…) không đổi gì so với gõ thẳng `pan <command>`.
|
|
521
|
+
|
|
153
522
|
## Built-in git commands
|
|
154
523
|
|
|
155
524
|
Read `repositories` from the nearest `.project.yaml` (walk-up from cwd):
|
|
156
525
|
|
|
157
|
-
| Command
|
|
158
|
-
|
|
159
|
-
| `pan clone`
|
|
160
|
-
| `pan
|
|
161
|
-
| `pan
|
|
162
|
-
| `pan
|
|
163
|
-
| `pan
|
|
164
|
-
| `pan
|
|
526
|
+
| Command | Action |
|
|
527
|
+
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
528
|
+
| `pan clone` | Clone all repositories in the manifest — bảng tổng hợp `repo · result · note` (cloned · already exists · no access · not found · failed; KHÔNG dừng ở lỗi đầu tiên, clone hết rồi mới tổng hợp) |
|
|
529
|
+
| `pan clone <git-url>` | **Thêm 1 repo mới** — tự tách tên dự án từ URL (bỏ đuôi `.git`, lấy phần cuối path/scp-like), **ghi thêm entry vào `.project.yaml`** (path mặc định `apps/<tên>`), rồi clone ngay repo đó. Đã có tên đó trong manifest → dùng lại entry cũ, không thêm trùng. Xem [chi tiết](#pan-clone-url--thêm-repo-mới-tiện-như-git-clone) |
|
|
530
|
+
| `pan pull` | Pull all cloned repositories — bảng tổng hợp `repo · branch · result · changes · conflict` |
|
|
531
|
+
| `pan sync-main [repo\|all]` (`pan sm`) | Fetch + merge `origin/main` into current branch (interactive picker; conflict summary) |
|
|
532
|
+
| `pan fetch` (`pan gfa`) | Fetch all remotes — bảng tổng hợp `repo · branch · result · behind/ahead · new refs` |
|
|
533
|
+
| `pan push` | Push all repos (`-u origin HEAD` by default) — bảng tổng hợp `repo · branch · result · commits · changes · MR/PR link` |
|
|
534
|
+
| `pan mr [target] [repo\|all\|list]` | Create GitLab Merge Requests (interactive multi-select; target defaults to `main`) |
|
|
535
|
+
| `pan checkout [-b\|-B] <branch> [repo\|all\|list]` (`pan co`) | Switch/create branch across repos (interactive multi-select) |
|
|
536
|
+
| `pan grv` | `git remote -v` for workspace + each child repo — bảng tổng hợp `repo · branch · remote · fetch · push` (`push` = `=` khi giống `fetch`; nhiều remote thì gộp `origin (+N)`) |
|
|
537
|
+
| `pan gst` | Bảng tổng hợp repos dirty: `repo · branch · state · breakdown · behind/ahead` (repo sạch được ẩn; `--verbose` hoặc `-sb` để in `git status` đầy đủ) |
|
|
165
538
|
|
|
166
539
|
Git options:
|
|
167
540
|
|
|
@@ -169,6 +542,176 @@ Git options:
|
|
|
169
542
|
- `--dry-run` — print commands only
|
|
170
543
|
- `[manifest]` — manifest path (default: `.project.yaml`)
|
|
171
544
|
|
|
545
|
+
### `pan clone <url>` — thêm repo mới, tiện như `git clone`
|
|
546
|
+
|
|
547
|
+
`pan clone` không tham số = clone TẤT CẢ repo trong manifest (như cũ). Truyền
|
|
548
|
+
thêm 1 **git URL** (`https://...`, `git@host:group/repo.git`, hoặc bất kỳ
|
|
549
|
+
chuỗi kết thúc `.git`) thì `pan clone` xử lý khác hẳn:
|
|
550
|
+
|
|
551
|
+
```bash
|
|
552
|
+
pan clone https://github.com/you/my-repo.git
|
|
553
|
+
# 1. Tách tên dự án từ URL: "my-repo"
|
|
554
|
+
# 2. Ghi thêm vào .project.yaml (KHÔNG phải .project.local.yaml):
|
|
555
|
+
# - name: my-repo
|
|
556
|
+
# url: https://github.com/you/my-repo.git
|
|
557
|
+
# path: apps/my-repo
|
|
558
|
+
# 3. git clone ngay repo đó vào apps/my-repo/
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
- Giống hệt `git clone <url>` về công dụng, nhưng **tự ghi lại vào manifest** —
|
|
562
|
+
không cần tay chỉnh `.project.yaml` rồi chạy lại `pan clone`.
|
|
563
|
+
- Đã có repo TÊN ĐÓ trong manifest rồi (kể cả khai ở `.project.local.yaml`) →
|
|
564
|
+
**không thêm trùng**, dùng lại URL/path đã khai, chỉ clone (idempotent — chạy
|
|
565
|
+
lại nhiều lần an toàn).
|
|
566
|
+
- `--dry-run` → in ra sẽ ghi gì / clone gì, KHÔNG đụng file `.project.yaml` và
|
|
567
|
+
không clone thật.
|
|
568
|
+
- `--base-dir DIR` áp dụng như các lệnh git khác (path tương đối tính từ đây).
|
|
569
|
+
- Muốn thêm repo riêng, không muốn commit chung với team? Đừng dùng cách này —
|
|
570
|
+
tự thêm tay vào `.project.local.yaml` (xem mục riêng phía trên) thay vào đó.
|
|
571
|
+
|
|
572
|
+
**Không có `.project.yaml`?** Mọi lệnh git ở trên (trừ `pan clone` — cần `url`
|
|
573
|
+
khai báo trong manifest, không tự suy ra được) vẫn chạy: nếu walk-up từ cwd
|
|
574
|
+
không thấy `.project.yaml`, CLI **fallback** coi **chính thư mục đang gõ
|
|
575
|
+
lệnh** là gốc dự án và quét git repo con bên trong (giống cách `pan stats`
|
|
576
|
+
fallback — pwd + tối đa 2 cấp con, bỏ qua `node_modules`/`.git`/`dist`/…). Nhờ
|
|
577
|
+
vậy dùng được `pan pull|push|fetch|checkout|sync-main|mr|grv|gst` ngay cả khi
|
|
578
|
+
chưa có/không dùng workspace pan-stack, miễn thư mục gốc chứa các repo git con.
|
|
579
|
+
|
|
580
|
+
### Bảng tổng hợp `pull` / `push` / `fetch` / `gst` / `clone` / `grv`
|
|
581
|
+
|
|
582
|
+
6 lệnh trên chạy git **im lặng** (không xả output raw của từng repo), in một dòng
|
|
583
|
+
tiến trình gọn cho mỗi repo (` ↻ csdl-cc-backend (main) ... fast-forward`), rồi
|
|
584
|
+
đóng bằng **bảng tổng hợp** ở cuối để bạn nhìn được ngay bức tranh tổng:
|
|
585
|
+
|
|
586
|
+
- **`pull`** — cột `result` (`up-to-date · fast-forward · merge · rebase · conflict · failed`), `changes` (`N files +add −del`), `conflict` (danh sách file mâu thuẫn ở footer nếu có).
|
|
587
|
+
- **`push`** — cột `result` (`pushed · up-to-date · rejected`), `commits` (số commit `ahead` trước push), `changes` (tổng `N files +add −del` cộng từ mọi commit sắp đẩy), `MR/PR link` (parse URL merge_request/pull do GitLab/GitHub in ở stderr; footer có tổng dòng đã push).
|
|
588
|
+
- **`fetch`** — chạy `git fetch --all --prune`, cột `behind/ahead` so upstream sau fetch (↓ = có commit mới ở remote → gợi ý `pan pull`), `new refs` (new / updated / tags / pruned).
|
|
589
|
+
- **`gst`** — chỉ liệt kê repo dirty / đang merge-rebase / lỗi; hiển thị `state`, `breakdown` (staged/unstaged/untracked), `behind/ahead`; repo sạch được đếm ẩn.
|
|
590
|
+
- **`clone`** — cột `result` (`cloned · already exists · no access · not found · failed`), `note` (dòng lỗi ngắn gọn — chỉ lấy dòng `fatal:`/`remote:`, KHÔNG in nguyên message thô/đường dẫn dài). Clone HẾT các repo rồi mới tổng hợp — 1 repo không có quyền/không tồn tại KHÔNG chặn các repo còn lại.
|
|
591
|
+
- **`grv`** — cột `remote` (tên remote, `origin (+N)` nếu có nhiều remote), `fetch`/`push` (URL; `push` in `=` khi giống hệt `fetch` cho gọn bảng).
|
|
592
|
+
|
|
593
|
+
Muốn xem output raw thô như trước? Dùng `--verbose` với `gst` (hoặc chạy `git`
|
|
594
|
+
trực tiếp trong repo).
|
|
595
|
+
|
|
596
|
+
## `pan stats` — Git contribution stats
|
|
597
|
+
|
|
598
|
+
Thống kê đóng góp Git cho các repo trong `.project.yaml` (đọc `git log`). Vì
|
|
599
|
+
PAN Stack là **vỏ bọc** và không phải ai cũng clone đủ repo, repo nào **thiếu /
|
|
600
|
+
không đọc được** sẽ được **báo lên report** (khung cảnh báo) thay vì làm hỏng
|
|
601
|
+
thống kê. Alias `pan graph`.
|
|
602
|
+
|
|
603
|
+
**Không có `.project.yaml`?** `pan stats` vẫn chạy: nếu walk-up không thấy
|
|
604
|
+
`.project.yaml`, nó **fallback** quét git từ **chính `pwd` xuống tối đa 2 cấp
|
|
605
|
+
con** (gồm bản thân `pwd`, thư mục con trực tiếp, và 1 cấp con nữa — đủ bắt
|
|
606
|
+
submodule), không đọc sâu hơn. Nhờ vậy dùng được kể cả khi chưa `pan create`/init
|
|
607
|
+
workspace.
|
|
608
|
+
|
|
609
|
+
| Command | Action |
|
|
610
|
+
| -------------------- | ------------------------------------------------------------------------------------------------ |
|
|
611
|
+
| `pan stats [report]` | Quét → dựng báo cáo HTML (Tailwind CDN, bảng màu FPT) → serve `localhost:4321` và mở trình duyệt |
|
|
612
|
+
| `pan stats people` | Liệt kê thành viên tham gia (gộp theo email) |
|
|
613
|
+
| `pan stats review` | Xuất Markdown code-change của 1 thành viên × 1 dự án cho AI review/chấm điểm |
|
|
614
|
+
|
|
615
|
+
Bộ lọc thời gian (dùng chung cho mọi lệnh):
|
|
616
|
+
|
|
617
|
+
- `--since <n>` — preset ngày: `1 2 3 4 5 7 14 30` (30 = "1 tháng")
|
|
618
|
+
- `--from <YYYY-MM-DD> --to <YYYY-MM-DD>` — khoảng ngày tuỳ chọn
|
|
619
|
+
- Không truyền → toàn bộ lịch sử
|
|
620
|
+
|
|
621
|
+
Options khác:
|
|
622
|
+
|
|
623
|
+
- `-m, --member <email|tên>` — lọc theo thành viên (bắt buộc với `review`)
|
|
624
|
+
- `-p, --project <tên repo>` — lọc theo dự án (bắt buộc với `review`)
|
|
625
|
+
- `--port <n>` — cổng serve (mặc định `4321`)
|
|
626
|
+
- `--no-open` — không tự mở trình duyệt
|
|
627
|
+
- `-o, --out <file>` — nơi ghi HTML/Markdown
|
|
628
|
+
- `--no-diff` — (`review`) chỉ tóm tắt, bỏ diff
|
|
629
|
+
- `--max-diff-lines <n>` — (`review`) giới hạn số dòng diff (mặc định `6000`)
|
|
630
|
+
- `--head-only` — chỉ quét HEAD hiện tại. **Mặc định** dùng `git log --all` để
|
|
631
|
+
gộp commit từ **mọi nhánh** (local + remote-tracking + tags), git tự dedupe
|
|
632
|
+
theo hash. Nếu đồng đội commit ở nhánh chưa có bản sao remote-tracking, chạy
|
|
633
|
+
`pan fetch` trước để cập nhật.
|
|
634
|
+
|
|
635
|
+
Báo cáo HTML tương tác (lọc chạy phía client trên toàn bộ commit đã nhúng):
|
|
636
|
+
|
|
637
|
+
- **Bộ lọc thời gian ngay trên trang**: nút preset `Tất cả · 1n · 2n · 3n · 4n ·
|
|
638
|
+
5n · 7n · 14n · 1 tháng` + ô `from → to` (Áp dụng) cho khoảng ngày tuỳ chọn.
|
|
639
|
+
- **Dropdown chọn thành viên (multi-select)**: checkbox từng người, "Chọn tất
|
|
640
|
+
cả / Bỏ chọn"; rỗng = tất cả. (Thay cho ô lọc text.)
|
|
641
|
+
- Mỗi thành viên một **card** (1/3 desktop · 50% tablet · full mobile), bấm để
|
|
642
|
+
bung danh sách dự án với commit + `+add`/`−del`; nút **"Mở tất cả"**.
|
|
643
|
+
- **Bảng tổng hợp** cuối trang có hàng TỔNG — tự cập nhật theo bộ lọc.
|
|
644
|
+
|
|
645
|
+
Các cờ CLI `--since/--from/--to/--member` chỉ đặt **giá trị khởi tạo** cho báo
|
|
646
|
+
cáo; sau đó lọc trực tiếp trên trình duyệt. (Merge commit bị loại; danh tính gộp
|
|
647
|
+
theo email — sửa tay qua `~/.pan-code-graph/alias-map.json`.)
|
|
648
|
+
|
|
649
|
+
`pan stats review` xuất file `.md` gồm bảng commit + diff, kèm sẵn **prompt chấm
|
|
650
|
+
điểm 1–10** (đúng đắn · chất lượng · an toàn · test · nhất quán) để dán cho AI.
|
|
651
|
+
|
|
652
|
+
Đầu ra lưu tại `~/.pan-code-graph/` (`report.html`, `review-*.md`, `alias-map.json`).
|
|
653
|
+
|
|
654
|
+
Ví dụ:
|
|
655
|
+
|
|
656
|
+
```bash
|
|
657
|
+
pan stats --since 7 # báo cáo 7 ngày gần đây
|
|
658
|
+
pan stats report --from 2026-07-01 --to 2026-07-22 # khoảng ngày tuỳ chọn
|
|
659
|
+
pan stats people --since 30 # ai tham gia trong 1 tháng
|
|
660
|
+
pan stats review -m an@fpt.com -p csdl-cc-backend --since 7 -o review.md
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
### `pan mr` — GitLab Merge Requests
|
|
664
|
+
|
|
665
|
+
Creates Merge Requests for the workspace stack root + each repo in `.project.yaml`
|
|
666
|
+
that has commits ahead of `origin/<target>`. Does NOT auto-push — run `pan push`
|
|
667
|
+
first if HEAD is not on the remote yet. Selection modes:
|
|
668
|
+
|
|
669
|
+
- `pan mr` — interactive checkbox picker (target = `main`)
|
|
670
|
+
- `pan mr develop` — interactive checkbox picker (target = `develop`)
|
|
671
|
+
- `pan mr main all` — non-interactive, all repos
|
|
672
|
+
- `pan mr main csdl-cc-backend,csdl-cc-b-frontend` — comma/space list
|
|
673
|
+
- `pan mr main csdl-cc-backend` — single repo
|
|
674
|
+
|
|
675
|
+
Interactive picker theo [quy ước chung](#quy-ước-chung-cho-mọi-menu-tương-tác-trong-pan) (`menuCheckbox`):
|
|
676
|
+
`↑↓` di chuyển · `space` chọn · `a` chọn tất cả · `i` đảo chọn · `x` thoát · `Enter` xác nhận
|
|
677
|
+
(nếu thiếu `@inquirer/core`, tự fallback `@inquirer/prompts` rồi readline nhập số).
|
|
678
|
+
|
|
679
|
+
Result rows: `✓` (new MR) · `=` (existing open MR) · `!` (needs `pan push` first) ·
|
|
680
|
+
`-` (skipped: no commits ahead / detached HEAD / already on target) · `✗` (error).
|
|
681
|
+
|
|
682
|
+
Token resolution: `--token` flag → `GITLAB_TOKEN` env var →
|
|
683
|
+
`<workspace>/.pan-env-build.yaml`. GitLab host is derived per-repo from the
|
|
684
|
+
`origin` remote URL; override with `--gitlab-host HOST` if needed.
|
|
685
|
+
|
|
686
|
+
### `pan checkout` — switch/create branches across repos
|
|
687
|
+
|
|
688
|
+
Chuyển hoặc tạo nhánh trên workspace stack root + các repo con trong `.project.yaml`.
|
|
689
|
+
Interactive checkbox picker (arrow keys + space) khi chạy trong TTY và không
|
|
690
|
+
truyền lựa chọn.
|
|
691
|
+
|
|
692
|
+
- `pan co main` — switch tất cả (tương tác chọn repo)
|
|
693
|
+
- `pan co -b feat/#1234` — tạo nhánh mới từ HEAD (tương tác chọn repo)
|
|
694
|
+
- `pan co -b feat/#1234 all` — tạo trên tất cả repo
|
|
695
|
+
- `pan co -b feat/#1234 csdl-cc-backend,csdl-cc-b-frontend` — tạo trên list cụ thể
|
|
696
|
+
- `pan co -B hotfix/x --start-point origin/main` — force-reset `hotfix/x` từ `origin/main`
|
|
697
|
+
- `pan co develop csdl-cc-backend` — switch một repo
|
|
698
|
+
|
|
699
|
+
Picker theo [quy ước chung](#quy-ước-chung-cho-mọi-menu-tương-tác-trong-pan): `↑↓` di chuyển ·
|
|
700
|
+
`space` chọn · `a` chọn tất cả · `i` đảo chọn · `x` thoát · `Enter` xác nhận. Non-TTY (stdin bị
|
|
701
|
+
pipe) hoặc CI thì bắt buộc truyền `all` / tên repo / list.
|
|
702
|
+
|
|
703
|
+
Flags:
|
|
704
|
+
|
|
705
|
+
- `-b <branch>` — `git checkout -b` (fail nếu nhánh đã tồn tại local)
|
|
706
|
+
- `-B <branch>` — `git checkout -B` (tạo hoặc reset về `--start-point`)
|
|
707
|
+
- `--start-point REF` — base ref cho `-b`/`-B` (default: HEAD hiện tại)
|
|
708
|
+
- `--no-workspace` — bỏ qua workspace stack root
|
|
709
|
+
|
|
710
|
+
Result rows: `✓` (chuyển/tạo mới) · `=` (đã ở nhánh đó) · `!` (nhánh đã tồn tại
|
|
711
|
+
khi dùng `-b` — dùng `-B` để reset hoặc bỏ `-b` để switch) · `-` (skipped: chưa
|
|
712
|
+
clone / dry-run) · `✗` (lỗi: branch không tồn tại, dirty tree conflict, start-point
|
|
713
|
+
không hợp lệ, v.v.). Không tự stash — commit hoặc `git stash` trước nếu dirty.
|
|
714
|
+
|
|
172
715
|
Works from child repo directories — the CLI walks up to find `.project.yaml`.
|
|
173
716
|
|
|
174
717
|
## Project commands
|
|
@@ -179,12 +722,12 @@ use `--project <name>` or pick interactively.
|
|
|
179
722
|
|
|
180
723
|
### Environment variables
|
|
181
724
|
|
|
182
|
-
| Variable
|
|
183
|
-
|
|
184
|
-
| `PAN_WORKSPACE_ROOT` | Directory containing `.project.yaml`
|
|
185
|
-
| `PAN_REPO_ROOT`
|
|
186
|
-
| `PAN_PROJECT_ROOT`
|
|
187
|
-
| `PAN_ARG_1`, …
|
|
725
|
+
| Variable | Meaning |
|
|
726
|
+
| -------------------- | ------------------------------------------- |
|
|
727
|
+
| `PAN_WORKSPACE_ROOT` | Directory containing `.project.yaml` |
|
|
728
|
+
| `PAN_REPO_ROOT` | Directory containing the active `.pan.yaml` |
|
|
729
|
+
| `PAN_PROJECT_ROOT` | Alias of `PAN_WORKSPACE_ROOT` |
|
|
730
|
+
| `PAN_ARG_1`, … | Arguments after the command name |
|
|
188
731
|
|
|
189
732
|
### Registry (optional)
|
|
190
733
|
|
|
@@ -202,11 +745,17 @@ pan-stack-cli/
|
|
|
202
745
|
platform.js # Windows/cross-platform helpers
|
|
203
746
|
manifest.js # YAML parsing
|
|
204
747
|
run-command.js # command execution
|
|
205
|
-
git/ # clone, pull, push, fetch, grv, gst
|
|
206
|
-
|
|
207
|
-
|
|
748
|
+
git/ # clone, pull, sync-main, push, fetch, mr, checkout, grv, gst
|
|
749
|
+
stats/ # pan stats: scan git log → report HTML / people / review md
|
|
750
|
+
skill-registry-client.js # HTTP client cho registry server (fetch/download/extract — dùng
|
|
751
|
+
# chung bởi `pan ai install/update`, `pan create`, `pan ui init`)
|
|
752
|
+
references/ # npm publish docs (KHÔNG publish lên npm — xem package.json "files")
|
|
208
753
|
```
|
|
209
754
|
|
|
755
|
+
Template (`pan create` scaffold + `pan ui init` mẫu landing/mobile/cms) **KHÔNG còn nằm
|
|
756
|
+
trong package này** — sống ở `apps/pan-agent-skill-registry/registry/templates/` và được
|
|
757
|
+
tải qua registry server lúc chạy (xem 2 mục ở trên).
|
|
758
|
+
|
|
210
759
|
## Local development
|
|
211
760
|
|
|
212
761
|
Install globally from source: [references/npm-development.md](references/npm-development.md).
|