ccperm 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ko.md CHANGED
@@ -41,24 +41,29 @@ ccperm
41
41
 
42
42
  TTY 환경(기본)에서는 박스 프레임 TUI가 실행됩니다:
43
43
 
44
- **목록 뷰** — 프로젝트가 권한 수 기준으로 정렬됩니다. 컬럼: Bash, MCP, Tools, TOTAL, `!` (위험도 경고), `†` (deprecated `:*` 패턴).
44
+ **목록 뷰** — 프로젝트가 권한 수 기준으로 정렬됩니다. 컬럼: Bash, MCP, Tools, TOTAL, `!` (위험도), `†` (deprecated `:*`), `G` (글로벌과 중복).
45
45
 
46
46
  ```
47
- ┌ ccperm ──────────────────────────── 1/8 ┐
48
- │ PROJECT Bash MCP Tools TOTAL
49
- ├─────────────────────────────────────────┤
50
- │ ~/.claude 2 2 │
51
- ├─────────────────────────────────────────┤
52
- │ ▸ my-project local 5 · 3 8 │
53
- │ other-app shared 2 3 · 5 │
54
- [↑↓] navigate [Enter] detail [q] quit┘
47
+ ┌ ccperm ──────────────────────────────── 1/8 ┐
48
+ │ PROJECT Bash MCP Tools TOTAL G
49
+ ├─────────────────────────────────────────────┤
50
+ │ ~/.claude 15 · 2 17 ·│
51
+ ├─────────────────────────────────────────────┤
52
+ │ ▸ my-project local 5 · 3 8 3
53
+ │ other-app shared 2 3 · 5 ·
54
+ │ ! risk deprecated G in global │
55
+ └──────── [↑↓] navigate [Enter] detail [/] search [q] quit┘
55
56
  ```
56
57
 
57
- **상세 뷰** — Enter로 프로젝트를 펼칩니다. 카테고리를 Enter로 접고 펼 수 있습니다. `[d]`로 권한 삭제, `[g]`로 글로벌 설정에 복사할 수 있습니다.
58
+ **상세 뷰** — Enter로 프로젝트를 펼칩니다. 카테고리를 Enter로 접고 펼 수 있습니다.
59
+ - `[d]` 권한 삭제
60
+ - `[g]` 글로벌에 추가 (즉시 `(in global)` 태그 반영)
61
+ - `[i]` 위험도 정보 토글
62
+ - 글로벌에 이미 있는 권한은 노란색 `(in global)` 태그 표시
58
63
 
59
- **정보 모드**`[i]`를 누르면 권한의 위험도와 설명이 나타납니다.
64
+ **검색 뷰**`/`로 전체 프로젝트의 권한을 검색합니다. 권한명 기준 매칭, 프로젝트별로 그룹 표시. 방향키로 탐색 (헤더 자동 스킵), Enter로 해당 프로젝트 상세 뷰로 이동.
60
65
 
61
- 키 조작: `↑↓` 이동, `Enter` 선택/펼치기, `[i]` 정보, `[d]` 삭제, `[g]` 글로벌 복사, `Esc` 뒤로, `q` 종료.
66
+ 키 조작: `↑↓` 이동, `Enter` 선택/펼치기, `[i]` 정보, `[d]` 삭제, `[g]` +global, `/` 검색, `Esc` 뒤로, `q` 종료.
62
67
 
63
68
  ## 텍스트 출력
64
69
 
package/README.md CHANGED
@@ -41,24 +41,29 @@ By default, ccperm scans all projects under `~` and launches an interactive TUI.
41
41
 
42
42
  When running in a TTY (the default), ccperm opens a box-frame TUI:
43
43
 
44
- **List view** — Projects sorted by permission count. Columns: Bash, MCP, Tools, TOTAL, `!` (risk warnings), `†` (deprecated `:*` patterns).
44
+ **List view** — Projects sorted by permission count. Columns: Bash, MCP, Tools, TOTAL, `!` (risk), `†` (deprecated `:*`), `G` (redundant with global).
45
45
 
