claude-novice 0.2.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/.claude-plugin/marketplace.json +25 -0
- package/.claude-plugin/plugin.json +22 -0
- package/ARCHITECTURE.md +59 -0
- package/LICENSE +21 -0
- package/README.md +372 -0
- package/config/bootstrap-manifests/github-cli.json +80 -0
- package/config/bootstrap-manifests/supabase.json +71 -0
- package/config/bootstrap-manifests/vercel.json +69 -0
- package/config/levels.json +33 -0
- package/config/safety-rules.json +263 -0
- package/config/service-capabilities.json +51 -0
- package/config/terms.json +198 -0
- package/hooks/hooks.json +107 -0
- package/package.json +45 -0
- package/scripts/bootstrap-engine.js +240 -0
- package/scripts/lib/capability-router.js +170 -0
- package/scripts/lib/capsule.js +178 -0
- package/scripts/lib/fingerprint.js +17 -0
- package/scripts/lib/grammar.js +287 -0
- package/scripts/lib/hookio.js +49 -0
- package/scripts/lib/manifest.js +154 -0
- package/scripts/lib/safety.js +370 -0
- package/scripts/lib/secrets.js +104 -0
- package/scripts/lib/state.js +256 -0
- package/scripts/post-tool-batch.js +108 -0
- package/scripts/post-tool-use-failure.js +48 -0
- package/scripts/post-tool-use.js +114 -0
- package/scripts/pre-tool-use.js +58 -0
- package/scripts/session-end.js +21 -0
- package/scripts/session-start.js +48 -0
- package/scripts/stop.js +69 -0
- package/scripts/user-prompt-expansion.js +66 -0
- package/scripts/user-prompt-submit.js +158 -0
- package/scripts/verify-docs.mjs +93 -0
- package/skills/mode/SKILL.md +48 -0
- package/skills/novice/SKILL.md +41 -0
- package/skills/setup-service/SKILL.md +88 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "novice",
|
|
3
|
+
"description": "비개발자 입문자용 Claude Code 학습 동반자 — 실제 개발 용어 보존, 안전 게이트, 외부 서비스 CLI 부트스트랩",
|
|
4
|
+
"owner": {
|
|
5
|
+
"name": "hjsh200219",
|
|
6
|
+
"url": "https://github.com/hjsh200219"
|
|
7
|
+
},
|
|
8
|
+
"plugins": [
|
|
9
|
+
{
|
|
10
|
+
"name": "novice",
|
|
11
|
+
"description": "비개발자 입문자를 위한 3단계 학습 동반자. 용어 설명 병기(fade), 파괴·시크릿·비용 안전 게이트, 2-tier CLI 부트스트랩(vercel/gh/supabase) + MCP·Chrome capability 라우터.",
|
|
12
|
+
"source": ".",
|
|
13
|
+
"category": "education",
|
|
14
|
+
"tags": [
|
|
15
|
+
"beginner",
|
|
16
|
+
"onboarding",
|
|
17
|
+
"korean",
|
|
18
|
+
"education",
|
|
19
|
+
"safety",
|
|
20
|
+
"vibe-coding",
|
|
21
|
+
"hooks"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "novice",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "비개발자 입문자를 위한 3단계 학습 동반자 — 실제 개발 용어 보존, 안전 게이트, 외부 서비스 CLI 부트스트랩",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "SHC"
|
|
7
|
+
},
|
|
8
|
+
"userConfig": {
|
|
9
|
+
"default_level": {
|
|
10
|
+
"type": "number",
|
|
11
|
+
"title": "기본 novice 레벨",
|
|
12
|
+
"description": "novice 기본 레벨 (1=최고 초보, 2=중간, 3=아키텍처 중심)",
|
|
13
|
+
"default": 1
|
|
14
|
+
},
|
|
15
|
+
"novice_enabled": {
|
|
16
|
+
"type": "boolean",
|
|
17
|
+
"title": "novice 활성화",
|
|
18
|
+
"description": "novice 학습 동반자 활성화 여부 (안전 게이트는 이 값과 무관하게 플러그인 활성 시 항상 동작)",
|
|
19
|
+
"default": true
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# ARCHITECTURE
|
|
2
|
+
|
|
3
|
+
novice는 Claude Code hook + skill + config 데이터로 구성된 학습 동반자 플러그인이다.
|
|
4
|
+
런타임 코드는 hook 핸들러(stdin JSON → stdout JSON)이고, 동작 규칙은 config JSON에 데이터로 있다.
|
|
5
|
+
|
|
6
|
+
## 레이어와 종속성 방향
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
config/*.json (데이터 SSOT)
|
|
10
|
+
▲ (읽기 전용 소비)
|
|
11
|
+
scripts/lib/*.js (순수 로직)
|
|
12
|
+
▲ (import)
|
|
13
|
+
scripts/*.js (hook 핸들러) skills/*/SKILL.md (모델용 절차)
|
|
14
|
+
▲
|
|
15
|
+
tests/ (검증)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
| 레이어 | 위치 | 역할 | 허용 import |
|
|
19
|
+
|--------|------|------|-------------|
|
|
20
|
+
| L1 config | `config/*.json`, `config/bootstrap-manifests/` | 동작 규칙 데이터 SSOT | (코드 아님) |
|
|
21
|
+
| L2 lib | `scripts/lib/` | 순수 로직 | node 내장 + 같은 lib. **hook 핸들러 import 금지** |
|
|
22
|
+
| L3 hook | `scripts/*.js` | hook 진입점 | `scripts/lib/`, node 내장 |
|
|
23
|
+
| L4 skills | `skills/` | 모델용 절차 문서 | (문서) |
|
|
24
|
+
| L5 tests | `tests/` | 검증 | 전부 |
|
|
25
|
+
|
|
26
|
+
**종속성 규칙**: L2 lib는 L3 hook을 import하지 않는다(역방향 금지). hook은 lib를 통해서만 상태·검증에 접근한다. config는 코드가 읽는 데이터이며 코드를 참조하지 않는다. 상세 규칙: [docs/design-docs/layer-rules.md](./docs/design-docs/layer-rules.md).
|
|
27
|
+
|
|
28
|
+
## lib 모듈 맵 (L2)
|
|
29
|
+
| 모듈 | 책임 |
|
|
30
|
+
|---|---|
|
|
31
|
+
| `state.js` | 영속·세션 상태 단일 진입. atomic write, 0600, symlink 거부, project override / session state, mute(프로젝트 스코프) |
|
|
32
|
+
| `hookio.js` | stdin/stdout 계약, emit 헬퍼, fail-open/fail-closed |
|
|
33
|
+
| `secrets.js` | 시크릿 스캔·redaction (원문 미저장), 안전 규칙 로드 |
|
|
34
|
+
| `grammar.js` | Bash·PowerShell 유한 grammar 토크나이저 + git subgrammar |
|
|
35
|
+
| `capsule.js` | mode capsule·glossary·tombstone·fade 계산 |
|
|
36
|
+
| `manifest.js` | bootstrap manifest 검증·로드 (Tier 1/2) |
|
|
37
|
+
| `capability-router.js` | CLI→MCP→Chrome→guided manual 경로 결정·검증·다운그레이드 |
|
|
38
|
+
| `fingerprint.js` | tool 호출 fingerprint (post-tool event 중복 제거) |
|
|
39
|
+
| `safety.js` | PreToolUse 안전 분석 (rm·git·deploy·MCP 판정, grammar+secret 소비) |
|
|
40
|
+
|
|
41
|
+
## hook 핸들러 맵 (L3)
|
|
42
|
+
| hook | 파일 | 책임 |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| SessionStart | `session-start.js` | 상태 복구·capsule/glossary 주입 |
|
|
45
|
+
| UserPromptSubmit | `user-prompt-submit.js` | 자연어 명령(mode/reset/mute), capsule 중복 방지 |
|
|
46
|
+
| UserPromptExpansion | `user-prompt-expansion.js` | `/novice:mode` 처리 |
|
|
47
|
+
| PreToolUse | `pre-tool-use.js` | 안전 게이트 (deny-only; 파괴 비가역·시크릿만 차단, 오류 시 fail-closed) |
|
|
48
|
+
| PostToolUse | `post-tool-use.js` | 출력 redaction + event 기록 |
|
|
49
|
+
| PostToolUseFailure | `post-tool-use-failure.js` | 실패 event 기록 |
|
|
50
|
+
| PostToolBatch | `post-tool-batch.js` | batch 집계·개입 (single-writer) |
|
|
51
|
+
| Stop | `stop.js` | 용어 카운터 |
|
|
52
|
+
| SessionEnd | `session-end.js` | 세션 정리·TTL |
|
|
53
|
+
| (라이브러리) | `bootstrap-engine.js` | setup-service 상태 머신 + capability 라우터 |
|
|
54
|
+
|
|
55
|
+
## 교차 관심사
|
|
56
|
+
- **상태**: 전부 `state.js` 경유, `CLAUDE_PLUGIN_DATA` 아래에만.
|
|
57
|
+
- **안전**: pre-tool-use = fail-closed; 학습 hook = fail-open.
|
|
58
|
+
- **시크릿**: `secrets.js`가 스캔·redaction, 원문은 로그·state·metric에 미기록.
|
|
59
|
+
- **credential**: 플러그인이 값을 다루지 않음. bootstrap audit엔 메타데이터만.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SHC (hjsh200219)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# novice — 비개발자 입문자용 Claude Code 플러그인
|
|
2
|
+
|
|
3
|
+
**한국어** · [English](#english)
|
|
4
|
+
|
|
5
|
+
비개발자 입문자가 Claude Code로 바이브 코딩을 시작할 때 실제 개발 용어와 학습 기회를 보존하고,
|
|
6
|
+
외부 서비스 CLI 설정을 안전한 범위에서 돕고, CLI 공포와 파괴·비용·시크릿 노출 위험을 줄이는
|
|
7
|
+
3단계 학습 동반자 플러그인입니다.
|
|
8
|
+
|
|
9
|
+
- 스펙: `docs/PRD.md` (revision 12)
|
|
10
|
+
- 최소 지원 런타임: Claude Code `2.1.215`
|
|
11
|
+
- 상태: MVP 구현 완료 — 테스트 147개 통과 (외부 dependency 0).
|
|
12
|
+
실제 2.1.215 runtime에서 hook payload 캡처 + `--plugin-dir` live E2E 검증 완료.
|
|
13
|
+
남은 것은 사람 참가자가 필요한 product beta 검증(concierge/moderated).
|
|
14
|
+
|
|
15
|
+
## 설치
|
|
16
|
+
|
|
17
|
+
Claude Code 안에서 marketplace를 등록한 뒤 설치합니다:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
/plugin marketplace add hjsh200219/novice
|
|
21
|
+
/plugin install novice@novice
|
|
22
|
+
/reload-plugins
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- 설치 확인: `/plugin` 목록에서 novice가 enabled인지 확인하고, `/novice`를 실행해
|
|
26
|
+
상태 대시보드가 나오면 정상입니다.
|
|
27
|
+
- **업데이트**: 설치본은 캐시 복사본이라 자동 갱신되지 않습니다. `/plugin` 메뉴에서
|
|
28
|
+
novice marketplace를 update한 뒤 플러그인을 재설치하세요.
|
|
29
|
+
- 로컬 개발·수정 테스트: 리포를 clone한 뒤 `claude --plugin-dir <리포 경로>`로
|
|
30
|
+
설치 없이 로드할 수 있습니다.
|
|
31
|
+
- npm 채널: [`claude-novice`](https://www.npmjs.com/package/claude-novice) 패키지로도
|
|
32
|
+
배포됩니다. `npm install -g claude-novice` 후 `claude --plugin-dir "$(npm root -g)/claude-novice"`로
|
|
33
|
+
로드하거나, 자체 marketplace의 plugin `source`에 `{"source":"npm","package":"claude-novice"}`를
|
|
34
|
+
쓸 수 있습니다.
|
|
35
|
+
- 제거: `/plugin uninstall novice` — 제거하면 안전 게이트도 함께 사라집니다
|
|
36
|
+
(아래 위협 모델 참조).
|
|
37
|
+
|
|
38
|
+
## 사용법
|
|
39
|
+
|
|
40
|
+
| 명령 | 동작 |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `/novice` | front door — 현재 상태(레벨·학습층·안전 게이트·mute) 대시보드 + 하위 명령 안내 |
|
|
43
|
+
| `/novice:mode` | 현재 level, 적용 범위, 안전 게이트 유지 여부 표시 |
|
|
44
|
+
| `/novice:mode 1` | Level 1 (기본값) — 모든 용어에 설명 병기, 실행 전·후 해설 |
|
|
45
|
+
| `/novice:mode 2` | Level 2 — 3회까지 설명, 핵심 결정만 해설 |
|
|
46
|
+
| `/novice:mode 3` | Level 3 — 요청 시만 설명, 아키텍처·유저플로우 중심 |
|
|
47
|
+
| `/novice:mode off` | novice 톤·설명·시각화 완전 제거 (안전 게이트는 유지) |
|
|
48
|
+
|
|
49
|
+
### 자연어 명령
|
|
50
|
+
|
|
51
|
+
프롬프트 **전체가 정확히** 아래 형태와 일치할 때만 동작합니다(앞뒤 공백·마침표만 허용).
|
|
52
|
+
"더 쉽게 설명해 줘" 같은 일반 문장은 현재 답변에만 영향을 주고 설정을 바꾸지 않습니다.
|
|
53
|
+
|
|
54
|
+
| 명령 | 동작 | 예시 |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `novice 1` / `novice 2` / `novice 3` / `novice off` | 모드 전환 (`/novice:mode N`과 동일) | `novice 2` |
|
|
57
|
+
| `novice reset all` | 모든 용어의 설명 카운터 초기화 (다시 처음부터 N회 설명) | `novice reset all` |
|
|
58
|
+
| `novice reset <용어>` | 특정 용어만 카운터 초기화 | `novice reset commit` |
|
|
59
|
+
| `novice mute <용어>` | 특정 용어를 **영구 제외** — 노출 횟수와 무관하게 설명 중단 | `novice mute commit` |
|
|
60
|
+
| `novice unmute <용어>` | mute 해제 — 다시 fade 규칙에 따라 설명 | `novice unmute commit` |
|
|
61
|
+
|
|
62
|
+
- **reset vs mute**: `reset`은 카운터를 0으로 되돌려 **다시** N회 설명하게 하고, `mute`는 지금 즉시 설명을 끊고 계속 끊어 둡니다.
|
|
63
|
+
- **mute는 프로젝트 단위**로 저장되어 세션이 바뀌어도 유지됩니다. reset·용어 카운터는 세션 스코프입니다.
|
|
64
|
+
- 용어(예: `commit`)는 한글 별칭(`커밋`)으로도 지정할 수 있고, 사전에 없는 용어는 무시됩니다.
|
|
65
|
+
|
|
66
|
+
용어는 순화하지 않습니다. `commit(현재 변경을 하나의 저장 지점으로 기록하는 것)`처럼
|
|
67
|
+
실제 용어 뒤에 설명을 병기하고, 세션에서 충분히 노출된 용어(Level 1 기준 3회)는 설명을 걷어냅니다.
|
|
68
|
+
|
|
69
|
+
## 외부 서비스 CLI 부트스트랩 (2-tier)
|
|
70
|
+
|
|
71
|
+
자동화 경계는 두 tier 모두 **탐지 → 설치 → 로그인 → 인증 상태 확인까지**입니다.
|
|
72
|
+
|
|
73
|
+
- **Tier 1** (검토된 manifest: Vercel, GitHub CLI, Supabase): 고정 package coordinate로
|
|
74
|
+
표준 승인 흐름 실행. 설치와 로그인은 각각 1회씩 승인받습니다.
|
|
75
|
+
- **Tier 2** (그 외 CLI): 공식 문서 URL·package coordinate·실행 argv를 화면에 그대로
|
|
76
|
+
제시하고, 사용자가 근거를 확인·승인한 경우에만 같은 engine으로 진행합니다.
|
|
77
|
+
공식 근거를 확인할 수 없으면 guided manual로 낮춥니다.
|
|
78
|
+
|
|
79
|
+
리소스 생성·env/secret 값 입력·배포는 **사용자가 직접** 하거나 guided manual로 안내합니다.
|
|
80
|
+
플러그인은 credential 값을 요청·보관·전달·자동입력하지 않습니다.
|
|
81
|
+
secure 저장소를 지원하는 CLI(gh, supabase)가 plaintext fallback으로 떨어지는 환경에서는
|
|
82
|
+
자동 로그인을 중단합니다. 파일 저장이 공식 기본 동작인 CLI(vercel)는 저장 위치와
|
|
83
|
+
logout 경로를 로그인 승인 전에 고지합니다 — provider별 정책은 manifest의
|
|
84
|
+
`credential_store`에 명시되어 있습니다.
|
|
85
|
+
|
|
86
|
+
CLI 설치를 거부하거나 preflight가 실패하면 capability 라우터가
|
|
87
|
+
**CLI → 공식/동의된 MCP → visible Chrome → guided manual** 순으로 경로를 낮춥니다.
|
|
88
|
+
MCP는 두 경우에 쓰입니다 — (1) `mcp_allowlist`에 server·transport·publisher·tool·provenance가
|
|
89
|
+
모두 일치하는 사전 검토 엔트리, 또는 (2) **사용자가 Claude에 이미 등록한 서버 + 이번 작업에
|
|
90
|
+
명시적으로 동의**한 경우(동의한 tool 범위). 기본 allowlist는 비어 있어 등록·동의 없이는 자동
|
|
91
|
+
실행되지 않고, MCP 서버를 자동 설치하지 않습니다. CLI도 Tier 1 검토 manifest 외에 **사용자가
|
|
92
|
+
근거 확인 후 동의한 Tier 2 CLI**를 사용합니다. Chrome은 공식 Claude in Chrome 연결 시 visible
|
|
93
|
+
mode로만 씁니다. 라우터는 경로 결정·검증·다운그레이드까지 하고, 실제 MCP tool 호출은 모델이(안전
|
|
94
|
+
게이트가 계속 가드), Chrome 조작·최종 submit은 사용자가 합니다.
|
|
95
|
+
|
|
96
|
+
## 안전 게이트 위협 모델
|
|
97
|
+
|
|
98
|
+
안전 게이트는 **최소 deny-only 코어**입니다. 긍정적으로 식별한 파괴 비가역 작업과 노출된
|
|
99
|
+
시크릿 값만 차단하고, 확인 질문(ask) 티어는 두지 않습니다. 파싱할 수 없거나 애매한 명령은
|
|
100
|
+
판정하지 않고 **Claude Code 네이티브 권한 프롬프트**에 위임합니다.
|
|
101
|
+
|
|
102
|
+
| 위협 | 동작 | 보증하지 않는 범위 |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| 로컬 파괴 명령 (`rm -rf ~`·`/`·프로젝트 루트, `dd`/`mkfs`/`shred`, PowerShell `Format-Volume`/`Clear-Disk`) | bare 명령을 파싱해 catastrophic이면 deny | 난독화, 파이프·체인·치환 낀 명령, 일반 폴더 삭제, 플러그인 밖 실행 |
|
|
105
|
+
| Git history 파괴 (`push --force`) | protected branch 대상이면 deny | 비보호 branch force-push, `reset --hard`·`clean`(위임), 다른 Git client 작업 |
|
|
106
|
+
| DB/원격 리소스 삭제 (CLI·MCP) | production/unknown 대상 파괴 작업 deny | staging/dev 대상(위임), 외부 콘솔 직접 작업 |
|
|
107
|
+
| 시크릿 commit/deploy/명령줄 노출 | commit candidate tree·deploy 인자·명령줄 스캔 후 시크릿 값 발견 시 deny | 미지원 포맷, 암호화·난독화된 시크릿, 스캔 불가(대용량·exotic 옵션) |
|
|
108
|
+
| 비용·반복 루프 | batch당 최대 1회 개입 안내 | 정확한 과금 계산, hard billing cap |
|
|
109
|
+
|
|
110
|
+
### 명시적 비보증 (No silent security claims)
|
|
111
|
+
|
|
112
|
+
- **범용 shell parser가 아닙니다.** bare 단일 command + argv만 유한 grammar로 파싱합니다.
|
|
113
|
+
pipe·리다이렉트·명령 치환·체인(`&&`·`;`) 등 미지원 문법은 **판정하지 않고 Claude Code
|
|
114
|
+
네이티브 권한에 위임**합니다. 이 위임 때문에 파이프 낀 파괴 명령(`rm -rf / ; …`)은 novice가
|
|
115
|
+
잡지 않을 수 있습니다 — 대신 CC 기본 권한 프롬프트가 처리합니다. (단, 명령줄에 노출된
|
|
116
|
+
시크릿 값은 문법과 무관하게 스캔·deny합니다.)
|
|
117
|
+
- **확인 질문(ask) 티어가 없습니다.** 애매하면 묻지 않고 위임합니다 — benign 명령에 대한
|
|
118
|
+
false-prompt를 없애기 위한 설계입니다. 되돌리기 어려운 파괴/시크릿만 차단합니다.
|
|
119
|
+
- **완전한 DLP·시크릿 관리자·악성 MCP 방어가 아닙니다.** 알려진 패턴 fixture 기준으로만 탐지합니다.
|
|
120
|
+
스캔할 수 없는 대상(대용량 파일·exotic git 옵션·unborn HEAD)은 차단하지 않고 위임합니다.
|
|
121
|
+
- **timeout fail-open 한계:** Claude Code가 hook timeout·강제 종료를 non-blocking으로
|
|
122
|
+
처리하는 경우는 보증 범위 밖입니다. hook 내부 오류·잘못된 입력·입력 상한 초과만 deny(fail closed)합니다.
|
|
123
|
+
- **플러그인을 disable/uninstall하면 안전 게이트도 사라집니다.** "always-on"은 플러그인이
|
|
124
|
+
활성화된 동안만 의미합니다. novice `off`는 학습층만 끄고 안전 게이트는 유지합니다.
|
|
125
|
+
- **Git은 tracked 로컬 파일만 보호합니다.** untracked/ignored 파일, 외부 DB, 배포 리소스는
|
|
126
|
+
Git checkpoint로 복구되지 않습니다.
|
|
127
|
+
|
|
128
|
+
## 상태와 privacy
|
|
129
|
+
|
|
130
|
+
- 상태는 `${CLAUDE_PLUGIN_DATA}` 아래에만 저장합니다 (project override, 세션별 용어 카운터).
|
|
131
|
+
plugin root에는 쓰지 않습니다.
|
|
132
|
+
- 상태 파일: atomic write, `0600`, symlink 거부, size cap. 세션 상태는 `/clear` 시 삭제, 30일 TTL.
|
|
133
|
+
- secret scanner는 후보 바이트를 메모리에서만 검사하고 원문을 로그·state·metric에 남기지 않습니다.
|
|
134
|
+
- bootstrap audit에는 service ID·manifest revision·단계·exit status만 저장합니다.
|
|
135
|
+
- 원격 telemetry를 보내지 않습니다.
|
|
136
|
+
|
|
137
|
+
## Release Notes
|
|
138
|
+
|
|
139
|
+
### 0.2.0 (2026-07-21)
|
|
140
|
+
- **안전 게이트를 deny-only 최소 코어로 전환** — 확인 질문(ask) 티어 제거. benign
|
|
141
|
+
파이프·체인 명령(`find … | sort && ls`)마다 뜨던 false-prompt 소멸. 파싱 불가·모호한
|
|
142
|
+
명령은 판정 없이 Claude Code 네이티브 권한에 위임.
|
|
143
|
+
- deny 유지: `rm` 홈·루트·프로젝트 루트, `dd`/`mkfs`/`shred`·disk-format cmdlet,
|
|
144
|
+
protected branch force-push, production/unknown 파괴 MCP, commit/deploy/명령줄 시크릿 값.
|
|
145
|
+
- `/novice` front door 명령 추가 — 상태 대시보드(레벨·학습층·안전 게이트·mute) + 하위 명령 안내.
|
|
146
|
+
- commit/deploy 시크릿 스캔에 `tests/fixtures/` 경로 예외 — 플러그인이 자기 테스트
|
|
147
|
+
fixture에 자기 게이트로 걸리던 오탐 해소.
|
|
148
|
+
- config 정리: 미사용 ask 잔재(`dangerous_tokens`·`git_rules` 등) 제거, 위임 의미를
|
|
149
|
+
`delegate` 값으로 명명. PRD rev 12, 테스트 147.
|
|
150
|
+
|
|
151
|
+
### 0.1.0 (2026-07-20)
|
|
152
|
+
- 최초 릴리스 — 3단계 학습 동반자(용어 병기·fade·mute), 파괴·시크릿·비용 안전 게이트,
|
|
153
|
+
2-tier CLI 부트스트랩(vercel/gh/supabase), MCP·Chrome capability 라우터. PRD rev 11.
|
|
154
|
+
|
|
155
|
+
## 개발
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npm test # 전체 (unit + integration)
|
|
159
|
+
npm run test:unit
|
|
160
|
+
npm run test:integration
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
외부 runtime dependency 없음 (Node >= 18, node:test). 테스트 구성: unit 11개 파일
|
|
164
|
+
(config·state·mode·capsule·stop·grammar·secrets·batch·bootstrap·capability-router·output-style),
|
|
165
|
+
integration 4개 파일 (hooks-contract·safety-corpus·safety-mutation·latency-benchmark).
|
|
166
|
+
안전 gate는 mutation 하네스로도 검증합니다 — 위험 명령 35건을 106개 mutant로 변형해 detector
|
|
167
|
+
우회가 없음을 확인합니다. latency 벤치는 blocking hook의 p95 예산(UserPromptSubmit ≤300ms,
|
|
168
|
+
PreToolUse ≤250ms)을 회귀 테스트로 강제합니다(`NOVICE_BENCH_ITERS`로 반복 횟수 조정).
|
|
169
|
+
|
|
170
|
+
`tests/fixtures/contract/`의 hook payload fixture는 Claude Code **2.1.215 실측 캡처**입니다
|
|
171
|
+
(provenance 필드로 캡처/파생/문서 구분 — 상세는 해당 디렉토리 README).
|
|
172
|
+
플러그인 자체도 같은 runtime에 `--plugin-dir`로 로드해 `/novice:mode` expansion →
|
|
173
|
+
상태 갱신 → capsule 주입까지 live E2E로 확인했고, hook 실행 순서(expansion→submit)도 실측했습니다.
|
|
174
|
+
|
|
175
|
+
코드로 검증 불가라 남는 항목: 실제 CLI 설치·로그인 E2E(사용자 환경·계정 필요),
|
|
176
|
+
`/clear`·compact의 SessionStart source·MCP destructive payload 실측(headless 트리거 불가),
|
|
177
|
+
product beta 지표(사람 참가자 필요).
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
<a name="english"></a>
|
|
182
|
+
|
|
183
|
+
# novice — a beginner-friendly Claude Code plugin
|
|
184
|
+
|
|
185
|
+
[한국어](#novice--비개발자-입문자용-claude-code-플러그인) · **English**
|
|
186
|
+
|
|
187
|
+
A three-level learning companion plugin for non-developers starting out with Claude Code.
|
|
188
|
+
It preserves real development terminology and learning opportunities, helps set up external
|
|
189
|
+
service CLIs within a safe boundary, and reduces the fear of the CLI along with the risk of
|
|
190
|
+
destructive commands, runaway cost, and secret exposure.
|
|
191
|
+
|
|
192
|
+
- Spec: `docs/PRD.md` (revision 12)
|
|
193
|
+
- Minimum supported runtime: Claude Code `2.1.215`
|
|
194
|
+
- Status: MVP implemented — 147 tests passing (zero external
|
|
195
|
+
dependencies). Verified against a real 2.1.215 runtime via hook-payload capture and a
|
|
196
|
+
`--plugin-dir` live E2E. What remains is the product beta, which needs human participants.
|
|
197
|
+
|
|
198
|
+
## Installation
|
|
199
|
+
|
|
200
|
+
Register the marketplace inside Claude Code, then install:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
/plugin marketplace add hjsh200219/novice
|
|
204
|
+
/plugin install novice@novice
|
|
205
|
+
/reload-plugins
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
- Verify: check that novice is enabled in `/plugin`, then run `/novice` — a status
|
|
209
|
+
dashboard means it's working.
|
|
210
|
+
- **Updating**: the installed copy is a cached snapshot and does not auto-update. Update the
|
|
211
|
+
novice marketplace in the `/plugin` menu, then reinstall the plugin.
|
|
212
|
+
- Local development: clone the repo and load it without installing via
|
|
213
|
+
`claude --plugin-dir <repo path>`.
|
|
214
|
+
- npm channel: also published as [`claude-novice`](https://www.npmjs.com/package/claude-novice).
|
|
215
|
+
`npm install -g claude-novice` then `claude --plugin-dir "$(npm root -g)/claude-novice"`,
|
|
216
|
+
or point your own marketplace's plugin `source` at `{"source":"npm","package":"claude-novice"}`.
|
|
217
|
+
- Uninstall: `/plugin uninstall novice` — removing the plugin also removes the safety gate
|
|
218
|
+
(see the threat model below).
|
|
219
|
+
|
|
220
|
+
## Usage
|
|
221
|
+
|
|
222
|
+
| Command | Behavior |
|
|
223
|
+
|---|---|
|
|
224
|
+
| `/novice:mode` | Show current level, scope, and whether the safety gate stays on |
|
|
225
|
+
| `/novice:mode 1` | Level 1 (default) — explanation appended to every term, before/after narration |
|
|
226
|
+
| `/novice:mode 2` | Level 2 — explain up to 3 times, narrate key decisions only |
|
|
227
|
+
| `/novice:mode 3` | Level 3 — explain on request only, architecture/user-flow focused |
|
|
228
|
+
| `/novice:mode off` | Fully remove novice tone/explanations/visualization (safety gate stays on) |
|
|
229
|
+
|
|
230
|
+
### Natural-language commands
|
|
231
|
+
|
|
232
|
+
These act only when the **entire prompt matches exactly** (leading/trailing whitespace and a
|
|
233
|
+
trailing period are tolerated). A general sentence like "explain it more simply" affects only
|
|
234
|
+
the current answer and does not change any setting.
|
|
235
|
+
|
|
236
|
+
| Command | Behavior | Example |
|
|
237
|
+
|---|---|---|
|
|
238
|
+
| `novice 1` / `novice 2` / `novice 3` / `novice off` | Switch mode (same as `/novice:mode N`) | `novice 2` |
|
|
239
|
+
| `novice reset all` | Reset every term's explanation counter (explain N times again) | `novice reset all` |
|
|
240
|
+
| `novice reset <term>` | Reset one term's counter | `novice reset commit` |
|
|
241
|
+
| `novice mute <term>` | **Permanently exclude** a term — explanation stops regardless of count | `novice mute commit` |
|
|
242
|
+
| `novice unmute <term>` | Undo a mute — explanation resumes per the fade rule | `novice unmute commit` |
|
|
243
|
+
|
|
244
|
+
- **reset vs mute**: `reset` restarts the counter from zero so the term is explained N more
|
|
245
|
+
times; `mute` stops the explanation right now and keeps it off.
|
|
246
|
+
- **mute is stored per project**, so it persists across sessions. reset and the term counters
|
|
247
|
+
are session-scoped.
|
|
248
|
+
- A term (e.g. `commit`) can be named by its Korean alias (`커밋`) too; unknown terms are ignored.
|
|
249
|
+
|
|
250
|
+
Terms are never simplified away. It appends an explanation after the real term, as in
|
|
251
|
+
`commit (recording the current changes as one save point)`, and once a term has appeared
|
|
252
|
+
enough times in a session (3 times at Level 1) the explanation is dropped.
|
|
253
|
+
|
|
254
|
+
## External service CLI bootstrap (2-tier)
|
|
255
|
+
|
|
256
|
+
The automation boundary for both tiers is **detect → install → log in → verify auth**.
|
|
257
|
+
|
|
258
|
+
- **Tier 1** (reviewed manifests: Vercel, GitHub CLI, Supabase): runs the standard approval
|
|
259
|
+
flow with fixed package coordinates. Install and login are each approved once.
|
|
260
|
+
- **Tier 2** (any other CLI): the engine shows the official docs URL, package coordinate, and
|
|
261
|
+
the exact argv on screen, and proceeds through the same engine only after the user confirms
|
|
262
|
+
and approves the evidence. If no official provenance can be confirmed, it falls back to a
|
|
263
|
+
guided manual.
|
|
264
|
+
|
|
265
|
+
Creating resources, entering env/secret values, and deploying are done by **the user
|
|
266
|
+
directly** or guided manually. The plugin never requests, stores, forwards, or auto-fills
|
|
267
|
+
credential values. For a CLI that supports secure storage (gh, supabase), auto-login is
|
|
268
|
+
aborted when the environment falls back to plaintext. For a CLI whose documented default is
|
|
269
|
+
file storage (vercel), the storage location and logout path are disclosed before the login is
|
|
270
|
+
approved — the per-provider policy lives in each manifest's `credential_store`.
|
|
271
|
+
|
|
272
|
+
If CLI install is refused or preflight fails, a capability router downgrades along
|
|
273
|
+
**CLI → official/consented MCP → visible Chrome → guided manual**. MCP is used in two cases —
|
|
274
|
+
(1) a pre-reviewed `mcp_allowlist` entry matching on server, transport, publisher, tools, and
|
|
275
|
+
provenance, or (2) a server the **user has already registered in Claude plus explicit per-task
|
|
276
|
+
consent** (limited to the consented tools). The default allowlist is empty, so nothing runs
|
|
277
|
+
without registration + consent, and MCP servers are never auto-installed. CLI likewise accepts,
|
|
278
|
+
beyond the Tier 1 reviewed manifests, a **Tier 2 CLI the user explicitly consents to after
|
|
279
|
+
seeing the evidence**. Chrome is used in visible mode only when the official Claude in Chrome is
|
|
280
|
+
connected. The router decides, validates, and downgrades — actual MCP tool calls are made by the
|
|
281
|
+
model (still guarded by the safety gate), and Chrome actions / final submit are done by the user.
|
|
282
|
+
|
|
283
|
+
## Safety gate threat model
|
|
284
|
+
|
|
285
|
+
The safety gate is a **minimal, deny-only core**. It blocks only positively-identified,
|
|
286
|
+
irreversible destructive actions and exposed secret values; there is no confirmation (ask) tier.
|
|
287
|
+
Anything it cannot parse or is unsure about gets no opinion and is delegated to **Claude Code's
|
|
288
|
+
native permission prompt**.
|
|
289
|
+
|
|
290
|
+
| Threat | Behavior | Not guaranteed |
|
|
291
|
+
|---|---|---|
|
|
292
|
+
| Local destructive commands (`rm -rf ~`·`/`·project root, `dd`/`mkfs`/`shred`, PowerShell `Format-Volume`/`Clear-Disk`) | parse the bare command, deny if catastrophic | Obfuscation, piped/chained/substituted commands, deleting a normal folder, execution outside the plugin |
|
|
293
|
+
| Git history destruction (`push --force`) | deny when the target is a protected branch | Force-push to an unprotected branch, `reset --hard`·`clean` (delegated), other Git clients |
|
|
294
|
+
| DB / remote resource deletion (CLI·MCP) | deny destructive ops on production/unknown targets | staging/dev targets (delegated), actions in an external console |
|
|
295
|
+
| Secret commit / deploy / command-line exposure | scan commit candidate tree, deploy args, and the command line; deny on a secret value | Unsupported formats, encrypted/obfuscated secrets, unscannable (oversize·exotic) |
|
|
296
|
+
| Cost / retry loops | at most one intervention per batch | Exact billing, hard billing cap |
|
|
297
|
+
|
|
298
|
+
### Explicit non-guarantees (No silent security claims)
|
|
299
|
+
|
|
300
|
+
- **Not a general shell parser.** It parses only a single bare command + argv. Unsupported
|
|
301
|
+
syntax — pipes, redirects, command substitution, chains (`&&`·`;`) — gets **no opinion and is
|
|
302
|
+
delegated to Claude Code's native permission**. Because of this, a piped destructive command
|
|
303
|
+
(`rm -rf / ; …`) may not be caught by novice — Claude Code's own prompt handles it instead.
|
|
304
|
+
(A secret value on the command line is still scanned and denied regardless of grammar.)
|
|
305
|
+
- **No confirmation (ask) tier.** When unsure it delegates rather than prompting — by design, to
|
|
306
|
+
eliminate false prompts on benign commands. Only hard-to-reverse destruction/secrets are blocked.
|
|
307
|
+
- **Not a full DLP, secret manager, or malicious-MCP defense.** Detection is based only on
|
|
308
|
+
known-pattern fixtures. Unscannable targets (large files, exotic git options, unborn HEAD) are
|
|
309
|
+
delegated, not blocked.
|
|
310
|
+
- **timeout fail-open limit:** cases where Claude Code treats a hook timeout / forced kill as
|
|
311
|
+
non-blocking are outside the guarantee. Internal hook errors, malformed input, and input-cap
|
|
312
|
+
overflow are denied (fail closed).
|
|
313
|
+
- **Disabling/uninstalling the plugin removes the safety gate too.** "Always-on" only means
|
|
314
|
+
while the plugin is enabled. novice `off` turns off only the learning layer; the safety gate
|
|
315
|
+
stays on.
|
|
316
|
+
- **Git protects tracked local files only.** Untracked/ignored files, external DBs, and deploy
|
|
317
|
+
resources are not recoverable via a Git checkpoint.
|
|
318
|
+
|
|
319
|
+
## State and privacy
|
|
320
|
+
|
|
321
|
+
- State is stored only under `${CLAUDE_PLUGIN_DATA}` (project override, per-session term
|
|
322
|
+
counters). Nothing is written to the plugin root.
|
|
323
|
+
- State files: atomic write, `0600`, symlink refusal, size cap. Session state is deleted on
|
|
324
|
+
`/clear`, with a 30-day TTL.
|
|
325
|
+
- The secret scanner inspects candidate bytes in memory only and never leaves the original in
|
|
326
|
+
logs/state/metrics.
|
|
327
|
+
- The bootstrap audit stores only service ID, manifest revision, step, and exit status.
|
|
328
|
+
- No remote telemetry is sent.
|
|
329
|
+
|
|
330
|
+
## Release Notes
|
|
331
|
+
|
|
332
|
+
### 0.2.0 (2026-07-21)
|
|
333
|
+
- **Safety gate reduced to a deny-only minimal core** — the confirmation (ask) tier is gone;
|
|
334
|
+
false prompts on benign piped/chained commands are eliminated. Unparseable/ambiguous commands
|
|
335
|
+
are delegated to Claude Code's native permission prompt.
|
|
336
|
+
- Still denied: `rm` of home/root/project root, `dd`/`mkfs`/`shred`/disk-format cmdlets,
|
|
337
|
+
protected-branch force-push, destructive MCP on production/unknown, secret values in
|
|
338
|
+
commits/deploys/command lines.
|
|
339
|
+
- New `/novice` front-door command (status dashboard + subcommand guide).
|
|
340
|
+
- `tests/fixtures/` excluded from the commit/deploy secret scan (the plugin no longer blocks
|
|
341
|
+
committing its own test corpus). Config cleanup, PRD rev 12, 147 tests.
|
|
342
|
+
|
|
343
|
+
### 0.1.0 (2026-07-20)
|
|
344
|
+
- Initial release — 3-level learning companion (term annotation·fade·mute), safety gate,
|
|
345
|
+
2-tier CLI bootstrap (vercel/gh/supabase), MCP·Chrome capability router. PRD rev 11.
|
|
346
|
+
|
|
347
|
+
## Development
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
npm test # everything (unit + integration)
|
|
351
|
+
npm run test:unit
|
|
352
|
+
npm run test:integration
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
No external runtime dependencies (Node >= 18, node:test). Test layout: 11 unit files
|
|
356
|
+
(config·state·mode·capsule·stop·grammar·secrets·batch·bootstrap·capability-router·output-style),
|
|
357
|
+
4 integration files (hooks-contract·safety-corpus·safety-mutation·latency-benchmark). The safety
|
|
358
|
+
gate is also checked by a mutation harness — it mutates 35 dangerous commands into 106 mutants
|
|
359
|
+
and confirms the detector is never bypassed. The latency benchmark enforces the blocking-hook p95
|
|
360
|
+
budget (UserPromptSubmit ≤300ms, PreToolUse ≤250ms) as a regression test (tune iterations with
|
|
361
|
+
`NOVICE_BENCH_ITERS`).
|
|
362
|
+
|
|
363
|
+
The hook-payload fixtures in `tests/fixtures/contract/` are **real Claude Code 2.1.215
|
|
364
|
+
captures** (the `provenance` field distinguishes captured/derived/documented — see that
|
|
365
|
+
directory's README). The plugin itself was also loaded on the same runtime via `--plugin-dir`
|
|
366
|
+
and confirmed end to end: `/novice:mode` expansion → state update → capsule injection, and the
|
|
367
|
+
hook execution order (expansion→submit) was captured too.
|
|
368
|
+
|
|
369
|
+
What cannot be verified in code (documented as such): real CLI install/login E2E (needs the
|
|
370
|
+
user's environment and accounts), real captures of the `/clear`/compact SessionStart source and
|
|
371
|
+
the MCP destructive payload (cannot be triggered headlessly), and the product-beta metrics
|
|
372
|
+
(need human participants).
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"manifest_revision": 1,
|
|
4
|
+
"reviewed_at": "2026-07-20",
|
|
5
|
+
"tier": 1,
|
|
6
|
+
"service_id": "github",
|
|
7
|
+
"binary": "gh",
|
|
8
|
+
"docs_url": "https://cli.github.com/manual/gh_auth_login",
|
|
9
|
+
"installers": [
|
|
10
|
+
{
|
|
11
|
+
"os": ["darwin"],
|
|
12
|
+
"package_manager": "homebrew",
|
|
13
|
+
"package_coordinate": "gh",
|
|
14
|
+
"argv": ["brew", "install", "gh"],
|
|
15
|
+
"min_version": "2.40.0",
|
|
16
|
+
"global_changes": ["Homebrew Cellar에 gh 설치"]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"os": ["linux"],
|
|
20
|
+
"package_manager": "apt",
|
|
21
|
+
"package_coordinate": "gh",
|
|
22
|
+
"argv": ["sudo", "apt-get", "install", "-y", "gh"],
|
|
23
|
+
"min_version": "2.40.0",
|
|
24
|
+
"global_changes": ["시스템 패키지로 gh 설치"]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"os": ["win32"],
|
|
28
|
+
"package_manager": "winget",
|
|
29
|
+
"package_coordinate": "GitHub.cli",
|
|
30
|
+
"argv": ["winget", "install", "--id", "GitHub.cli", "--exact"],
|
|
31
|
+
"min_version": "2.40.0",
|
|
32
|
+
"global_changes": ["시스템에 GitHub CLI 설치"]
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"detect": {
|
|
36
|
+
"argv": ["gh", "--version"],
|
|
37
|
+
"success": { "exit_code": 0 }
|
|
38
|
+
},
|
|
39
|
+
"version_check": {
|
|
40
|
+
"argv": ["gh", "--version"],
|
|
41
|
+
"success": { "exit_code": 0, "stdout_regex": "gh version \\d+\\.\\d+\\.\\d+" }
|
|
42
|
+
},
|
|
43
|
+
"auth_status": {
|
|
44
|
+
"argv": ["gh", "auth", "status"],
|
|
45
|
+
"success": { "exit_code": 0 },
|
|
46
|
+
"unauthenticated": { "exit_code_not": 0 }
|
|
47
|
+
},
|
|
48
|
+
"login": {
|
|
49
|
+
"argv": ["gh", "auth", "login", "--web"],
|
|
50
|
+
"interactive": true,
|
|
51
|
+
"user_completes": ["브라우저 device flow 인증 코드 입력"],
|
|
52
|
+
"success_verify": "auth_status"
|
|
53
|
+
},
|
|
54
|
+
"logout": {
|
|
55
|
+
"argv": ["gh", "auth", "logout"]
|
|
56
|
+
},
|
|
57
|
+
"credential_store": {
|
|
58
|
+
"storage": "OS keychain (macOS Keychain, Windows Credential Manager, libsecret) 우선",
|
|
59
|
+
"secure_storage": true,
|
|
60
|
+
"plaintext_fallback": true,
|
|
61
|
+
"plaintext_fallback_location": "~/.config/gh/hosts.yml",
|
|
62
|
+
"abort_auto_login_on_plaintext": true,
|
|
63
|
+
"abort_note": "keychain을 쓸 수 없어 hosts.yml plaintext로 떨어지는 환경이면 자동 로그인을 중단하고 위치·위험·logout 경로를 안내한다.",
|
|
64
|
+
"disclosure": "인증 토큰은 기본적으로 OS keychain에 저장된다. keychain이 없으면 ~/.config/gh/hosts.yml에 평문 저장될 수 있다."
|
|
65
|
+
},
|
|
66
|
+
"uninstall": {
|
|
67
|
+
"homebrew": ["brew", "uninstall", "gh"],
|
|
68
|
+
"apt": ["sudo", "apt-get", "remove", "-y", "gh"],
|
|
69
|
+
"winget": ["winget", "uninstall", "--id", "GitHub.cli"]
|
|
70
|
+
},
|
|
71
|
+
"side_effects": [
|
|
72
|
+
"전역 패키지 추가",
|
|
73
|
+
"~/.config/gh 설정 디렉토리 생성",
|
|
74
|
+
"OS keychain에 인증 항목 추가"
|
|
75
|
+
],
|
|
76
|
+
"noninteractive_policy": {
|
|
77
|
+
"login": "deny",
|
|
78
|
+
"reason": "gh auth login 대화형 흐름은 비대화형 환경에서 실행하지 않는다. GH_TOKEN 환경변수 사용법을 guided manual로 안내한다"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"manifest_revision": 1,
|
|
4
|
+
"reviewed_at": "2026-07-20",
|
|
5
|
+
"tier": 1,
|
|
6
|
+
"service_id": "supabase",
|
|
7
|
+
"binary": "supabase",
|
|
8
|
+
"docs_url": "https://supabase.com/docs/reference/cli/install",
|
|
9
|
+
"installers": [
|
|
10
|
+
{
|
|
11
|
+
"os": ["darwin", "linux"],
|
|
12
|
+
"package_manager": "homebrew",
|
|
13
|
+
"package_coordinate": "supabase/tap/supabase",
|
|
14
|
+
"argv": ["brew", "install", "supabase/tap/supabase"],
|
|
15
|
+
"min_version": "1.200.0",
|
|
16
|
+
"global_changes": ["Homebrew tap 추가 및 supabase 설치"]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"os": ["win32"],
|
|
20
|
+
"package_manager": "scoop",
|
|
21
|
+
"package_coordinate": "supabase",
|
|
22
|
+
"argv": ["scoop", "install", "supabase"],
|
|
23
|
+
"min_version": "1.200.0",
|
|
24
|
+
"global_changes": ["scoop bucket에서 supabase 설치"]
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"detect": {
|
|
28
|
+
"argv": ["supabase", "--version"],
|
|
29
|
+
"success": { "exit_code": 0 }
|
|
30
|
+
},
|
|
31
|
+
"version_check": {
|
|
32
|
+
"argv": ["supabase", "--version"],
|
|
33
|
+
"success": { "exit_code": 0, "stdout_regex": "\\d+\\.\\d+\\.\\d+" }
|
|
34
|
+
},
|
|
35
|
+
"auth_status": {
|
|
36
|
+
"argv": ["supabase", "projects", "list"],
|
|
37
|
+
"success": { "exit_code": 0 },
|
|
38
|
+
"unauthenticated": { "exit_code_not": 0 }
|
|
39
|
+
},
|
|
40
|
+
"login": {
|
|
41
|
+
"argv": ["supabase", "login"],
|
|
42
|
+
"interactive": true,
|
|
43
|
+
"user_completes": ["브라우저에서 access token 발급·확인"],
|
|
44
|
+
"success_verify": "auth_status"
|
|
45
|
+
},
|
|
46
|
+
"logout": {
|
|
47
|
+
"argv": ["supabase", "logout"]
|
|
48
|
+
},
|
|
49
|
+
"credential_store": {
|
|
50
|
+
"storage": "OS native credential storage (macOS Keychain 등) 우선",
|
|
51
|
+
"secure_storage": true,
|
|
52
|
+
"plaintext_fallback": true,
|
|
53
|
+
"plaintext_fallback_location": "~/.supabase/access-token",
|
|
54
|
+
"abort_auto_login_on_plaintext": true,
|
|
55
|
+
"abort_note": "native credential storage가 없어 plaintext 파일로 떨어지면 자동 로그인을 중단하고 위치·삭제 방법을 안내한다.",
|
|
56
|
+
"disclosure": "access token은 기본적으로 OS 보안 저장소에 저장된다. 미지원 환경에서는 ~/.supabase 아래 평문 저장될 수 있다."
|
|
57
|
+
},
|
|
58
|
+
"uninstall": {
|
|
59
|
+
"homebrew": ["brew", "uninstall", "supabase"],
|
|
60
|
+
"scoop": ["scoop", "uninstall", "supabase"]
|
|
61
|
+
},
|
|
62
|
+
"side_effects": [
|
|
63
|
+
"전역 패키지 추가",
|
|
64
|
+
"~/.supabase 설정 디렉토리 생성 가능",
|
|
65
|
+
"OS keychain에 access token 항목 추가"
|
|
66
|
+
],
|
|
67
|
+
"noninteractive_policy": {
|
|
68
|
+
"login": "guided_manual",
|
|
69
|
+
"reason": "supabase login은 브라우저 토큰 발급이 필요하다. 비대화형 환경에서는 SUPABASE_ACCESS_TOKEN 환경변수 설정을 사용자가 직접 하도록 안내한다"
|
|
70
|
+
}
|
|
71
|
+
}
|