@decencia/ch-cli 1.0.0 → 1.1.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.
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerSetupSkillCommand(program: Command): void;
3
+ //# sourceMappingURL=setup-skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-skill.d.ts","sourceRoot":"","sources":["../../src/commands/setup-skill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyBhE"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.registerSetupSkillCommand = registerSetupSkillCommand;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const os = __importStar(require("os"));
40
+ const output_1 = require("../output");
41
+ function registerSetupSkillCommand(program) {
42
+ program
43
+ .command('setup-skill')
44
+ .description('Claude Code 스킬을 ~/.claude/skills/에 설치')
45
+ .action(() => {
46
+ const srcPath = path.join(__dirname, '..', 'skill', 'SKILL.md');
47
+ const destDir = path.join(os.homedir(), '.claude', 'skills', '2t-decencia-channel-cli');
48
+ const destPath = path.join(destDir, 'SKILL.md');
49
+ try {
50
+ if (!fs.existsSync(srcPath)) {
51
+ (0, output_1.printError)(`패키지 내 SKILL.md를 찾을 수 없습니다: ${srcPath}`);
52
+ return;
53
+ }
54
+ if (!fs.existsSync(destDir)) {
55
+ fs.mkdirSync(destDir, { recursive: true });
56
+ }
57
+ fs.copyFileSync(srcPath, destPath);
58
+ (0, output_1.printSuccess)(`Claude Code 스킬이 설치되었습니다: ~/.claude/skills/2t-decencia-channel-cli/SKILL.md`);
59
+ }
60
+ catch (err) {
61
+ (0, output_1.printError)(`스킬 설치 중 오류가 발생했습니다: ${err.message}`);
62
+ }
63
+ });
64
+ }
65
+ //# sourceMappingURL=setup-skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-skill.js","sourceRoot":"","sources":["../../src/commands/setup-skill.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,8DAyBC;AA9BD,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AACzB,sCAAqD;AAErD,SAAgB,yBAAyB,CAAC,OAAgB;IACxD,OAAO;SACJ,OAAO,CAAC,aAAa,CAAC;SACtB,WAAW,CAAC,uCAAuC,CAAC;SACpD,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,yBAAyB,CAAC,CAAC;QACxF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAEhD,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,IAAA,mBAAU,EAAC,8BAA8B,OAAO,EAAE,CAAC,CAAC;gBACpD,OAAO;YACT,CAAC;YAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,CAAC;YAED,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YACnC,IAAA,qBAAY,EAAC,4EAA4E,CAAC,CAAC;QAC7F,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,IAAA,mBAAU,EAAC,uBAAuB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
package/dist/index.js CHANGED
@@ -51,6 +51,7 @@ const prd_1 = require("./commands/prd");
51
51
  const db_schema_1 = require("./commands/db-schema");
52
52
  const notifications_1 = require("./commands/notifications");
53
53
  const dashboard_1 = require("./commands/dashboard");
54
+ const setup_skill_1 = require("./commands/setup-skill");
54
55
  // Read version from package.json
