rootr-cli 0.25.0 → 0.29.0

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.ko.md CHANGED
@@ -331,6 +331,33 @@ stdout 과 `--json` 출력은 그대로입니다. 끄려면 `ROOTR_MAIL_NOTICE=0
331
331
  키마다 한 번 붙입니다. 웹훅 요청은 서명되어 있습니다 — `add` 때 한 번 보이는 비밀값으로
332
332
  `X-Rootr-Signature: sha256=HMAC_SHA256(secret, 원문)` 을 확인하세요. 몸통에는 문서 내용이 없습니다(`apiUrl` 을 부르세요).
333
333
 
334
+ ### 내 도메인 연결 (domain)
335
+
336
+ 발행한 페이지(PAGE)를 내 도메인(`www.회사.co.kr`)에서 보통 홈페이지처럼 엽니다 — 첫 화면은 그 페이지, `/{하위}` 는
337
+ 공개된 하위 페이지, 루터 서명은 붙지 않습니다. Team 플랜부터, 워크스페이스 관리자만 됩니다.
338
+
339
+ - **무료 주소** `이름.rootr.site` — 결제·DNS 없이 바로 열립니다(워크스페이스당 3개, 영어 소문자·숫자·하이픈 3~30자, `www`·`api`·`admin` 같은 이름과 `rootr` 가 들어간 이름은 예약).
340
+ - **내 도메인** — 1개당 월 $10, 연 결제 시 월 $8(연 $96). "도메인 연결" 애드온의 자리를 하나 씁니다. 자리가 없으면
341
+ `402`(결제 필요)와 함께 설정 › 결제 주소를 알려 줍니다. 애드온이 있는데 꽉 찼으면 `--confirm-charge` 로 1개를 더 삽니다(일할 계산).
342
+ 해제하면 수량이 줄고(일할 환불), 마지막 하나면 이번 주기 끝에 애드온이 끝나도록 예약됩니다.
343
+
344
+ ```bash
345
+ rootr domain detect www.회사.co.kr # DNS 를 어디서 관리하는지(가비아·카페24·Cloudflare…) + 단계 안내
346
+ rootr domain add www.회사.co.kr /홈페이지 # 등록 — 넣을 한 줄과 그 업체 화면 기준 단계가 나온다
347
+ rootr domain add --subdomain acme /홈페이지 # 무료 주소 acme.rootr.site — 바로 열린다
348
+ rootr domain available acme # 무료 주소 이름을 쓸 수 있는지
349
+ rootr domain check <id> # 지금 다시 확인(연결 전이면 exit 2)
350
+ rootr domain list # 종류·상태(DNS 확인 중 / 인증서 발급 중 / 연결됨 / 일시 중지) + 자리 사용
351
+ rootr domain rename <id> www.right.co.kr # 연결 전 도메인의 이름 바꾸기(결제 그대로, 새 id)
352
+ rootr domain remove <id> # 연결 해제(업체 DNS 의 CNAME 줄도 지우세요)
353
+ ```
354
+
355
+ 고객이 넣는 것은 **딱 한 줄**입니다: 타입 `CNAME`, 이름 `www`, 값 `connect.rootr.site`. 그다음 HTTPS 인증서는
356
+ 루터가 알아서 발급하고 5분마다 다시 확인합니다 — 연결되면 등록한 사람에게 알림과 메일이 갑니다. 루트 도메인
357
+ (`회사.co.kr`)에는 CNAME 을 못 거는 곳이 많아 `www.` 으로 연결하고 루트는 포워딩합니다(업체별 방법이 안내에 나옵니다).
358
+ 같은 주소를 **다른 워크스페이스가 전에 등록했던** 경우에만 소유 확인 줄(`TXT`, 이름 `_rootr-verify.www`)이 하나 더 필요합니다 —
359
+ 남겨 둔 CNAME 으로 남의 도메인을 가로채지 못하게.
360
+
334
361
  ### 제보 보내기 (feedback)
335
362
 
336
363
  ```bash
@@ -378,7 +405,7 @@ rootr memory forget <id> # 폐기(--hard면 행 삭제)
378
405
 
379
406
  ## MCP 서버로 사용하기
380
407
 
