@bifos/dooray-cli 0.15.1 → 0.16.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.md CHANGED
@@ -5,746 +5,221 @@
5
5
  [![CI](https://github.com/jon890/dooray-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/jon890/dooray-cli/actions/workflows/ci.yml)
6
6
  [![license](https://img.shields.io/npm/l/@bifos/dooray-cli.svg)](https://github.com/jon890/dooray-cli/blob/main/LICENSE)
7
7
 
8
- NHN Dooray REST API래핑한 CLI 도구입니다. 터미널과 AI 에이전트 환경에서 Dooray 업무를 관리할 있습니다.
8
+ [NHN Dooray](https://dooray.com) 를 AI 에이전트가 다룰 있게 만든 CLI 다.
9
9
 
10
- > A CLI tool wrapping the NHN Dooray REST API. Manage Dooray tasks from your terminal or AI agent workflows.
11
-
12
- ## 설치 (Installation)
10
+ 업무·댓글·위키·메일·메신저를 명령 줄로 처리하고, 결과를 `--json` 으로 내보낸다.
11
+ Claude Code 같은 에이전트에 스킬로 설치하면 "업무 만들어줘" 같은 자연어 지시를 그대로 처리한다.
13
12
 
14
13
  ```bash
15
14
  npm install -g @bifos/dooray-cli
16
- ```
17
-
18
- ## 초기 설정 (Setup)
19
-
20
- 대화형 마법사로 한 번에 설정할 수 있습니다:
21
-
22
- ```bash
23
15
  dooray setup
16
+ dooray skill install
24
17
  ```
25
18
 
26
- 아래 순서로 진행합니다:
27
- 1. API Endpoint 선택
28
- 2. API Key 입력
29
- 3. 연결 테스트
30
- 4. 메일 설정 (선택)
31
- API 토큰은 `https://{tenant}.dooray.com/setting/api/token`에서 발급할 수 있습니다.
32
-
33
- 수동 설정도 가능합니다:
34
-
35
- ```bash
36
- dooray config set base-url https://api.dooray.com
37
- dooray config set api-key <YOUR_API_TOKEN>
38
- dooray doctor
39
- ```
40
-
41
- ## Claude Code 스킬 관리
42
-
43
- AI 에이전트용 스킬은 CLI와 별도로 상태를 확인하고 갱신할 수 있습니다.
44
-
45
- ```bash
46
- dooray skill status # 설치 상태 확인
47
- dooray skill install # 최초 설치
48
- dooray skill update # 현재 CLI 버전의 스킬로 갱신
49
- dooray skill status --json # 자동화용 상태 확인
50
- ```
51
-
52
- Node 버전 관리자를 사용하면 전역 npm 설치 경로가 Node 버전별로 달라질 수 있습니다.
53
- 스킬은 npm 패키지 경로를 직접 가리키지 않고 관리 저장소를 거쳐 연결됩니다.
54
- 절대 경로 `XDG_DATA_HOME`이 있으면 `$XDG_DATA_HOME/dooray-cli/skills/`를 사용하고, 없거나 상대 경로이면 `~/.local/share/dooray-cli/skills/`를 사용합니다.
55
- 그래서 Node 버전 경로가 바뀌어도 Claude Code 활성 링크는 안정적으로 유지됩니다.
56
- 다만 `npm install -g @bifos/dooray-cli@latest`로 CLI를 갱신한 뒤에는 새 스킬 파일을 반영하기 위해 `dooray skill update`를 명시적으로 실행하세요.
57
- 기존 경로가 직접 만든 파일이나 디렉터리라면 기본 갱신은 중단됩니다.
58
- 그 경우 내용을 확인한 뒤 `dooray skill update --force`를 사용하면 기존 항목을 `.backup-<timestamp>` 경로로 백업하고 교체합니다.
59
-
60
- ## 사용법 (Usage)
61
-
62
- ### 프로젝트
63
-
64
- ```bash
65
- dooray project list # 프로젝트 목록 (기본: public)
66
- dooray project list --search ocr # 코드로 검색
67
- dooray project list --type private # 개인 프로젝트 목록
68
- dooray project members <project> # 멤버 목록
69
- dooray project workflows <project> # 워크플로우 목록
70
- dooray project groups <project> # 멤버 그룹 목록 (ID / Code)
71
- dooray project tags <project> # 태그 목록 (ID / Color / Name / Group / Mandatory)
72
- dooray project templates <project> # 템플릿 목록 (ID / Template Name)
73
- ```
74
-
75
- > **태그 캐시 갱신**: 이전 버전에서 캐시한 태그가 색상 없이 표시되면 `dooray cache clear` 실행 후 다시 조회하세요.
76
-
77
- ### 멤버
78
-
79
- ```bash
80
- dooray member list <project> # 프로젝트 멤버 목록 (이름·organizationMemberId)
81
- dooray member get <organizationMemberId> # 멤버 상세 (cache 우회)
82
-
83
- # organization 전체 멤버 검색
84
- dooray member search 홍길동 # 이름 검색
85
- dooray member search --email user@example.com # 이메일 (정확히 일치)
86
- dooray member search --user-code abc # 사번 like 검색
87
- dooray member search --user-code-exact abc123 # 사번 exact match
88
- dooray member search 김 --size 50 --page 1 # 페이지네이션
89
- ```
90
-
91
- ### 업무
92
-
93
- ```bash
94
- dooray post list <project> # 업무 목록 (최신순)
95
- dooray post search <project> "키워드" # 제목 검색
96
- dooray post get <project> 42 # 업무 상세
97
- dooray post get <project> 42 --json # JSON 출력
98
- ```
99
-
100
- #### 업무 식별 방식 (post 하위 16개 명령 공통)
101
-
102
- | 방식 | 예시 |
103
- |---|---|
104
- | `<project> <number>` | `dooray post get <project> 42` |
105
- | Dooray URL positional | `dooray post get https://x.dooray.com/task/to/<postId>` |
106
- | `--id <postId>` | `dooray post get --id <postId>` |
107
- | `--url <url>` | `dooray post get --url https://x.dooray.com/task/to/<postId>` |
108
-
109
- 지원 URL 형식 3종 (positional 첫 인자 / `--url` 공통):
110
-
111
- - `https://*.dooray.com/task/to/<postId>`
112
- - `https://*.dooray.com/task/<projectId>/<postId>` — 브라우저 주소창 복사본
113
- - `https://*.dooray.com/project/tasks/<postId>` — 프로젝트 업무 목록에서 열기
114
-
115
- 대상: `post get`/`edit`/`done`/`workflow`, `post comment list`/`add`/`edit`/`delete`, `post file list`/`upload`/`download`/`download-all`/`delete`.
116
- AI 에이전트는 사용자 메시지의 Dooray URL을 그대로 첫 인자로 전달하면 가장 빠르다.
117
-
118
- **projectId 직접 입력**:
119
-
120
- `member=me` 응답에 없는 프로젝트 (다른 팀 / 권한만 있는 프로젝트) 도 projectId (15+자리 numeric) 를 직접 입력하면 자동으로 cache 우회.
121
-
122
- ```bash
123
- # 코드 매칭 (기존)
124
- dooray post search <project> "keyword"
125
-
126
- # projectId 직접 입력 — member 아닌 프로젝트도 자동화 가능
127
- dooray post search 1234567890123456789 "keyword"
128
- dooray post list 1234567890123456789
129
- dooray member list 1234567890123456789
130
- ```
131
-
132
- 권한 검증은 후속 API 호출 시점 — 권한 없으면 4xx.
133
-
134
- ### 업무 생성
135
-
136
- ```bash
137
- dooray post create <project> \
138
- --title "업무 제목" \
139
- --body "본문 마크다운" \
140
- --to "담당자이름" \
141
- --priority normal
142
-
143
- # 본문을 파일에서 읽기 (--body와 --body-file은 동시 사용 불가)
144
- dooray post create <project> --title "업무 제목" --body-file ./content.md
145
-
146
- # 메타 옵션: --tag(반복) / --parent / --workflow / --milestone
147
- dooray post create <project> \
148
- --title "업무 제목" --body "본문" --to "담당자이름" \
149
- --tag "버그" --tag "긴급" \
150
- --parent "<project>/337" \
151
- --workflow "진행 중" \
152
- --milestone "Sprint 12"
153
- ```
154
-
155
- > mandatory-tag 정책 프로젝트(예: `<project>`)에서는 mandatory 그룹마다 1개 이상 `--tag`로 지정해야 한다.
156
- > 누락 시 클라이언트가 사전 검증으로 후보 목록과 함께 에러 출력.
157
-
158
- > **`post create` 출력의 `.id` 는 internal postId (19자리 숫자)입니다.**
159
- > 이 ID 로 후속 조회·수정·댓글 작업을 할 때는 **`--id <postId>`** 를 사용하세요.
160
- > `<project> <업무번호>` 의 번호 자리에 postId 를 넣으면 안내 에러가 발생합니다.
161
- >
162
- > ```bash
163
- > # 생성 후 바로 조회하는 패턴
164
- > POST_ID=$(dooray post create <project> --title "..." --json | jq -r '.id')
165
- > dooray post get --id "$POST_ID"
166
- > dooray post comment add --id "$POST_ID" --body "첫 댓글"
167
- > ```
168
-
169
- #### 템플릿 기반 정형 task
170
-
171
- ```bash
172
- # 프로젝트의 템플릿 목록
173
- dooray project templates <project>
174
-
175
- # 템플릿으로 업무 생성 (body/users/tags 자동 채움)
176
- dooray post create <project> --template "릴리스 플랜"
177
-
178
- # 사용자 옵션 override — 일부 필드만 다르게
179
- dooray post create <project> --template "릴리스 플랜" --title "v0.9 릴리스 계획" --tag "p0"
180
-
181
- # 19자리 templateId 직접 입력
182
- dooray post create <project> --template 1234567890123456789 --title "by id"
183
- ```
184
-
185
- `interpolation=true` 가 기본 — Dooray 가 `${year}`, `${month}` 같은 시스템 매크로를 응답에서 자동 치환.
186
- 사용자 정의 변수 (`--field key=value`) 는 본 release scope 외.
187
-
188
- ### 업무 수정
189
-
190
- ```bash
191
- # 대화형 ($EDITOR)
192
- dooray post edit <project> 42
193
-
194
- # 비대화형 (AI 에이전트 친화)
195
- dooray post edit <project> 42 --title "새 제목" --body "새 본문"
196
-
197
- # 본문을 파일에서 읽기
198
- dooray post edit <project> 42 --body-file ./updated.md
199
- ```
200
-
201
- #### 본문 변경 시 attachment 보호
202
-
203
- `post edit` 와 `post comment edit` 는 본문을 통째로 replace 합니다.
204
- 새 본문에 기존 inline attachment markdown(`![](/files/<id>)`)이 빠져 있으면 stderr 에 경고를 띄우고 (y/N) 로 물어봅니다.
205
-
206
- 자동화 환경 (pipe / non-TTY) 에서는 그대로 abort 됩니다. 의도한 변경이면 `--no-confirm` 으로 다시 실행하세요.
207
-
208
- ```bash
209
- echo "new body" | dooray post comment edit <project> <post-number> <comment-id> --body - --no-confirm
210
- ```
211
-
212
- ### 댓글
213
-
214
- ```bash
215
- dooray post comment list <project> 42
216
- dooray post comment add <project> 42 --body "댓글 내용"
217
- dooray post comment add <project> 42 --body-file ./comment.md
218
- ```
219
-
220
- > table 출력의 Creator 컬럼은 프로젝트 멤버 캐시로 자동 enrich되며, `--json`은 raw 응답을 유지한다.
221
-
222
- #### 멘션·내부 링크 자동 삽입
223
-
224
- ```bash
225
- # 댓글에 멤버·그룹 멘션
226
- dooray post comment add <project> <post-number> \
227
- --body "주간 리포트 첨부" \
228
- --mention "홍길동" \
229
- --mention-group <project>/dev
230
-
231
- # 본문에 다른 업무 링크 append
232
- dooray post create <project> \
233
- --title "이번 주 작업" \
234
- --body "관련 이슈" \
235
- --link-task <project>/470
236
-
237
- # 송신 전 합성 결과 미리보기
238
- dooray post comment add <project> <post-number> --body "..." --link-task <project>/470 --dry-run
239
- ```
240
-
241
- > `--mention` / `--mention-group` / `--link-task` / `--dry-run` 은 `post create`, `post edit`, `post comment add`, `post comment edit` 4 명령 모두 지원.
242
- > 이전 버전 캐시는 orgId가 없으므로 첫 호출 시 자동 갱신됩니다 (또는 `dooray cache clear`).
19
+ ## 설치와 설정
243
20
 
244
- #### 참조자(cc) / 담당자(to) 변경
21
+ Node.js 20 이상이 필요하다.
245
22
 
246
23
  ```bash
247
- # 멤버/그룹 추가 (기존 참조자 유지 + dedupe)
248
- dooray post edit <project> <post-number> \
249
- --cc 홍길동 --cc-group dev-team \
250
- --to 김철수
251
-
252
- # 기존 참조자 전부 비우고 신규만
253
- dooray post edit <project> <post-number> --cc-clear --cc 홍길동
254
-
255
- # 신규 업무 생성 시 그룹 cc 동봉
256
- dooray post create <project> --title "주간 audit" --cc-group dev-team
24
+ npm install -g @bifos/dooray-cli
257
25
  ```
258
26
 
259
- interactive ($EDITOR) 모드에서는 6개 옵션이 무시되고 stderr 경고가 출력됩니다.
260
- `post edit --dry-run --json` 사용 출력에 `users: { to, cc }` 가 포함되어 API 호출 없이 변경 결과 미리보기 가능.
261
- `post create --dry-run` 은 본문만 출력하며 `users` 는 포함하지 않음.
262
-
263
- **그룹 cc / mention 사용 예**:
264
-
265
- ```bash
266
- # code 부분일치
267
- dooray post create <project> ... --cc-group "개발"
268
-
269
- # code 정확 일치
270
- dooray post create <project> ... --mention-group "all"
271
-
272
- # 19자리 id 직접 입력 (response shape robustness 또는 code 누락 그룹 회피)
273
- dooray post create <project> ... --cc-group "<19자리 group id>"
274
-
275
- # 후보 탐색
276
- dooray project groups <project>
277
- ```
27
+ `dooray setup` API endpoint API key, 메일 설정까지 대화형으로 받는다.
28
+ API key Dooray 웹의 **설정 API 인증 토큰** 에서 만든다.
278
29
 
279
30
  ```bash
280
- dooray post edit <project> <post-number> --cc-group dev-team --dry-run --json | jq '.users.cc'
281
- # 출력 예: [{ "type": "group", "group": { "projectMemberGroupId": "...", "members": [] } }, ...]
31
+ dooray setup
32
+ dooray doctor # 설정이 제대로 됐는지 확인
282
33
  ```
283
34
 
284
- #### 생성 태그 변경
35
+ 에이전트에서 쓰려면 스킬을 설치한다. Claude Code 가 이 CLI 의 사용법을 알게 된다.
285
36
 
286
37
  ```bash
287
- # 기존 태그 유지 + 신규 추가 (dedupe)
288
- dooray post edit --id <postId> --tag "<group>: <name>"
289
-
290
- # 기존 태그 전부 제거 + 신규만 적용
291
- dooray post edit --id <postId> --tag-clear --tag "<group>: <name>"
292
-
293
- # 특정 태그만 제거 (기존 유지)
294
- dooray post edit --id <postId> --tag-remove "<group>: <name>"
38
+ dooray skill install
39
+ dooray skill status
295
40
  ```
296
41
 
297
- `--title` / `--body` 없이 단독 호출 가능 기존 본문은 자동 재전송.
298
- mandatory tag 그룹은 `post create` 와 동일하게 사전 검증.
42
+ CLI 버전으로 올린 뒤에는 `dooray skill update` 실행해야 스킬도 갱신된다.
299
43
 
300
- #### 상위 업무 변경 (`--parent`)
44
+ ## 사용법
301
45
 
302
- ```bash
303
- # 자식 업무에 부모 지정
304
- dooray post edit <project> <child-number> --title "<원제목>" --parent <project>/<parent-number>
46
+ 설정을 마치면 에이전트에게 한국어로 시키면 된다.
305
47
 
306
- # 다른 부모로 변경
307
- dooray post edit --id <postId> --title "<원제목>" --parent <other-parent-postId>
308
48
  ```
309
-
310
- 내부적으로 `client.updatePost` 호출 별도 `POST .../set-parent-post` endpoint 추가 호출.
311
- **parent 해제 (top-level 화)** Dooray API 가 미지원이라 웹 UI 에서 수동 처리.
312
-
313
- interactive ($EDITOR) 모드에서 `--parent` 사용 시 무시 + stderr 경고.
314
- **parent 단독 변경하려면 `--title "<원제목>"` 동반 필요** — `post edit` 는 본문 변경(`--title`/`--body`) 동반 시에만 non-interactive 분기로 들어감.
315
- parent 변경은 분기 안에서만 수행됨.
316
-
317
- `--dry-run --json` 출력의 `parentChange` 필드는 **사용자 입력 원문 그대로** (`<project>/<number>` 또는 raw postId).
318
- resolver 처리 전 미리보기 값이며 실제 호출 대상 `postId` 가 아님.
319
- dry-run 은 API 미호출 원칙을 유지해 `resolvePostRef` 도 건너뜀.
320
-
321
- #### `--to` / `--cc` / `--mention` 입력 형식 (자동 분기)
322
-
323
- 이름 외에도 이메일 / organizationMemberId 직접 입력 가능 — **동명이인 우회 + ID 직접 입력**:
324
-
325
- ```bash
326
- # 이름 (이전부터 지원, 부분일치)
327
- dooray post create <project> --title "..." --cc 홍길동
328
-
329
- # 이메일 (동명이인 우회)
330
- dooray post create <project> --title "..." --cc user@example.com
331
-
332
- # organizationMemberId 직접
333
- dooray post create <project> --title "..." --cc 1234567890123456789
49
+ "내 프로젝트 목록 보여줘"
50
+ "백엔드 프로젝트에 '로그인 실패 로그 확인' 업무 만들고 김철수 담당자로 지정해줘"
51
+ "42번 업무에 '80% 완료' 댓글 달아줘"
52
+ "이번 주 회의록 위키 페이지 만들어줘"
53
+ "안 읽은 메일 보여줘"
54
+ "개발팀 대화방에 배포 완료 알려줘"
55
+ "이 업무 완료 처리하고 담당자에게 알려줘"
334
56
  ```
335
57
 
336
- 분기 규칙 (`resolveMember` 자동 판단):
337
- - `^\d{15,}$`memberId 직접 사용
338
- - `^[^\s@]+@[^\s@]+\.[^\s@]+$` — 이메일, `searchMembers` exact 조회
339
- - 그 외 — 이름 부분일치
340
-
341
- `member search --email` 의 인프라 재사용.
342
-
343
- #### comment list 필터 옵션
344
-
345
- ```bash
346
- # 최신 5개 (desc 정렬)
347
- dooray post comment list <project> 42 --latest 5
348
-
349
- # 특정 시간 이후 댓글만
350
- dooray post comment list <project> 42 --since 2026-04-27
351
-
352
- # 작성자 이름으로 필터 (부분일치)
353
- dooray post comment list <project> 42 --from-author 홍길동
58
+ 에이전트가 알맞은 `dooray` 명령으로 옮기고, 필요하면 프로젝트 코드나 업무 번호를 먼저 조회한다.
59
+ 업무 URL 을 그대로 붙여도 된다 에이전트가 URL 에서 대상을 찾아낸다.
354
60
 
355
- # 오름차순 / 내림차순 정렬
356
- dooray post comment list <project> 42 --sort asc
357
- dooray post comment list <project> 42 --sort desc
358
- dooray post comment list <project> 42 --reverse # --sort desc alias
359
- ```
61
+ 에이전트가 쓰는 명령 카탈로그와 판단 기준은 [스킬 문서](skills/dooray-cli/SKILL.md)에 있다.
360
62
 
361
- #### comment latest
63
+ ## 에이전트 없이 직접 쓰기
362
64
 
363
- 최신 댓글 1개(또는 N개)를 빠르게 조회한다.
65
+ 터미널에서 바로 수도 있다.
364
66
 
365
67
  ```bash
366
- # 최신 댓글 1개
367
- dooray post comment latest <project> 42
368
-
369
- # 최신 3개
370
- dooray post comment latest <project> 42 -n 3
371
-
372
- # URL로도 가능
373
- dooray post comment latest --url <dooray-url>
68
+ dooray project list # 프로젝트
69
+ dooray post list <project> # 업무 목록
70
+ dooray post get <project> 42 # 업무 상세
71
+ dooray post create <project> --title "제목" # 업무 생성
72
+ dooray post comment add <project> 42 --body "댓글"
73
+ dooray wiki pages <project> # 위키 페이지 목록
74
+ dooray mail list --unread # 읽은 메일
374
75
  ```
375
76
 
376
- #### comment get
377
-
378
- 단일 댓글 ID 로 본문·메타·attachments 를 직접 fetch. `comment list` 후 jq 필터링 없이 바로 사용할 수 있어 자동화 파이프라인에 적합하다.
379
-
380
77
  ```bash
381
- # 단일 댓글 조회 (자동화 친화)
382
- dooray post comment get <project> <post-number> <comment-id> --json | jq -r '.body.content'
383
-
384
- # ID / URL 모드
385
- dooray post comment get --id <postId> --comment-id <commentId> --json
78
+ dooray post edit <project> 42 --cc-group <group-code> # 제목·본문 없이 참조자 그룹 추가
386
79
  ```
387
80
 
388
- ### 상태 변경
389
-
390
- ```bash
391
- dooray post done <project> 42 # 완료 처리
392
- dooray post workflow <project> 42 "진행 중" # 워크플로우 변경
393
- ```
81
+ 참조자·담당자 옵션만 지정하면 `$EDITOR`를 열지 않고 기존 제목·본문·태그를 보존한 채 참여자만 바꾼다.
394
82
 
395
- ### 위키
83
+ 전체 명령과 옵션은 `--help` 로 본다.
396
84
 
397
85
  ```bash
398
- dooray wiki list # 위키 목록
399
- dooray wiki pages <project> # 페이지 목록
400
- dooray wiki tree <project> # 페이지 계층 트리 (root 부터 재귀)
401
- dooray wiki tree <project> --depth 2 # 손자까지만
402
- dooray wiki page get <project> <page-id> # 페이지 상세
403
- dooray wiki page create <project> --title "..." [--parent <page-id>] [--body "..." | --body-file <path>]
404
- dooray wiki page edit <project> <page-id> --title "새 제목" # 제목만 (비대화형)
405
- dooray wiki page edit <project> <page-id> --body "..." | --body-file <path> # 본문만 (비대화형)
406
- dooray wiki page edit <project> <page-id> # $EDITOR (플래그 없을 때)
407
- dooray wiki page delete <project> <page-id> # 삭제 (y/N 확인)
408
- dooray wiki page delete <project> <page-id> --yes # 확인 없이 삭제 (자동화용)
86
+ dooray --help
87
+ dooray post --help
88
+ dooray post create --help
409
89
  ```
410
90
 
411
- 하위 페이지가 있는 페이지를 삭제하면 하위 페이지는 상위 페이지로 재부착된다 (사라지지 않음).
91
+ 출력은 가지 모드다.
412
92
 
413
- #### 위키 페이지 첨부파일
93
+ | 플래그 | 출력 | 쓰는 곳 |
94
+ | --- | --- | --- |
95
+ | (없음) | 사람이 읽는 표 | 터미널 |
96
+ | `--json` | JSON | 파싱, 명령 연결 |
97
+ | `--quiet` | ID 만 | 스크립트 |
414
98
 
415
- post `post file` 명령군과 동일 패턴 `<project> <page-id>` 외에도 `--id`/`--url`/positional URL 지원.
99
+ 전역 옵션이라 모든 명령에 붙일 있다. 서브커맨드의 `--help` 에는 나오지 않는다.
416
100
 
417
101
  ```bash
418
- # 목록 (general 첨부 + inline image 다 표시, type 컬럼)
419
- dooray wiki page file list <project> <page-id>
420
-
421
- # 업로드 (기본 general — 페이지 하단 첨부 영역)
422
- dooray wiki page file upload <project> <page-id> --file ./SKILL.md
423
- # stdout: attachFileId + 파일 메타 출력
424
-
425
- # 인라인 이미지 업로드 (본문 markdown 은 사용자가 직접 박음)
426
- dooray wiki page file upload <project> <page-id> --file ./diagram.png --type inline_image
427
- # stdout 에 본문 삽입용 markdown snippet 안내
428
-
429
- # 다운로드
430
- dooray wiki page file download <project> <page-id> --file-id <id> -o ./
431
-
432
- # 페이지 모든 첨부 (files + images) 일괄 다운로드
433
- dooray wiki page file download-all <project> <page-id> -o ./attachments/
434
-
435
- # 삭제 (confirm 없이 즉시)
436
- dooray wiki page file delete <project> <page-id> --file-id <id>
437
-
438
- # URL 모드 (--id 모드는 --project 동반 필요)
439
- dooray wiki page file list "https://<tenant>.dooray.com/wiki/<wikiId>/<pageId>"
440
- dooray wiki page file upload --id <pageId> --project <project> --file ./README.md
102
+ POST_ID=$(dooray post create <project> --title "배포" --quiet)
103
+ dooray post comment add --id "$POST_ID" --body "시작합니다"
441
104
  ```
442
105
 
443
- `--json` 옵션으로 자동화 파이프라인에서 동일 parse 코드를 사용할 수 있습니다:
444
-
445
- ```bash
446
- # download — { outputPath, fileName, size }
447
- dooray wiki page file download <project> <page-id> --file-id <id> -o ./ --json
448
-
449
- # download-all — { count, succeeded, failed } (부분 실패 시 exit 1)
450
- dooray wiki page file download-all <project> <page-id> -o ./ --json | jq '.failed'
451
-
452
- # delete — { fileId, status: "deleted" }
453
- dooray wiki page file delete <project> <page-id> --file-id <id> --json
454
-
455
- # upload (general) — res.result raw (--quiet 는 id 만)
456
- dooray wiki page file upload <project> <page-id> --file ./report.pdf --json
457
-
458
- # upload (inline_image) — res.result + markdownSnippet 필드 추가
459
- dooray wiki page file upload <project> <page-id> --file ./diagram.png --type inline_image --json
460
- # 출력 예:
461
- # {
462
- # "id": "<id>",
463
- # "attachFileId": "<attachFileId>",
464
- # "name": "diagram.png",
465
- # "size": 12345,
466
- # "type": "inline_image",
467
- # "markdownSnippet": "![diagram.png](/wikis/<wikiId>/files/<attachFileId>)"
468
- # }
469
-
470
- # 자동화: markdownSnippet 을 jq 로 추출해 본문에 삽입
471
- SNIPPET=$(dooray wiki page file upload <project> <page-id> --file ./diagram.png --type inline_image --json | jq -r '.markdownSnippet')
472
- ```
473
-
474
- **주의**:
475
- - `upload` 시 multipart 필드 순서 (`type` → `file`) 가 중요.
476
- 클라이언트가 자동으로 강제
477
- - `inline_image` 로 올린 파일은 본문에 markdown 으로 박혀야 위키에서 보임.
478
- `--json` 의 `markdownSnippet` 을 복사하거나 jq 로 추출해 `dooray wiki page edit` 본문에 직접 추가
479
- - `delete` 는 confirm 없이 즉시 삭제 (실수 방지 책임은 호출자)
480
-
481
- #### 위키 페이지 댓글
482
-
483
- post 의 `post comment` 명령군과 동일 패턴 — `<project> <page-id>` 외에도 `--id`/`--url`/positional URL 지원.
106
+ ### 댓글에 파일 첨부
484
107
 
485
108
  ```bash
486
- # 목록 (최신순)
487
- dooray wiki page comment list <project> <page-id>
488
- dooray wiki page comment list <project> <page-id> --latest 5
489
-
490
- # 최신 1건 shortcut
491
- dooray wiki page comment latest <project> <page-id>
492
-
493
- # 단일 조회
494
- dooray wiki page comment get <project> <page-id> <comment-id>
495
-
496
- # 추가 — interactive ($EDITOR) 또는 옵션
497
- dooray wiki page comment add <project> <page-id> # $EDITOR
498
- dooray wiki page comment add <project> <page-id> --body "회의 결정 사항"
499
- dooray wiki page comment add <project> <page-id> --body-file ./note.md
500
- echo "댓글" | dooray wiki page comment add <project> <page-id> --body -
501
-
502
- # 수정 — interactive ($EDITOR, 기존 본문 prefill) 또는 옵션
503
- dooray wiki page comment edit <project> <page-id> <comment-id> --body "..."
504
-
505
- # 삭제 (confirm 없이 즉시)
506
- dooray wiki page comment delete <project> <page-id> <comment-id>
507
-
508
- # URL 모드
509
- dooray wiki page comment list "https://<tenant>.dooray.com/wiki/<wikiId>/<pageId>"
109
+ dooray post comment file upload <project> <number> <comment-id> <path>
510
110
  ```
511
111
 
512
- **post comment 와의 차이**:
513
- - mention / cc / 받는 사람 미지원 wiki API 부재
514
- - 첨부 파일 미지원 — wiki comment 전용 endpoint 부재 (페이지 본문 파일은 `wiki page file` 사용)
515
- - 본문은 markdown 그대로 전송 (mimeType 자동)
112
+ 이미지 확장자는 이미지 마크다운으로, 그 외 파일은 일반 링크로 댓글 본문에 추가한다.
113
+ `comment file list`는 UI에서 직접 첨부한 파일을 놓칠 있으며, 이 경우 `post file list`로 확인한다.
516
114
 
517
- ### 메일
115
+ ### 삭제 명령의 확인
518
116
 
519
- IMAP을 통해 Dooray 메일을 조회할 수 있습니다. 메일 설정은 `dooray setup`에서 한 번에 진행하거나, 수동으로 설정할 수 있습니다.
117
+ | 영역 | 삭제 명령 |
118
+ | --- | --- |
119
+ | 업무 | `dooray post comment delete`<br>`dooray post file delete`<br>`dooray post comment file delete` |
120
+ | 위키 | `dooray wiki page delete`<br>`dooray wiki page file delete`<br>`dooray wiki page comment delete` |
520
121
 
521
- ```bash
522
- # 수동 설정 (dooray setup 사용 불필요)
523
- dooray config set imap-username user@example.com
524
- dooray config set imap-password <IMAP_APP_PASSWORD>
525
-
526
- # 메일 조회
527
- dooray mail list # 최근 메일 목록
528
- dooray mail list --unread # 안읽은 메일만
529
- dooray mail list --search "키워드" # 제목 검색
530
- dooray mail list --size 50 # 조회 개수 지정
531
- dooray mail get <uid> # 메일 상세
532
- dooray mail get <uid> --json # JSON 출력
533
-
534
- # 메일 발송
535
- dooray mail send --to "user@example.com" --subject "제목" --body "본문"
536
- dooray mail send --to "recipient@example.com" --cc "copy@example.com" --subject "제목" --body-file ./content.md
537
- dooray mail send --to "recipient@example.com" --subject "HTML 메일" --body "<h1>Hello</h1>" --html
538
-
539
- # 메일 답장 (스레드 유지)
540
- dooray mail reply <uid> --body "답장 내용"
541
-
542
- # 저장된 메일 사용자명·앱 비밀번호 제거
543
- dooray mail logout
544
- dooray mail logout --yes # 비대화형 환경
545
- ```
546
-
547
- ### 메신저
548
-
549
- Dooray 메신저로 1:1 다이렉트 메시지 또는 대화방 메시지를 보낼 수 있습니다.
550
- 전송은 API 토큰 소유자 명의로 나갑니다.
551
-
552
- ```bash
553
- # 1:1 다이렉트 메시지 (받는 사람은 organizationMemberId 또는 이메일)
554
- dooray messenger send --to "user@example.com" --body "배포 완료했습니다."
555
- dooray messenger send --to <memberId> --body-file ./message.md
122
+ 여섯 명령은 TTY에서 기본값이 아니오인 `y/N` 확인을 요청한다.
123
+ 자동화·파이프 non-TTY 실행에서는 `-y` 또는 `--yes`로 확인을 생략해야 한다.
124
+ 플래그가 없으면 삭제 API를 호출하기 전에 종료 코드 3으로 끝난다.
125
+ 기존 삭제 자동화에는 명시적인 yes 플래그를 추가해야 한다.
556
126
 
557
- # 대화방 메시지 (channelId 또는 대화방 이름)
558
- dooray messenger channel-send --channel "배포 알림방" --body "빌드 성공"
559
- dooray messenger channel-send --channel <channelId> --body-file - # stdin
127
+ ## 프로젝트 구조
560
128
 
561
- # --body 없이 실행하면 $EDITOR 로 본문을 작성
562
- dooray messenger send --to "user@example.com"
563
129
  ```
564
-
565
- - `--to`는 이름 검색을 지원하지 않습니다. organizationMemberId 또는 이메일만 입력하세요.
566
- - `--channel`은 채널 ID 또는 자신이 속한 대화방 이름(부분일치)으로 지정할 수 있습니다.
567
- 이름이 겹치는 대화방이 여러 개면 후보 목록이 함께 출력됩니다.
568
-
569
- ### 첨부파일
570
-
571
- 업무에 파일을 첨부하거나, 첨부된 파일을 다운로드할 수 있습니다.
572
-
573
- ```bash
574
- # 첨부파일 목록
575
- dooray post file list <project> <number>
576
-
577
- # 파일 다운로드
578
- dooray post file download <project> <number> <file-id>
579
- dooray post file download <project> <number> <file-id> -o ./downloads
580
-
581
- # 전체 파일 다운로드
582
- dooray post file download-all <project> <number> -o ./downloads
583
-
584
- # 파일 업로드
585
- dooray post file upload <project> <number> ./report.pdf
586
-
587
- # 파일 삭제
588
- dooray post file delete <project> <number> <file-id>
130
+ src/
131
+ index.ts CLI 진입점
132
+ api/ Dooray REST API 클라이언트 (ky), IMAP·SMTP 클라이언트
133
+ cache/ ~/.dooray/cache/ 파일 캐시
134
+ config/ ~/.dooray/config.json 스키마와 읽기·쓰기
135
+ resolvers/ 이름·이메일·URL 을 ID 로 바꾸는 계층
136
+ commands/ Commander.js 명령 정의
137
+ formatters/ 표·JSON·quiet 출력
138
+ editor/ $EDITOR 연동
139
+ skill/ Claude Code 스킬 설치·갱신
140
+ utils/ 에러, 스피너, 종료 코드
589
141
  ```
590
142
 
591
- 자동화 스크립트에서 `--json` 옵션으로 구조화된 출력을 파이프로 가공할 있습니다:
592
-
593
- ```bash
594
- # download — { outputPath, fileName, size }
595
- dooray post file download <project> <number> --file-id <id> -o ./ --json
596
- # 출력: {"outputPath": "./<fileName>", "fileName": "...", "size": 12345}
597
-
598
- # download-all — { count, succeeded, failed } (부분 실패 시 exit 1)
599
- dooray post file download-all <project> <number> -o ./ --json | jq '.failed'
600
- # 출력: [] 또는 [{"fileId": "...", "error": "..."}]
143
+ 의존 방향은 `api/` `resolvers/` `commands/` `formatters/` 다.
601
144
 
602
- # delete { fileId, status: "deleted" }
603
- dooray post file delete <project> <number> --file-id <id> --json
604
- # 출력: {"fileId": "...", "status": "deleted"}
145
+ | 문서 | 담는 |
146
+ | --- | --- |
147
+ | [docs/prd.md](docs/prd.md) | 제품 목적과 범위 |
148
+ | [docs/flow.md](docs/flow.md) | 사용자 흐름 |
149
+ | [docs/code-architecture.md](docs/code-architecture.md) | 디렉터리 트리, 레이어, API 전략 |
150
+ | [docs/data-schema.md](docs/data-schema.md) | 캐시 구조와 TTL |
151
+ | [docs/adr/INDEX.md](docs/adr/INDEX.md) | 기술 의사결정 기록 |
605
152
 
606
- # upload — res.result raw (--quiet 는 id 만)
607
- dooray post file upload <project> <number> ./report.pdf --json
608
- ```
609
-
610
- URL/`--id`/`--url` 모드에서는 sub-id를 옵션으로 전달:
611
- ```bash
612
- dooray post file download --url <url> --file-id <fileId> -o ./downloads
613
- dooray post file delete --url <url> --file-id <fileId>
614
- dooray post file upload --url <url> --file ./report.pdf
615
- dooray post comment edit --url <url> --comment-id <commentId> --body "..."
616
- dooray post comment delete --url <url> --comment-id <commentId>
617
- ```
153
+ ## 기여하기
618
154
 
619
- ### 댓글 첨부 파일 (`post comment file *`)
155
+ 이슈와 PR 모두 환영한다.
620
156
 
621
- 자동화로 댓글에 인라인 이미지 / 파일을 삽입할 때 사용.
622
- 4 명령 (list/upload/download/delete) 모두 `<project> <post-number> <comment-id>` 또는 `--id <postId> --comment-id <logId>` / `--url <url> --comment-id <logId>` 패턴 지원.
157
+ ### 개발 환경
623
158
 
624
159
  ```bash
625
- # 첨부 목록
626
- dooray post comment file list <project> <post-num> <comment-id>
627
-
628
- # 업로드 (post-level files API 로 업로드 + 댓글 본문에 markdown reference append)
629
- dooray post comment file upload <project> <post-num> <comment-id> ./screenshot.png
160
+ git clone https://github.com/jon890/dooray-cli.git
161
+ cd dooray-cli
162
+ pnpm install
630
163
 
631
- # 다운로드 (post-level 파일과 동일 UX 일관성 wrapper)
632
- dooray post comment file download <project> <post-num> <comment-id> <file-id> --out ./out.png
164
+ pnpm run build # tsup 으로 dist/index.js 단일 번들 생성
165
+ pnpm test # vitest
166
+ pnpm tsc --noEmit # 타입 검사 (빌드는 타입을 검사하지 않는다)
633
167
 
634
- # 삭제 (댓글 본문 markdown 제거 + post-level 파일 삭제, --yes 로 confirm 생략)
635
- dooray post comment file delete <project> <post-num> <comment-id> <file-id> --yes
168
+ node dist/index.js --help # 빌드 결과 직접 실행
169
+ npm link # dooray 명령으로 실행
636
170
  ```
637
171
 
638
- > Dooray REST API 댓글 전용 attachment endpoint 제공하지 않아 내부적으로
639
- > post-level files API 댓글 본문 PUT 합성으로 동작한다. 단일 명령
640
- > = 단일 파일 — 다중 파일은 호출자가 반복 호출.
172
+ `pnpm` 쓴다. 빌드는 `tsup`(esbuild) 담당하고 `tsc` 타입 검사 전용이므로,
173
+ 타입 오류를 잡으려면 `pnpm tsc --noEmit` 따로 돌려야 한다.
641
174
 
642
- ## 출력 모드
175
+ ### 명령을 추가할 때
643
176
 
644
- | 플래그 | 설명 | 용도 |
645
- |--------|------|------|
646
- | (없음) | 테이블 출력 | 사람이 읽기 좋음 |
647
- | `--json` | JSON 출력 | 파싱, 파이프라인 |
648
- | `--quiet` | ID만 출력 | 스크립팅 |
177
+ 1. `src/api/client.ts` API 호출을 추가한다. 기존 메서드로 되는지 먼저 확인한다
178
+ 2. 이름을 ID 로 바꿔야 하면 `src/resolvers/` 에 resolver 를 만든다. 매칭 정책은 정확일치 → 부분일치 → 모호하면 후보와 함께 에러다
179
+ 3. `src/commands/` 명령을 정의한다. 인접한 명령의 구조를 따르는 것이 가장 빠르다
180
+ 4. 출력은 `src/formatters/` 에서 표·JSON·quiet 모드를 모두 지원한다
181
+ 5. `src/**/*.test.ts` 테스트를 추가한다
649
182
 
650
- ```bash
651
- # 파이프라인 예시
652
- dooray post list <project> --json | jq '.[] | select(.priority == "high")'
653
- dooray post list <project> --quiet | xargs -I{} dooray post done <project> {}
654
- ```
183
+ 새 설정 값이 필요하면 `src/config/` 의 스키마와 `config set` 처리에 키를 추가한다.
655
184
 
656
- ## AI 에이전트 연동
185
+ Dooray API 동작이 문서와 다르거나 직관에 반하면 [docs/adr/](docs/adr/) 에 기록한다.
186
+ 파일 업로드의 307 리다이렉트나 multipart 필드 순서처럼, 모르고 접근하면 다시 막히는 것들이 이미 32건 쌓여 있다.
657
187
 
658
- `skills/dooray-cli/SKILL.md`에 AI 에이전트를 위한 스킬 파일이 포함되어 있습니다.
659
- Claude Code 등의 AI 에이전트에서 dooray-cli를 자동으로 활용할 수 있도록 의도→커맨드 매핑, 체이닝 예시, 에러 핸들링 가이드가 포함되어 있습니다.
188
+ ### PR
660
189
 
661
- ```bash
662
- # Claude Code 스킬 상태 확인과 설치
663
- dooray skill status
664
- dooray skill install
665
- ```
190
+ - 커밋과 PR 제목은 `type(scope): 설명` 형식을 쓴다
191
+ - 커밋 메시지와 PR 본문은 한국어로 쓴다
192
+ - PR 을 열면 CI 가 빌드와 테스트를 돌리고, Claude 가 코드 리뷰를 남긴다
193
+ - 리뷰의 🔴 항목은 머지 전에 반영한다
666
194
 
667
- ## 피드백 (GitHub Issue 등록)
195
+ ### 버그와 제안
668
196
 
669
- `dooray feedback` 명령으로 GitHub issue를 직접 등록할 있습니다 (`gh` CLI 위임).
197
+ CLI 안에서 바로 이슈를 만들있다.
670
198
 
671
199
  ```bash
672
- # 인터랙티브 (제목/본문/라벨 대화형 입력)
673
- dooray feedback
674
-
675
- # 논인터랙티브
676
- dooray feedback --title "버그 제목" --body "재현 방법"
677
-
678
- # --last 모드 (직전 에러 자동 첨부)
679
- dooray config set track-last-run true # 1회만, opt-in
680
- dooray feedback --last # 직전 명령 + 에러 자동 첨부 + $EDITOR로 의견 추가
681
- dooray feedback --last --title "재현" --body "추가 설명" --dry-run # 미리보기
682
-
683
- # 미리보기 (gh 호출 없이 본문 확인)
684
- dooray feedback --dry-run
200
+ dooray feedback # 대화형
201
+ dooray feedback --title "제목" --body "내용" --label bug
202
+ dooray feedback --last --title "에러 제목" # 직전 실패 명령을 자동 첨부
685
203
  ```
686
204
 
687
- > **개인정보 보호**: `--last` 모드에서 argv`--api-key`/`--token`/`Authorization` 시크릿 패턴을 자동 마스킹 저장합니다. cwd/env는 미저장.
205
+ `--last` 는 미리 켜야 한다: `dooray config set track-last-run true`.
206
+ argv 는 API 키 같은 값을 가린 뒤 저장한다.
688
207
 
689
- ## 캐시
690
-
691
- 프로젝트, 멤버, 워크플로우, 위키 정보는 `~/.dooray/cache/`에 캐시됩니다.
692
-
693
- ```bash
694
- dooray cache clear # 캐시 삭제
695
- dooray doctor # 캐시 상태 확인
696
- ```
208
+ [GitHub Issues](https://github.com/jon890/dooray-cli/issues) 에 직접 올려도 된다.
697
209
 
698
210
  ## 기술 스택
699
211
 
700
- - TypeScript + Commander.js
701
- - ky (fetch 기반 HTTP 클라이언트)
702
- - @inquirer/prompts (대화형 설정 마법사)
703
- - tsup (esbuild 번들러)
704
- - chalk + cli-table3 (출력 포맷)
705
-
706
- ## 개발
707
-
708
- ```bash
709
- pnpm install
710
- pnpm run build
711
- node dist/index.js --help
712
-
713
- # 글로벌 링크
714
- pnpm link --global
715
- dooray --help
716
- ```
717
-
718
- ## GitHub Actions
719
-
720
- 이 레포는 두 개의 워크플로를 사용합니다:
721
-
722
- ### CI (`.github/workflows/ci.yml`)
723
- - 트리거: `main` 으로 push, `main` 대상 PR
724
- - 동작: `pnpm install --frozen-lockfile`, `pnpm test`, `pnpm build` (Node 18, ubuntu-latest)
725
- - 별도 secret 불필요
726
-
727
- ### Claude code review (`.github/workflows/claude-code-review.yml`)
728
- - 트리거: PR opened, PR 댓글에 `/review` 포함
729
- - 동작: 4 병렬 specialist 에이전트 (TypeScript / Conventions / Security / Architecture) 가 인라인 리뷰 + 요약 댓글 1개 게시
730
- - 필요 secret: `CLAUDE_CODE_OAUTH_TOKEN`
731
-
732
- #### Secret 셋업
733
-
734
- 1. https://github.com/jon890/dooray-cli/settings/secrets/actions 접속
735
- 2. `New repository secret` → 이름 `CLAUDE_CODE_OAUTH_TOKEN` + 값 (Anthropic 에서 발급한 OAuth 토큰)
736
- 3. PR 을 열거나 PR 댓글에 `/review` 작성하면 자동 실행
737
-
738
- #### 비용 / 토큰
739
-
740
- 각 PR 당 4 specialist 가 모두 `haiku` 모델로 동작 — 평균 PR 1건 당 수십 센트 수준.
741
- PR 자동 트리거 비활성화하려면 `claude-code-review.yml` 의 `if:` 조건에서 `github.event_name == 'pull_request'` 분기를 제거하고 `/review` 댓글 트리거만 남길 수 있음.
742
-
743
- #### Fork PR 제한
744
-
745
- GitHub Actions 정책상 fork 에서 열린 PR 은 `secrets.CLAUDE_CODE_OAUTH_TOKEN` 에 접근 못 해 **자동 리뷰가 silent 하게 skip** 된다.
746
- fork 기여자가 리뷰를 받으려면 maintainer 가 PR 댓글에 `/review` 를 작성하여 base repo 컨텍스트로 워크플로를 트리거해야 한다.
212
+ | 분류 | 사용 |
213
+ | --- | --- |
214
+ | 언어·런타임 | TypeScript, Node.js 20+ |
215
+ | CLI 프레임워크 | Commander.js |
216
+ | HTTP | ky |
217
+ | 메일 | imapflow (조회), nodemailer (발송), mailparser |
218
+ | 출력 | chalk, cli-table3, ora |
219
+ | 대화형 입력 | @inquirer/prompts |
220
+ | 빌드 | tsup (CJS 단일 번들) |
221
+ | 테스트 | vitest |
747
222
 
748
- ## 라이센스
223
+ ## 라이선스
749
224
 
750
- [MIT](LICENSE)
225
+ MIT