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