381
- `rootr mcp`는 stdio로 MCP(Model Context Protocol) 서버를 구동합니다. 제공 도구 202종:
408
+ `rootr mcp`는 stdio로 MCP(Model Context Protocol) 서버를 구동합니다. 제공 도구 214종:
382
409
 
383
410
  노드를 가리키는 인자(`target`, `databaseId`, `spreadsheetId`, `formId`, `crmId`, `trackerId`,
384
411
  `recordingId`, `presentationId`, `whiteboardId`, `logId`, `parentId` 등)는 **노드 id와 경로를 모두**
@@ -530,6 +557,10 @@ rootr db buttons <표> --file buttons.json # 목록 통째로 저장(남길 것
530
557
  rootr db button-run <표> <버튼id> # 한 번 누르기 (--rows id,id 로 고른 행 지정)
531
558
  rootr db automations <표> --file rules.json # 자동 규칙 — 사람이 안 눌러도 도는 것
532
559
  rootr db view <표> <뷰> --scale year # 달력 보기를 주·달·해 중에서
560
+ rootr db view <표> <뷰> --density compact --freeze 1 # 촘촘한 줄 · 왼쪽 첫 칸 고정
561
+ rootr db column <표> 지원일 --time off --range off # 시간·기간 없이 날짜 하나만
562
+ rootr db column <표> 마감일 --overdue on # 지난 날짜를 빨갛게(기본은 꺼짐)
563
+ rootr db column <표> 특이사항 --wrap on --align center # 긴 글 줄바꿈 · 가운데 정렬
533
564
  ```
534
565
 
535
566
  ```json
@@ -839,6 +870,16 @@ rootr db view <표> <뷰> --scale year # 달력 보기를 주·달·해
839
870
  | `rootr_remove_doc_mail_webhook` | 내 받은 문서 웹훅 지우기 |
840
871
  | `rootr_test_doc_mail_webhook` | 시험 전송(doc_mail.test) 후 전달 결과 |
841
872
 
873
+ #### 내 도메인 연결 (워크스페이스 관리자, Team 플랜)
874
+
875
+ | 도구 | 설명 |
876
+ |---|---|
877
+ | `rootr_list_custom_domains` | 워크스페이스의 도메인 목록 — 종류(내 도메인·무료 주소)·상태·가리키는 페이지·넣을 DNS 줄·사이트 주소 + 자리 요약(`slots`) |
878
+ | `rootr_add_custom_domain` | 발행한 페이지를 내 도메인으로 연결 — 넣을 한 줄 + 이름서버로 짚은 업체(가비아·카페24·Cloudflare…)의 단계 안내(`instructions`). `subdomain` 이면 무료 주소(바로 열림), 자리가 꽉 찼으면 사람 동의 뒤 `confirmCharge: true` |
879
+ | `rootr_check_custom_domain` | 지금 다시 확인 — DNS·인증서 상태와 쉬운 말 사유 |
880
+ | `rootr_rename_custom_domain` | 연결 전 내 도메인의 이름 바꾸기(결제 자리는 새 이름으로 옮겨 감) |
881
+ | `rootr_remove_custom_domain` | 연결 해제(인증서 호스트도 바로 지움) |
882
+
842
883
  문서함은 워크스페이스가 아니라 **사람(이메일)**에 붙습니다. 사람 없는 워크스페이스 키(원격 커넥터)는
843
884
  그 키를 만든 구성원으로 동작합니다.
844
885
 
@@ -859,11 +900,20 @@ rootr db view <표> <뷰> --scale year # 달력 보기를 주·달·해
859
900
  `rootr_append_page_blocks`, `rootr_update_page`, `rootr_update_page_block`,
860
901
  `rootr_read_page_live_data`)로 저작합니다.
861
902
 
862
- HTML을 짜는 것이 아니라 **정해진 블록 15종을 골라 쌓습니다** — `hero` `text`
903
+ HTML을 짜는 것이 아니라 **정해진 블록 16종을 골라 쌓습니다** — `hero` `text`
863
904
  `features` `gallery` `pricing` `testimonials` `faq` `timeline` `cta` `footer` +