46
46
  ```
47
- ┌ ccperm ──────────────────────────── 1/8 ┐
48
- │ PROJECT Bash MCP Tools TOTAL
49
- ├─────────────────────────────────────────┤
50
- │ ~/.claude 2 2 │
51
- ├─────────────────────────────────────────┤
52
- │ ▸ my-project local 5 · 3 8 │
53
- │ other-app shared 2 3 · 5 │
54
- [↑↓] navigate [Enter] detail [q] quit┘
47
+ ┌ ccperm ──────────────────────────────── 1/8 ┐
48
+ │ PROJECT Bash MCP Tools TOTAL G
49
+ ├─────────────────────────────────────────────┤
50
+ │ ~/.claude 15 · 2 17 ·│
51
+ ├─────────────────────────────────────────────┤
52
+ │ ▸ my-project local 5 · 3 8 3
53
+ │ other-app shared 2 3 · 5 ·
54
+ │ ! risk deprecated G in global │
55
+ └──────── [↑↓] navigate [Enter] detail [/] search [q] quit┘
55
56
  ```
56
57
 
57
- **Detail view** — Press Enter to expand a project. Categories are collapsible; press Enter to toggle. Press `[d]` to delete a permission, `[g]` to copy it to global settings.
58
+ **Detail view** — Press Enter to expand a project. Categories are collapsible; press Enter to toggle.
59
+ - `[d]` delete a permission
60
+ - `[g]` add permission to global settings (shows `(in global)` tag immediately)
61
+ - `[i]` toggle risk info mode
62
+ - Permissions already in global are tagged `(in global)` in yellow
58
63
 
59
- **Info mode** — Press `[i]` to show risk level and description for each permission.
64
+ **Search view** — Press `/` to search across all projects. Matches permission names and shows results grouped by project. Arrow keys navigate (headers are skipped), Enter jumps to the project's detail view.
60
65
 
61
- Keys: `↑↓` navigate, `Enter` select/expand, `[i]` info, `[d]` delete, `[g]` copy to global, `Esc` back, `q` quit.
66
+ Keys: `↑↓` navigate, `Enter` select/expand, `[i]` info, `[d]` delete, `[g]` +global, `/` search, `Esc` back, `q` quit.
62
67
 
63
68
  ## Static Output
64
69
 
package/dist/explain.js CHANGED
@@ -58,6 +58,13 @@ const BASH_COMMANDS = {
58
58
  // networking
59
59
  'curl': ['HTTP requests', 'medium', 'networking'],
60
60
  'wget': ['Download files', 'medium', 'networking'],
61
+ 'ss': ['Socket statistics', 'low', 'networking'],
62
+ 'netstat': ['Network statistics', 'low', 'networking'],
63
+ 'ip': ['Network config', 'low', 'networking'],
64
+ 'ping': ['Network connectivity test', 'low', 'networking'],
65
+ 'dig': ['DNS lookup', 'low', 'networking'],
66
+ 'nslookup': ['DNS lookup', 'low', 'networking'],
67
+ 'traceroute': ['Trace network route', 'low', 'networking'],
61
68
  'tailscale': ['Tailscale VPN', 'medium', 'networking'],
62
69
  'cloudflared': ['Cloudflare tunnel', 'medium', 'networking'],
63
70
  // databases
@@ -208,13 +215,24 @@ const TOOL_DESCRIPTIONS = {
208
215
  'Grep': ['Search file contents', 'low'],
209
216
  'WebSearch': ['Web search', 'low'],
210
217
  };
218
+ // Shell keywords that are not real commands — skip to find the actual command
219
+ const SHELL_KEYWORDS = new Set([
220
+ 'do', 'done', 'then', 'else', 'elif', 'fi', 'for', 'while', 'until',
221
+ 'if', 'case', 'esac', 'in', 'select',
222
+ ]);
211
223
  // Extract first command word from a bash label
212
224
  function extractCmd(label) {
213
225
  const clean = label
214
226
  .replace(/__NEW_LINE_[a-f0-9]+__\s*/, '')
215
227
  .replace(/[:]\*.*$/, '')
216
228
  .replace(/\s\*.*$/, '');
217
- return clean.split(/[\s(]/)[0];
229
+ const words = clean.split(/[\s(]/);
230
+ // Skip shell keywords to find the real command
231
+ for (const w of words) {
232
+ if (w && !SHELL_KEYWORDS.has(w))
233
+ return w;
234
+ }
235
+ return words[0];
218
236
  }
219
237
  function explainBash(label) {
220
238
  // Check critical patterns first (full string match)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccperm",
3
- "version": "1.14.0",
3
+ "version": "1.15.0",
4
4
  "description": "Audit Claude Code permissions across all your projects",
5
5
  "bin": {
6
6
  "ccperm": "bin/ccperm.js"