55
56
  function getVersion() {
56
57
  try {
@@ -89,6 +90,7 @@ program
89
90
  (0, db_schema_1.registerDbSchemaCommand)(program);
90
91
  (0, notifications_1.registerNotificationsCommand)(program);
91
92
  (0, dashboard_1.registerDashboardCommand)(program);
93
+ (0, setup_skill_1.registerSetupSkillCommand)(program);
92
94
  // Parse and execute
93
95
  program.parseAsync(process.argv).catch((err) => {
94
96
  console.error(err);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,yCAAoC;AACpC,2CAA6B;AAC7B,uCAAyB;AAEzB,0CAAsD;AACtD,0CAAsD;AACtD,kDAA8D;AAC9D,4CAAwD;AACxD,gDAA4D;AAC5D,wCAAoD;AACpD,wCAAoD;AACpD,kDAA8D;AAC9D,gDAA4D;AAC5D,sDAAiE;AACjE,wCAAoD;AACpD,oDAA+D;AAE/D,4DAAwE;AACxE,oDAAgE;AAEhE,iCAAiC;AACjC,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,IAAI,CAAC;KACV,WAAW,CAAC,oCAAoC,CAAC;KACjD,OAAO,CAAC,UAAU,EAAE,EAAE,eAAe,EAAE,OAAO,CAAC;KAC/C,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC;KAChC,MAAM,CAAC,SAAS,EAAE,mBAAmB,CAAC;KACtC,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC;KAC9B,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;KAChD,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC;KAC/B,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAAC;KACnC,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AAEtC,+BAA+B;AAC/B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;AACjC,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,gCAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;AACjC,IAAA,gCAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,qCAAwB,EAAC,OAAO,CAAC,CAAC;AAClC,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,mCAAuB,EAAC,OAAO,CAAC,CAAC;AAEjC,IAAA,4CAA4B,EAAC,OAAO,CAAC,CAAC;AACtC,IAAA,oCAAwB,EAAC,OAAO,CAAC,CAAC;AAElC,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,yCAAoC;AACpC,2CAA6B;AAC7B,uCAAyB;AAEzB,0CAAsD;AACtD,0CAAsD;AACtD,kDAA8D;AAC9D,4CAAwD;AACxD,gDAA4D;AAC5D,wCAAoD;AACpD,wCAAoD;AACpD,kDAA8D;AAC9D,gDAA4D;AAC5D,sDAAiE;AACjE,wCAAoD;AACpD,oDAA+D;AAE/D,4DAAwE;AACxE,oDAAgE;AAChE,wDAAmE;AAEnE,iCAAiC;AACjC,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,IAAI,CAAC;KACV,WAAW,CAAC,oCAAoC,CAAC;KACjD,OAAO,CAAC,UAAU,EAAE,EAAE,eAAe,EAAE,OAAO,CAAC;KAC/C,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC;KAChC,MAAM,CAAC,SAAS,EAAE,mBAAmB,CAAC;KACtC,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC;KAC9B,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;KAChD,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC;KAC/B,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAAC;KACnC,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AAEtC,+BAA+B;AAC/B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;AACjC,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,gCAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;AACjC,IAAA,gCAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,qCAAwB,EAAC,OAAO,CAAC,CAAC;AAClC,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,mCAAuB,EAAC,OAAO,CAAC,CAAC;AAEjC,IAAA,4CAA4B,EAAC,OAAO,CAAC,CAAC;AACtC,IAAA,oCAAwB,EAAC,OAAO,CAAC,CAAC;AAClC,IAAA,uCAAyB,EAAC,OAAO,CAAC,CAAC;AAEnC,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,11 +1,15 @@
1
1
  {
2
2
  "name": "@decencia/ch-cli",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Decencia Communication Channel CLI",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "ch": "dist/index.js"
8
8
  },
9
+ "files": [
10
+ "dist/",
11
+ "skill/"
12
+ ],
9
13
  "scripts": {
10
14
  "build": "tsc",
11
15
  "dev": "tsc --watch",
package/skill/SKILL.md ADDED
@@ -0,0 +1,490 @@
1
+ ---
2
+ name: "[2t] decencia-channel-cli"
3
+ tier: 2t
4
+ description: |
5
+ [2t] 디센시아 소통채널 CLI(ch) 설치, 설정, 사용법 가이드. AI 에이전트가 소통채널 내 문서(PRD, 기능명세, 스프린트, QnA, SQA, 아카이브, 개발현황, DB 스키마)를 CLI로 조작할 수 있도록 한다.
6
+ Use when: (1) 소통채널 CLI를 설치하거나 설정할 때,
7
+ (2) AI 에이전트가 소통채널 데이터를 조회/조작해야 할 때,
8
+ (3) "ch" 명령어 사용법이 필요할 때,
9
+ (4) "소통채널 CLI" or "ch-cli" 관련 작업을 할 때,
10
+ (5) 프로젝트의 기능명세/스프린트/QnA/SQA/아카이브/개발현황/DB스키마를 CLI로 관리할 때.
11
+ ---
12
+
13
+ # Decencia Communication Channel CLI (ch)
14
+
15
+ 소통채널의 모든 기능을 CLI로 조작하는 도구. API Key + Project ID 인증 기반.
16
+
17
+ ## 1. 설치
18
+
19
+ ```bash
20
+ # npm에서 글로벌 설치 (권장)
21
+ npm install -g @decencia/ch-cli
22
+
23
+ # 또는 소스에서 직접 빌드
24
+ cd C:\myprojects\decenciahomepage\ch-cli
25
+ npm install && npm run build
26
+ npm link
27
+ ```
28
+
29
+ ## 2. 초기 설정
30
+
31
+ ### 2-1. 로그인 (글로벌 설정)
32
+
33
+ ```bash
34
+ # API Key + Project ID로 로그인 (설정은 ~/.ch/config.json에 저장)
35
+ ch auth login --key <API_KEY> --project-id <PROJECT_ID>
36
+
37
+ # 인증 상태 확인
38
+ ch auth status
39
+
40
+ # 프로젝트 전환
41
+ ch auth switch --project-id <OTHER_PROJECT_ID>
42
+
43
+ # 로그아웃
44
+ ch auth logout
45
+ ```
46
+
47
+ ### 2-2. 로컬 프로젝트 설정 (.ch-project)
48
+
49
+ 여러 프로젝트를 오갈 때 projectId가 뒤바뀌는 사고를 방지하기 위해, 프로젝트 디렉토리마다 `.ch-project` 파일을 생성한다.
50
+
51
+ ```bash
52
+ # 현재 디렉토리에 .ch-project 파일 생성 (API에서 프로젝트명 자동 조회)
53
+ ch init --project-id <PROJECT_ID>
54
+
55
+ # 프로젝트명 직접 지정
56
+ ch init --project-id <PROJECT_ID> --project-name "프로젝트명"
57
+
58
+ # 현재 설정 상태 확인 (로컬 + 글로벌)
59
+ ch status
60
+ ```
61
+
62
+ #### 설정 우선순위
63
+
64
+ ```
65
+ --project CLI 옵션 > .ch-project (로컬) > ~/.ch/config.json (글로벌)
66
+ ```
67
+
68
+ - `.ch-project` 파일은 현재 디렉토리 → 상위 디렉토리로 탐색 (monorepo 지원)
69
+ - `.ch-project`에 `projectName`이 있으면 CLI 출력에 프로젝트명 프리픽스 표시:
70
+ `[법인·개인 자동수취 프로그램] DB 스키마가 저장되었습니다.`
71
+
72
+ #### .ch-project 파일 형식
73
+ ```json
74
+ {
75
+ "projectId": "yRZxS9CFfMa3Y0Q5Ey7x",
76
+ "projectName": "법인·개인 자동수취 프로그램"
77
+ }
78
+ ```
79
+
80
+ #### ~/.ch/config.json (글로벌 설정)
81
+ ```json
82
+ {
83
+ "apiKey": "발급받은 API Key",
84
+ "projectId": "프로젝트 ID (폴백용)",
85
+ "apiUrl": "https://ch-api-618529407342.asia-northeast3.run.app",
86
+ "defaultFormat": "table"
87
+ }
88
+ ```
89
+
90
+ > **주의**: `.ch-project` 없이 글로벌 config만 사용하면, 프로젝트를 전환할 때 다른 프로젝트에 데이터가 들어가는 사고가 발생할 수 있다. **프로젝트 디렉토리마다 `ch init`을 실행하는 것을 강력 권장한다.**
91
+
92
+ ## 3. 글로벌 옵션
93
+
94
+ 모든 명령에 적용 가능한 옵션:
95
+
96
+ | 옵션 | 설명 |
97
+ |------|------|
98
+ | `--json` | JSON 형식 출력 (AI 에이전트 파싱에 적합) |
99
+ | `--table` | 테이블 형식 출력 (기본값) |
100
+ | `--csv` | CSV 형식 출력 |
101
+ | `--project <id>` | 프로젝트 ID 오버라이드 (config 무시) |
102
+ | `--verbose` | 상세 로그 (디버깅용) |
103
+ | `--quiet` | 결과만 출력 (스크립팅용) |
104
+ | `--dry-run` | 쓰기 작업 시뮬레이션 (실제 반영 안함) |
105
+
106
+ **AI 에이전트 사용 시 `--json` 필수 권장** — 파싱이 쉬운 JSON 출력.
107
+
108
+ ## 4. 전체 명령어 레퍼런스
109
+
110
+ ---
111
+
112
+ ### 4.0 init / status — 로컬 프로젝트 설정
113
+
114
+ ```bash
115
+ ch init --project-id <PID> [--project-name <NAME>] # .ch-project 파일 생성
116
+ ch status # 현재 프로젝트 설정 상태 확인
117
+ ```
118
+
119
+ ---
120
+
121
+ ### 4.1 auth — 인증/세션 관리
122
+
123
+ ```bash
124
+ ch auth login --key <KEY> --project-id <PID> [--api-url <URL>] # 로그인
125
+ ch auth status # 인증 상태 확인
126
+ ch auth logout # 로그아웃
127
+ ch auth switch --project-id <PID> # 프로젝트 전환
128
+ ch auth keys list # API Key 목록
129
+ ch auth keys create --name <NAME> # API Key 발급
130
+ ch auth keys revoke <keyId> # API Key 폐기
131
+ ```
132
+
133
+ ---
134
+
135
+ ### 4.2 projects — 프로젝트 관리
136
+
137
+ ```bash
138
+ ch projects list # 프로젝트 목록
139
+ ch projects create --name <NAME> [--desc <DESC>] # 프로젝트 생성
140
+ ch projects info # 현재 프로젝트 상세
141
+ ch projects update [--name <NAME>] [--desc <DESC>] # 프로젝트 수정
142
+ ch projects archive # 아카이브
143
+ ch projects unarchive # 아카이브 해제
144
+ ch projects delete --confirm <PROJECT_NAME> # 영구 삭제
145
+
146
+ # 스키마 관리 (기능명세의 드롭다운 옵션 설정)
147
+ ch projects set-schema [--devices d1,d2] [--domains d1,d2] [--types t1,t2] [--permissions p1,p2]
148
+ ch projects get-schema # 현재 스키마 조회
149
+ ```
150
+
151
+ ---
152
+
153
+ ### 4.3 prd — PRD 관리
154
+
155
+ ```bash
156
+ # 조회
157
+ ch prd get # PRD 조회
158
+
159
+ # 생성/수정
160
+ ch prd set --title <TITLE> --content <CONTENT> # PRD 생성/수정
161
+ ch prd set --title <TITLE> --content "$(cat prd.md)" # 파일에서 읽어서 설정
162
+ ch prd set --title <TITLE> --content <CONTENT> --new-version # 새 버전으로 기록
163
+
164
+ # 버전 이력
165
+ ch prd versions # PRD 버전 이력 조회
166
+ ```
167
+
168
+ **권한**: admin, developer만 생성/수정 가능. 전체 역할 조회 가능.
169
+
170
+ ---
171
+
172
+ ### 4.4 specs — 기능명세 관리
173
+
174
+ ```bash
175
+ # 메타/스키마 조회
176
+ ch specs meta # 드롭다운 옵션 조회 (devices, domains, types, permissions)
177
+
178
+ # 조회
179
+ ch specs list [--device <DEV>] [--domain <DOM>] [--type <TYPE>] [--status <STATUS>] [--group-by <FIELD>] [--search <KEYWORD>] [--sort <FIELD>] [--desc] [--page N] [--per-page N]
180
+ ch specs get <specId>
181
+ ch specs versions <specId> # 버전 이력
182
+ ch specs related <specId> --type sprints|qna|sqa # 관련 데이터
183
+ ch specs export [--format json|csv] # 전체 내보내기
184
+
185
+ # 생성/수정/삭제
186
+ ch specs create --name <NAME> --device <DEV> --domain <DOM> --type <TYPE> [--permission <PERM>] [--content <CONTENT>] [--dto <DTO>] [--status <STATUS>] [--note <NOTE>]
187
+ ch specs update <specId> [--name] [--device] [--domain] [--type] [--permission] [--content] [--dto] [--status] [--note] [--new-version]
188
+ ch specs set-status <specId> <STATUS>
189
+ ch specs delete <specId>
190
+ ```
191
+
192
+ **상태 전이 규칙**: 정의됨 → 개발중 → 개발완료 → 검수완료 (역방향 불가)
193
+
194
+ ---
195
+
196
+ ### 4.5 sprints — 스프린트 관리
197
+
198
+ ```bash
199
+ # 조회
200
+ ch sprints list [--status scheduled|inProgress|completed] [--sort <FIELD>] [--desc] [--page N]
201
+ ch sprints get <sprintId>
202
+ ch sprints timeline [--weeks N] # 타임라인 (기본 8주)
203
+ ch sprints progress <sprintId> # 진행률
204
+
205
+ # 생성/수정/삭제
206
+ ch sprints create --name <NAME> --start YYYY-MM-DD --end YYYY-MM-DD [--content <CONTENT>] [--status <STATUS>] [--specs id1,id2,...]
207
+ ch sprints update <sprintId> [--name] [--content] [--status]
208
+ ch sprints set-status <sprintId> <STATUS>
209
+ ch sprints set-dates <sprintId> --start YYYY-MM-DD --end YYYY-MM-DD
210
+
211
+ # 기능명세 연결
212
+ ch sprints add-specs <sprintId> <specId1,specId2,...>
213
+ ch sprints remove-specs <sprintId> <specId1,specId2,...>
214
+
215
+ ch sprints delete <sprintId>
216
+ ```
217
+
218
+ ---
219
+
220
+ ### 4.6 qna — QnA 관리
221
+
222
+ ```bash
223
+ # 조회
224
+ ch qna list [--status awaitingReply|replied|reflected] [--category modification|question|etc] [--search <KEYWORD>] [--sort <FIELD>] [--desc] [--page N]
225
+ ch qna get <qnaId>
226
+ ch qna pending-count # 답변대기 건수
227
+ ch qna navigate <qnaId> --direction prev|next # 이전/다음
228
+
229
+ # 생성/수정/삭제
230
+ ch qna create --title <TITLE> --category <CAT> --content <CONTENT> [--spec <SPEC_ID>]
231
+ ch qna answer <qnaId> --content <ANSWER> # 답변 등록
232
+ ch qna update-answer <qnaId> --content <NEW_ANSWER> # 답변 수정
233
+ ch qna reflect <qnaId> --note <REFLECTION_NOTE> # 반영 완료
234
+ ch qna delete <qnaId>
235
+ ```
236
+
237
+ ---
238
+
239
+ ### 4.7 sqa — SQA 관리 (시트 + 수행 2계층 구조)
240
+
241
+ SQA는 **시트(Sheet)**와 **수행(Run)** 2계층으로 구성된다:
242
+ - **시트**: 테스트 항목의 템플릿. 여러 번 재사용 가능.
243
+ - **수행(Run)**: 시트를 기반으로 특정 날짜에 실행한 테스트 인스턴스.
244
+
245
+ ```bash
246
+ # === 시트(Sheet) 관리 ===
247
+ ch sqa list [--sort <FIELD>] [--desc] [--page N] # 시트 목록
248
+ ch sqa get <sheetId> # 시트 상세 (항목 포함)
249
+ ch sqa create --name <NAME> # 시트 생성
250
+ ch sqa update <sheetId> [--name <NAME>] # 시트 수정
251
+ ch sqa delete <sheetId> # 시트 삭제
252
+
253
+ # 시트에 테스트 항목 추가
254
+ ch sqa add-item <sheetId> --test <TEST_ITEM> [--spec <SPEC_ID>]
255
+
256
+ # === 수행(Run) 관리 ===
257
+ ch sqa start-run <sheetId> --date YYYY-MM-DD # 시트 기반으로 수행 시작
258
+ ch sqa runs [--sort <FIELD>] [--desc] [--page N] # 수행 목록
259
+ ch sqa run <runId> # 수행 상세
260
+ ch sqa delete-run <runId> # 수행 삭제
261
+
262
+ # 수행에서 항목 체크
263
+ ch sqa check <runId> <itemId> --result yes|no [--note <NOTE>]
264
+ ch sqa check-bulk <runId> --file results.json # 일괄 체크
265
+
266
+ # 수행 완료/집계/내보내기
267
+ ch sqa complete <runId> # 수행 완료 처리
268
+ ch sqa summary <runId> # Pass/Fail 집계
269
+ ch sqa export <runId> --output <FILE_PATH> # 엑셀 Export
270
+
271
+ # === Import ===
272
+ ch sqa import --file <EXCEL_PATH> [--name <NAME>] [--date YYYY-MM-DD]
273
+ ch sqa import-preview --file <EXCEL_PATH> # 미리보기
274
+ ```
275
+
276
+ **일괄 체크 JSON 형식**:
277
+ ```json
278
+ {
279
+ "results": [
280
+ { "itemId": "item1", "result": "yes", "note": "정상" },
281
+ { "itemId": "item2", "result": "no", "note": "버그 발견" }
282
+ ]
283
+ }
284
+ ```
285
+
286
+ ---
287
+
288
+ ### 4.8 archives — 아카이브 관리
289
+
290
+ ```bash
291
+ # 조회
292
+ ch archives list [--category <CAT>] [--date-from YYYY-MM-DD] [--date-to YYYY-MM-DD] [--search <KEYWORD>] [--sort <FIELD>] [--desc] [--page N]
293
+ ch archives get <archiveId>
294
+ ch archives navigate <archiveId> --direction prev|next
295
+
296
+ # 생성/수정/삭제
297
+ ch archives create --title <TITLE> --category <CAT> --date YYYY-MM-DD [--files path1,path2] [--memo <MEMO>]
298
+ ch archives update <archiveId> [--title] [--category] [--date] [--memo]
299
+ ch archives delete <archiveId>
300
+
301
+ # 파일 관리
302
+ ch archives add-files <archiveId> --files path1,path2
303
+ ch archives remove-file <archiveId> <fileName>
304
+ ch archives download <archiveId> --output <DIR> [--file <FILENAME>]
305
+
306
+ # 카테고리 관리
307
+ ch archives categories list
308
+ ch archives categories add <NAME>
309
+ ch archives categories remove <NAME>
310
+ ```
311
+
312
+ ---
313
+
314
+ ### 4.9 members — 멤버 관리
315
+
316
+ ```bash
317
+ ch members list # 멤버 목록
318
+ ch members invite --email <EMAIL> --role developer|client
319
+ ch members set-role <userId> --role admin|developer|client
320
+ ch members remove <userId>
321
+ ```
322
+
323
+ ---
324
+
325
+ ### 4.10 dev-status — 개발현황 문서 관리
326
+
327
+ 스프린트/기능명세와 연계되는 개발현황 문서를 관리한다.
328
+
329
+ ```bash
330
+ # 조회
331
+ ch dev-status list [--sprint <SPRINT_ID>] [--spec <SPEC_ID>] [--search <KEYWORD>] [--sort <FIELD>] [--desc] [--page N] [--per-page N]
332
+ ch dev-status get <docId>
333
+ ch dev-status versions <docId> # 버전 이력
334
+
335
+ # 생성/수정/삭제
336
+ ch dev-status create --title <TITLE> [--content <CONTENT>] [--sprints id1,id2] [--specs id1,id2]
337
+ ch dev-status update <docId> [--title] [--content] [--sprints id1,id2] [--specs id1,id2] [--change-note <NOTE>] [--new-version]
338
+ ch dev-status delete <docId>
339
+ ```
340
+
341
+ ---
342
+
343
+ ### 4.11 db-schema — DB 스키마 관리
344
+
345
+ ```bash
346
+ ch db-schema get # DB 스키마 조회
347
+ ch db-schema set --title <TITLE> --content <CONTENT> [--db-type firestore|supabase|mysql|generic] [--new-version]
348
+ ch db-schema versions # 버전 이력
349
+ ```
350
+
351
+ ---
352
+
353
+ ### 4.12 notifications — 알림 설정
354
+
355
+ ```bash
356
+ ch notifications get # 현재 설정 조회
357
+ ch notifications set-webhook [--kakao <URL>] [--slack <URL>]
358
+ ch notifications remove-webhook [--kakao] [--slack]
359
+ ch notifications test [--kakao] [--slack] # 테스트 발송
360
+ ch notifications toggle <eventName> [--on|--off] # 이벤트 알림 토글
361
+ ch notifications logs [--page N] # 발송 로그
362
+ ```
363
+
364
+ ---
365
+
366
+ ### 4.13 dashboard — 대시보드
367
+
368
+ ```bash
369
+ ch dashboard # 전체 요약
370
+ ch dashboard progress # 전체 진행률
371
+ ch dashboard sprint # 현재 Sprint 요약
372
+ ch dashboard qna-pending # 답변대기 QnA
373
+ ch dashboard sqa-latest # 최근 SQA 결과
374
+ ch dashboard recent-changes [--limit N] # 최근 변경 (기본 10건)
375
+ ch dashboard members-summary # 멤버 요약
376
+ ```
377
+
378
+ ---
379
+
380
+ ## 5. AI 에이전트 사용 패턴
381
+
382
+ ### 기본 원칙
383
+ 1. 항상 `--json` 옵션으로 JSON 출력을 사용한다
384
+ 2. 쓰기 작업 전 `--dry-run`으로 시뮬레이션하여 확인할 수 있다
385
+ 3. 에러 발생 시 stderr에 한국어 메시지가 출력된다
386
+ 4. **[필수] 기능명세 생성/수정 전 반드시 `ch specs meta --json`으로 드롭다운 옵션을 먼저 조회하고, schema에 정의된 값만 사용한다**
387
+ - devices, domain, featureTypes, permissions 필드는 프로젝트에 정의된 옵션 값을 **그대로** 사용해야 한다
388
+ - 임의의 영문 번역(예: "웹" → "web")이나 축약어를 사용하면 안 된다
389
+ - schema에 없는 값을 사용하면 API가 `400 BadRequest`로 거부한다
390
+
391
+ ### 에이전트 세션 초기화 예시
392
+ ```bash
393
+ # 0. 프로젝트 디렉토리에서 로컬 설정 (최초 1회, 강력 권장)
394
+ ch init --project-id "proj_xxxxx"
395
+
396
+ # 1. 로그인 (최초 1회)
397
+ ch auth login --key "sk-xxxxx" --project-id "proj_xxxxx"
398
+
399
+ # 1-1. 현재 설정 확인 (어떤 프로젝트에 연결되어 있는지)
400
+ ch status
401
+
402
+ # 2. 대시보드로 프로젝트 상태 파악
403
+ ch dashboard --json
404
+
405
+ # 3. 기능명세 메타 조회 (드롭다운 옵션 확인 — 생성/수정 전 필수!)
406
+ ch specs meta --json
407
+ # → schema.devices, schema.domains, schema.featureTypes, schema.permissions 확인
408
+
409
+ # 4. 기능명세 전체 조회
410
+ ch specs list --json --per-page 100
411
+ ```
412
+
413
+ ### 일반적인 워크플로우
414
+
415
+ #### 기능명세 생성 및 스프린트 연결
416
+ ```bash
417
+ # [필수] 먼저 메타 조회 → 사용 가능한 옵션 확인
418
+ ch specs meta --json
419
+ # 예시 응답: schema.devices=["웹","모바일","키오스크"], schema.domains=["사용자","관리자"], ...
420
+
421
+ # 기능명세 생성 — schema에서 확인한 값을 그대로 사용
422
+ ch specs create --name "로그인 기능" --device "웹" --domain "사용자" --type "인증" --json
423
+
424
+ # 생성된 specId 확인 후 스프린트에 연결
425
+ ch sprints add-specs <sprintId> <specId>
426
+ ```
427
+
428
+ #### QnA 답변 처리
429
+ ```bash
430
+ # 답변대기 QnA 확인
431
+ ch qna list --status awaitingReply --json
432
+
433
+ # 답변 등록
434
+ ch qna answer <qnaId> --content "답변 내용"
435
+
436
+ # 반영 완료 처리
437
+ ch qna reflect <qnaId> --note "v1.2에 반영됨"
438
+ ```
439
+
440
+ #### SQA 테스트 수행 (시트 → 수행 → 체크)
441
+ ```bash
442
+ # 1. 시트 조회
443
+ ch sqa list --json
444
+ ch sqa get <sheetId> --json
445
+
446
+ # 2. 시트 기반으로 수행(Run) 시작
447
+ ch sqa start-run <sheetId> --date 2026-05-14
448
+
449
+ # 3. 수행에서 항목 체크 (runId 사용!)
450
+ ch sqa check <runId> <itemId> --result yes
451
+ ch sqa check <runId> <itemId> --result no --note "재현됨"
452
+
453
+ # 또는 일괄 체크
454
+ ch sqa check-bulk <runId> --file results.json
455
+
456
+ # 4. 수행 완료
457
+ ch sqa complete <runId>
458
+
459
+ # 5. 결과 확인
460
+ ch sqa summary <runId>
461
+ ```
462
+
463
+ ## 6. 인프라 정보
464
+
465
+ | 항목 | 값 |
466
+ |------|------|
467
+ | npm 패키지 | `@decencia/ch-cli` |
468
+ | API 서버 | Cloud Run (asia-northeast3) |
469
+ | API URL | `https://ch-api-618529407342.asia-northeast3.run.app` |
470
+ | Swagger 문서 | `https://ch-api-618529407342.asia-northeast3.run.app/api/docs` |
471
+ | GCP 프로젝트 | `decenciasofthomepage` |
472
+ | DB | Firebase Firestore (ch_ 접두사 컬렉션) |
473
+ | 파일 저장소 | Firebase Storage |
474
+ | 인증 방식 | Bearer Token (API Key) + X-Project-Id 헤더 |
475
+ | 역할(RBAC) | admin, developer, client |
476
+ | CLI 소스 | `C:\myprojects\decenciahomepage\ch-cli` |
477
+ | API 소스 | `C:\myprojects\decenciahomepage\ch-api` |
478
+ | 소통채널 웹앱 | `C:\myprojects\decencia-channel` (channel.decenciasoft.com) |
479
+
480
+ ## 7. 트러블슈팅
481
+
482
+ | 증상 | 원인 | 해결 |
483
+ |------|------|------|
484
+ | `API Key가 설정되지 않았습니다` | 로그인 안됨 | `ch auth login --key ... --project-id ...` |
485
+ | `인증 실패` (401) | API Key 무효/만료 | 새 키 발급: `ch auth keys create --name "new"` |
486
+ | `권한이 없습니다` (403) | 역할 부족 | admin에게 역할 변경 요청 |
487
+ | `리소스를 찾을 수 없습니다` (404) | 잘못된 ID | `--json`으로 목록 조회 후 ID 재확인 |
488
+ | `서버에 연결할 수 없습니다` | 네트워크/URL 문제 | `--verbose`로 요청 URL 확인 |
489
+ | 다른 프로젝트에 데이터 들어감 | `.ch-project` 미설정 | `ch init --project-id <PID>`로 로컬 설정 |
490
+ | `ch status`에서 projectId 불일치 | 로컬/글로벌 설정 충돌 | `ch status`로 확인 후 `.ch-project` 재설정 |