864
905
  표에서 값을 끌어오는 `liveStats` `liveTable` `liveChart` + 신청을 받는 `form` +
865
906
  방문자가 시간을 잡는 `booking`(`{bookingNodeId, headline?, type?}` — 예약을 켜고 공개한 표의 노드 id) +
866
- 자유 블록 `custom`.
907
+ 모션그래픽 동영상 `video` + 자유 블록 `custom`.
908
+
909
+ **같은 페이지 안 이동** — 버튼·링크의 `target`에 `{"kind":"block","blockId":"booking"}`을 주면 새 탭 없이
910
+ 그 블록까지 부드럽게 내려갑니다(인스타그램 앱 안 브라우저에서 사람을 잃지 않는 광고 랜딩용). 가리킨 블록이
911
+ 페이지에 없으면 400이라, 만들 때 그 블록에 `id`를 직접 붙여 둡니다. `text` 본문에서는 `[글](#블록id)`.
912
+
913
+ **동영상(Team 플랜)** — `hero.background`에 `{"kind":"video","attachmentId":"…","posterAttachmentId":"…"}`,
914
+ 동영상 블록은 `{attachmentId, posterAttachmentId?, caption?, aspect?: "16:9"|"9:16"|"1:1"|"4:5", bleed?}`.
915
+ 둘 다 소리 없이 자동 재생·반복·컨트롤 없음이고, 동작 줄이기를 켠 방문자에게는 포스터 그림만 보입니다.
916
+ 히어로 동영상에는 `portraitAttachmentId`·`portraitPosterAttachmentId`(휴대폰 세로판)를 더할 수 있습니다 — 세로 화면은 그 판을, 아니면 기본판을 하나만 내려받습니다.
867
917
 
868
918
  **랜딩 페이지**용으로 두 블록은 가운데 본문 기둥을 벗어나 화면 폭 전체를 쓸 수 있습니다.
869
919
  `hero`에 `size: "screen"`을 주면 화면 한 장을 채우는 큰 제목(화면 폭 전체·화면 높이·큰 글자)이 되고,
package/README.md CHANGED
@@ -11,7 +11,7 @@ citations back to the exact paragraph.
11
11
  *(한국어 문서: [README.ko.md](https://github.com/gwmage/rootr-cli/blob/main/README.ko.md))*
12
12
 
13
13
  - `rootr` CLI — documents, databases, forms, signed documents, publishing, permissions, memory
14
- - `rootr mcp` — stdio MCP server, **202 tools** (see [MCP tools](#mcp-tools))
14
+ - `rootr mcp` — stdio MCP server, **214 tools** (see [MCP tools](#mcp-tools))
15
15
 
16
16
  Plain Node.js ESM, no build step. Node 18+ (uses the built-in `fetch`).
17
17
 
@@ -201,10 +201,18 @@ rootr db rows-rm /projects/tasks --ids r1,r2 --yes
201
201
  rootr db duplicates /hr/applicants --row r9 # same person (dedupe column) + latest linked history
202
202
  rootr db merge /hr/applicants r9 --into r1 # merge a duplicate into the existing row
203
203
  rootr db keep-duplicate /hr/applicants r9 --from r1 # keep as a new row, link both
204
+ rootr db rename-col /hr/applicants "대처-클레임" "대처-청소 후 사진 제출" --dry # what follows a rename (formulas, {col} templates, rollups, forms, pages); drop --dry to rename
205
+ rootr db carry-over /hr/applicants r9 # re-application: copy the latest earlier row into r9 (earlier row untouched)
206
+ rootr db column-set /hr/applicants Phone --json '{"dedupe":true,"dedupeCarry":{"auto":true,"exclude":["Applied on"],"mark":{"Re-applied":true}}}'
207
+ rootr db column-set /hr/applicants Phone --json '{"validate":{"kind":"mobile_kr","mode":"block"}}' # also date · birthdate · range, mode warn
208
+ rootr db rule-violations /hr/applicants # existing values that break a validate rule (nothing changed)
204
209
  rootr db history /hr/applicants --row r1 # who changed what, when, how
205
210
  rootr db restore /hr/applicants --at 2026-10-15T09:00:00+09:00 --yes # rows + columns/views back to that time
206
211
  rootr db view /projects/tasks Calendar --scale month # views: table, board, calendar, timeline
207
212
  rootr db view /hr/applicants Board --cards "Interview date,Phone" # fields shown on board cards
213
+ rootr db view /hr/applicants Table --density compact --freeze 1 # compact rows, keep the first column fixed
214
+ rootr db column /hr/applicants "Applied on" --overdue off --time off --range off # plain single date, no red
215
+ rootr db column /hr/applicants Notes --wrap on --align center # wrap long text, center it
208
216
  rootr db lock /projects/tasks --schema managers --rows own --locked "Approved,Score"
209
217
  rootr db notify /projects/tasks --file rules.json # notification rules
210
218
  rootr db buttons /projects/tasks --file buttons.json # buttons that do work when pressed
@@ -248,8 +256,14 @@ rootr form mapping /intake/request # which column each questi
248
256
  rootr form mapping /intake/request --set '{"f_name":"p_title"}'
249
257
  rootr form responses /intake/request --latest # --latest = newest one per person
250
258
  rootr form response-edit <responseId> --values '{"Email":"a@b.com"}'
259
+ rootr form submit /intake/request --values '{"f_email":"a@b.com"}' \
260
+ --files '{"Portfolio":["a.pdf","b.png"]}' # uploads each file, then submits
251
261
  ```
252
262
 
263
+ A `file` question takes one file unless it has `"multiple": true` (add `"maxFiles": 5`
264
+ to cap it, default 10); then the answer is an array. `"allowImages": true` on a
265
+ `text`/`textarea` question lets respondents put images inside their answer.
266
+
253
267
  Run `form mapping` right after pointing a form at a hand-built table. Answers reach the
254
268
  table by matching the question name to the column name, so a question the table has no
255
269
  column for is **dropped with no error anywhere** — this command is the only place that
@@ -286,6 +300,37 @@ rootr readreq /handbook/policy.md --users u1,u2 --due 2026-10-01T00:00:00Z --ack
286
300
  rootr readreq /handbook/policy.md # who has read it, completion rate
287
301
  ```
288
302
 
303
+ ### Custom domains (your own website address)
304
+
305
+ Open a published PAGE at your own domain (`www.customer.co.kr`) as a normal website — the root shows the
306
+ page, `/{child}` shows its published child pages, and there is no Rootr signature. Team plan and up,
307
+ workspace admins only.
308
+
309
+ - **Free address** `name.rootr.site` — live at once, no DNS and no payment (3 per workspace; lowercase a-z, 0-9 and
310
+ hyphen, 3–30 chars; names like `www`, `api`, `admin` and anything containing `rootr` are reserved).
311
+ - **Your own domain** — $10/month per domain, $8/month billed yearly ($96/year): one slot of the "Custom domain"
312
+ add-on. With no free slot the API answers `402` and points to Settings → Billing; when the add-on exists but is
313
+ full, `--confirm-charge` buys one more slot (prorated). Removing a domain lowers the quantity (prorated credit);
314
+ removing the last one schedules the add-on to end at the end of the billing period.
315
+
316
+ ```bash
317
+ rootr domain detect www.customer.co.kr # where is the DNS managed (Gabia, Cafe24, Cloudflare…) + the steps
318
+ rootr domain add www.customer.co.kr /홈페이지 # register; prints the one DNS line and provider-specific steps
319
+ rootr domain add --subdomain acme /홈페이지 # free address acme.rootr.site — live immediately
320
+ rootr domain available acme # is acme.rootr.site free to take
321
+ rootr domain check <id> # re-check now (exit 2 until it is live)
322
+ rootr domain list # kind, status (waiting for DNS / issuing certificate / connected / paused) + slot usage
323
+ rootr domain rename <id> www.right.co.kr # fix the name of a not-yet-live domain (billing unchanged, new id)
324
+ rootr domain remove <id> # disconnect (then remove the CNAME at your provider)
325
+ ```
326
+
327
+ The customer adds exactly **one** DNS line: `CNAME`, name `www`, value `connect.rootr.site`. Rootr then
328
+ issues the HTTPS certificate on its own and re-checks every 5 minutes; whoever registered the domain
329
+ gets a notification and an email when it goes live. A bare root domain (`customer.co.kr`) usually
330
+ cannot hold a CNAME — connect `www.` and forward the root to it (the guide shows how for your provider).
331
+ Only when the same name was registered before by a *different* workspace, one extra `TXT` line
332
+ (`_rootr-verify.www`) is required, so nobody can take over a domain whose CNAME was left behind.
333
+
289
334
  ### Signed documents and research notes
290
335
 
291
336
  A signed document is a markdown document whose body **freezes the moment it is submitted**; the
@@ -444,7 +489,7 @@ is refused and says when the grace was used.
444
489
 
445
490
  ## MCP tools
446
491
 
447
- `rootr mcp` speaks MCP over stdio. 202 tools:
492
+ `rootr mcp` speaks MCP over stdio. 214 tools:
448
493
 
449
494
  | Group | Count | Tools |
450
495
  |---|---|---|
@@ -470,6 +515,7 @@ is refused and says when the grace was used.
470
515
  | Visitor booking & Google Calendar | 6 | turn a published table into a booking page, rules, open slots, connect / list / disconnect Google Calendar |
471
516
  | Root-cause Q&A | 1 | ask the workspace knowledge graph, answer with citations |
472
517
  | Feedback | 1 | send feedback to the Rootr team |
518
+ | Custom domains | 4 | list (with kind + slot usage), add (own domain: the one DNS line + click-by-click steps for the detected DNS provider; `subdomain` for a free name.rootr.site; `confirmCharge` after the person agrees to buy a slot), check now, remove |
473
519
 
474
520
  Two gaps keep breathing room: `bufferMin` around bookings made through the table (CLI `--buffer`) and
475
521
  `calendarBufferMin` around events already on the connected Google Calendar, e.g. travel time to an outside
@@ -506,11 +552,23 @@ signed-document, issue, CRM and LOG tools need `docs:read` / `docs:write`; `root
506
552
  ### Pages
507
553
 
508
554
  A PAGE is **a screen for people outside the workspace** — an event announcement, a product page,
509
- a sign-up. You do not write HTML: you stack **15 predefined block types** — `hero`, `text`,
555
+ a sign-up. You do not write HTML: you stack **16 predefined block types** — `hero`, `text`,
510
556
  `features`, `gallery`, `pricing`, `testimonials`, `faq`, `timeline`, `cta`, `footer`, the
511
557
  table-backed `liveStats`, `liveTable`, `liveChart`, the `form` block, the `booking` block
512
558
  (a visitor scheduling calendar: `{bookingNodeId, headline?, type?}` — the node id of a published
513
- table with visitor booking on) — plus the free-form `custom`.
559
+ table with visitor booking on), the `video` block (a looping motion-graphic clip) — plus the free-form `custom`.
560
+
561
+ **Same-page links.** A button or link `target` can be `{"kind":"block","blockId":"booking"}` — it
562
+ jumps to that block on the same page (smooth scroll, same tab; ideal for a hero "Book now" button
563
+ on an ad landing page opened in an in-app browser). The block must exist on the page (else 400),
564
+ so give it an explicit `id`. In a `text` block, `[label](#<blockId>)` does the same.
565
+
566
+ **Videos (Team plan).** `hero.background` can be `{"kind":"video","attachmentId":"…","posterAttachmentId":"…"}`
567
+ and the `video` block is `{attachmentId, posterAttachmentId?, caption?, aspect?: "16:9"|"9:16"|"1:1"|"4:5", bleed?}`.
568
+ Both autoplay muted and looped with no controls; the poster shows for reduced-motion visitors. A hero video can add
569
+ `portraitAttachmentId` / `portraitPosterAttachmentId` — a vertical cut that portrait phone screens play instead (only one file is downloaded). Upload the
570
+ mp4 with `POST /v1/attachments/upload?workspaceId=…&nodeId=<page>&mimeType=video/mp4` (body = bytes,
571
+ `Content-Type: application/octet-stream`).
514
572
 
515
573
  For a **landing page**, two options let a block use the whole page width instead of the centred
516
574
  text column: `hero` with `size: "screen"` is a full-screen hero (edge to edge, one viewport tall,