tabby-agentdeck 0.2.0 → 0.3.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 +193 -178
- package/dist/alert.service.d.ts +87 -0
- package/dist/api.d.ts +16 -2
- package/dist/bind.d.ts +23 -0
- package/dist/claudeHooks.d.ts +2 -1
- package/dist/config.d.ts +47 -0
- package/dist/deck.service.d.ts +58 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1403 -62
- package/dist/index.js.map +1 -1
- package/dist/notify.service.d.ts +92 -5
- package/dist/order.d.ts +26 -0
- package/dist/reason.d.ts +16 -0
- package/dist/recovery.service.d.ts +32 -0
- package/dist/settings.component.d.ts +4 -2
- package/dist/status.service.d.ts +14 -2
- package/dist/tabenv.d.ts +26 -0
- package/hooks/agentdeck-notify.ps1 +126 -6
- package/hooks/agentdeck-status.ps1 +2 -2
- package/install.ps1 +2 -31
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,178 +1,193 @@
|
|
|
1
|
-
# tabby-agentdeck
|
|
2
|
-
|
|
3
|
-
Tabby 터미널 플러그인. **Claude Code · Codex 같은 AI 에이전트 CLI 를 여러 탭에 띄워 놓고 쓰는 사람**을 위한 것이다.
|
|
4
|
-
|
|
5
|
-
터미널 뷰포트를 **4:3 으로 고정**하고 남는 공간에 **세션 목록 + 작업 상태 사이드바**를 그린다.
|
|
6
|
-
어느 에이전트가 돌고 있고 어느 쪽이 내 입력을 기다리는지 탭을 옮겨 다니지 않고 한눈에 본다.
|
|
7
|
-
거기에 에이전트 CLI 가 터미널에서 겪는 문제들(이미지 붙여넣기, 줄바꿈 키, pty 폭 어긋남)을 같이 손봐 둔다.
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
┌──────────────────────────────┬──────────────────┐
|
|
11
|
-
│ │ AGENT DECK 4 │
|
|
12
|
-
│ 터미널 (창 높이 × 4/3) ├──────────────────┤
|
|
13
|
-
│ │ ● 진행중 리팩터링 │
|
|
14
|
-
│ Tabby 순정 탭바는 숨김 │ ⏸ 승인대기 재빌드 │
|
|
15
|
-
│ │ ✔ 완료 테스트 │
|
|
16
|
-
│ │ ○ 대기 │
|
|
17
|
-
│ ├──────────────────┤
|
|
18
|
-
│ │ + 새 탭 │ 설정 │
|
|
19
|
-
└──────────────────────────────┴──────────────────┘
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Windows 에서 만들고 검증했다. 상태 통보 훅은 PowerShell 스크립트라 Windows 전용이고, 그 외 기능은 플랫폼을 가리지 않는다.
|
|
23
|
-
|
|
24
|
-
## 기능
|
|
25
|
-
|
|
26
|
-
| | 동작 |
|
|
27
|
-
|---|---|
|
|
28
|
-
| **4:3 기준 폭 계산** | 창 높이에서 폭을 역산해 터미널을 고정폭으로 만든다. 남는 폭은 사이드바가 갖고, 그러고도 남으면 터미널이 흡수한다 |
|
|
29
|
-
| **사이드바 탭 관리** | 클릭=선택, `×`=닫기, 더블클릭=작업 이름 편집, 우클릭=상태 직접 지정 |
|
|
30
|
-
| **마우스 도킹** | 헤더를 끌어 좌/우/상/하 어느 가장자리에나 붙이고, 경계선을 끌어 크기를 바꾼다 |
|
|
31
|
-
| **작업 상태** | 진행중 / 승인대기 / 완료 / 오류 / 대기 를 색·배지·경과시간으로 표시 |
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
npm
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
|
130
|
-
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
1
|
+
# tabby-agentdeck
|
|
2
|
+
|
|
3
|
+
Tabby 터미널 플러그인. **Claude Code · Codex 같은 AI 에이전트 CLI 를 여러 탭에 띄워 놓고 쓰는 사람**을 위한 것이다.
|
|
4
|
+
|
|
5
|
+
터미널 뷰포트를 **4:3 으로 고정**하고 남는 공간에 **세션 목록 + 작업 상태 사이드바**를 그린다.
|
|
6
|
+
어느 에이전트가 돌고 있고 어느 쪽이 내 입력을 기다리는지 탭을 옮겨 다니지 않고 한눈에 본다.
|
|
7
|
+
거기에 에이전트 CLI 가 터미널에서 겪는 문제들(이미지 붙여넣기, 줄바꿈 키, pty 폭 어긋남)을 같이 손봐 둔다.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
┌──────────────────────────────┬──────────────────┐
|
|
11
|
+
│ │ AGENT DECK 4 │
|
|
12
|
+
│ 터미널 (창 높이 × 4/3) ├──────────────────┤
|
|
13
|
+
│ │ ● 진행중 리팩터링 │
|
|
14
|
+
│ Tabby 순정 탭바는 숨김 │ ⏸ 승인대기 재빌드 │
|
|
15
|
+
│ │ ✔ 완료 테스트 │
|
|
16
|
+
│ │ ○ 대기 │
|
|
17
|
+
│ ├──────────────────┤
|
|
18
|
+
│ │ + 새 탭 │ 설정 │
|
|
19
|
+
└──────────────────────────────┴──────────────────┘
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Windows 에서 만들고 검증했다. 상태 통보 훅은 PowerShell 스크립트라 Windows 전용이고, 그 외 기능은 플랫폼을 가리지 않는다.
|
|
23
|
+
|
|
24
|
+
## 기능
|
|
25
|
+
|
|
26
|
+
| | 동작 |
|
|
27
|
+
|---|---|
|
|
28
|
+
| **4:3 기준 폭 계산** | 창 높이에서 폭을 역산해 터미널을 고정폭으로 만든다. 남는 폭은 사이드바가 갖고, 그러고도 남으면 터미널이 흡수한다 |
|
|
29
|
+
| **사이드바 탭 관리** | 클릭=선택, `×`=닫기, 더블클릭=작업 이름 편집, 우클릭=상태 직접 지정 |
|
|
30
|
+
| **마우스 도킹** | 헤더를 끌어 좌/우/상/하 어느 가장자리에나 붙이고, 경계선을 끌어 크기를 바꾼다 |
|
|
31
|
+
| **작업 상태** | 진행중 / 승인대기 / 한도 도달 / 완료 / 오류 / 대기 를 색·배지·경과시간으로 표시 |
|
|
32
|
+
| **상태별 집계** | 헤더 오른쪽에 상태별 탭 수를 `⏸ 2 ● 3 ○ 1` 처럼 급한 순서(승인대기 → 오류 → 한도 도달 → 진행중 → 완료 → 대기)로 보여준다. `sortByStatus` 를 켜면 같은 순서로 탭이 정렬된다 |
|
|
33
|
+
| **작업 이름** | Enter 로 프롬프트를 보내는 순간 입력창 원문을 읽어 라벨로 삼는다 |
|
|
34
|
+
| **Claude Code 훅 연동** | 설정 창에서 한 번 설치하면 에이전트가 상태를 직접 알려준다 (선택) |
|
|
35
|
+
| **기본 프로필** | 새 탭을 항상 지정한 작업 루트에서 연다 |
|
|
36
|
+
| **입력 보정** | `Ctrl+V` 이미지 붙여넣기, `Ctrl+Enter`/`Shift+Enter` 줄바꿈, 우클릭 복사/붙여넣기 |
|
|
37
|
+
| **화면 복구** | 깨진 TUI 를 지우고 다시 그리게 한다. 사이드바 `↻` / 탭 우클릭 / `agentdeck-repair` 핫키 |
|
|
38
|
+
|
|
39
|
+
## 설치
|
|
40
|
+
|
|
41
|
+
**Tabby 안에서**: 설정 → 플러그인 → `agentdeck` 검색 → 설치 → Tabby 재시작.
|
|
42
|
+
|
|
43
|
+
**소스에서**:
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
npm install
|
|
47
|
+
npm run build
|
|
48
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File install.ps1
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`install.ps1` 은 Tabby 플러그인 디렉토리(`%APPDATA%\tabby\plugins\node_modules\tabby-agentdeck`)에
|
|
52
|
+
이 폴더를 가리키는 junction 을 건다. 소스를 고치고 `npm run build` 하면 Tabby 재시작으로 반영된다.
|
|
53
|
+
|
|
54
|
+
## 작업 이름과 상태
|
|
55
|
+
|
|
56
|
+
사이드바 한 줄은 **작업 이름(라벨)** 과 **상태 배지** 로 이루어진다.
|
|
57
|
+
둘 다 **설정 없이 플러그인만으로 돈다.** 더 정확하게 하려면 Claude Code 훅을 건다.
|
|
58
|
+
|
|
59
|
+
### 작업 이름
|
|
60
|
+
|
|
61
|
+
Enter 로 프롬프트를 보내는 그 순간, 화면에 그려져 있는 입력창(`❯ ...`, `> ...`)을 읽어 40자로 잘라 라벨에 넣는다.
|
|
62
|
+
붙여넣기·↑ 히스토리·IME 로 들어온 글자도 화면에 그려진 대로 잡힌다.
|
|
63
|
+
Shift+Enter / Ctrl+Enter 는 줄바꿈이라 라벨을 바꾸지 않고, 입력창 머리를 못 찾으면(일반 셸, y/n 확인 등) 라벨을 그대로 둔다.
|
|
64
|
+
|
|
65
|
+
### 상태
|
|
66
|
+
|
|
67
|
+
- **자동 감지(기본)**: PTY 출력이 흐르면 `진행중`, `idleAfterMs`(기본 2.5초) 동안 조용하면 `대기`.
|
|
68
|
+
`Do you want to`, `❯ 1. Yes`, `(y/n)` 같은 패턴이 보이면 `승인대기`. Claude Code 가 제목에 넣는 스피너도 진행중으로 읽는다.
|
|
69
|
+
`승인대기` 인 탭에 `esc to interrupt` 같은 작업 중 문구가 다시 보이면 사람이 승인한 것으로 보고 `진행중` 으로 올린다 —
|
|
70
|
+
훅이 고정한 탭에도 적용된다 (승인 뒤 첫 훅은 도구가 끝난 뒤라, 긴 빌드를 승인하면 그동안 승인대기에 박혀 있었다).
|
|
71
|
+
- **Claude Code 훅(권장)**: 설정 → AgentDeck → "상태 통보 훅" 설치. `~/.claude/settings.json` 의
|
|
72
|
+
UserPromptSubmit / Notification / PostToolUse / PostToolUseFailure / PermissionDenied / Stop / StopFailure 에 통보 스크립트를 건다.
|
|
73
|
+
다른 훅은 건드리지 않고 쓰기 전에 백업을 남긴다. 0.3.0 에서 이벤트가 늘었으므로 옛 설치는 "설치 안 됨" 으로 보인다 — 설치를 다시 누르면 된다.
|
|
74
|
+
에이전트가 "지시를 받았다 / 승인을 기다린다 / 도구가 돌았다(=승인됐다) / 끝났다 / 실패로 끝났다" 를 직접 알려주므로 판정이 흔들리지 않는다. 설정 창의 "제거" 로 되돌린다.
|
|
75
|
+
승인대기에는 이유(예: `Bash 권한`, `입력 대기`)가 함께 표시된다 — `⏸ 승인대기 · Bash 권한`. 상태가 바뀌면 이유는 사라진다.
|
|
76
|
+
- **한도 도달**: Claude Code 가 사용량 한도(세션/주간)에 걸려 턴이 끊기면 `StopFailure` 훅이 `error: rate_limit` 로 알려주고
|
|
77
|
+
사이드바는 `⛔ 한도 도달 · 12pm 리셋` 처럼 리셋 시각과 함께 보여준다. 승인할 것이 없는 상태라 승인대기와 구분한다.
|
|
78
|
+
한도 외의 실패(overloaded, server_error …)는 `✖ 오류 · overloaded` 로 표시된다. 한도가 풀려 세션이 이어지면(다음 프롬프트·도구 실행) 진행중으로 돌아온다.
|
|
79
|
+
훅 보고는 플러그인이 탭 셸에 심은 `AGENTDECK_TAB` 환경변수로 어느 탭인지 확정한다
|
|
80
|
+
(0.2.2 이전에 열린 탭·재시작으로 복원된 탭은 프로세스 계보로 폴백).
|
|
81
|
+
|
|
82
|
+
### 직접 지정
|
|
83
|
+
|
|
84
|
+
- 사이드바에서 **우클릭 → 상태 고르기**, **더블클릭 → 이름 편집**.
|
|
85
|
+
- 셸 스크립트 안에서라면 콘솔 제목을 `[AD:<status>] <라벨>` 로 바꾼다. 접두사는 표시에서 지워진다.
|
|
86
|
+
|
|
87
|
+
```powershell
|
|
88
|
+
$host.UI.RawUI.WindowTitle = "[AD:waiting] 배포 승인 대기"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
status 는 `running` / `waiting` / `done` / `error` / `idle`.
|
|
92
|
+
직접 지정한 상태는 **고정**되어 자동 감지가 덮어쓰지 않는다(배지에 점선 밑줄). 우클릭 → `↺ 자동 감지로` 로 해제한다.
|
|
93
|
+
이 경로는 셸 안에서 직접 실행할 때만 통한다 — 에이전트 훅에서는 콘솔 제목이 터미널까지 오지 않는다.
|
|
94
|
+
|
|
95
|
+
### 알림
|
|
96
|
+
|
|
97
|
+
창이 다른 앱 뒤에 가 있을 때(포커스 없음) 어느 탭이 `승인대기` · `오류` · `한도 도달` 로 넘어가면 OS 쪽에 알린다 —
|
|
98
|
+
작업표시줄 아이콘이 깜빡이고(`alertFlash`), 아이콘 위에 그런 탭의 개수가 뱃지로 얹힌다(`alertBadge`).
|
|
99
|
+
뱃지는 상태가 풀리는 대로 실제 개수를 따라가고 0 이면 사라진다. 깜빡임은 창을 다시 앞으로 가져오면 멈춘다.
|
|
100
|
+
OS 토스트(`alertToast`)는 기본으로 꺼져 있다 — 켜면 토스트를 눌러 바로 그 탭으로 갈 수 있다.
|
|
101
|
+
창이 앞에 있을 때는 셋 다 아무 일도 하지 않는다. 사이드바가 이미 보이고 있기 때문이다.
|
|
102
|
+
|
|
103
|
+
## 키
|
|
104
|
+
|
|
105
|
+
| 키 | 동작 |
|
|
106
|
+
|---|---|
|
|
107
|
+
| `Ctrl+Enter` / `Shift+Enter` | 줄바꿈 (`0x0A` 전송). `agentdeck-newline` |
|
|
108
|
+
| `Ctrl+V` | 붙여넣기. 클립보드에 **이미지만** 있으면 텍스트 대신 이미지 붙여넣기 키를 앱에 넘긴다 — Claude Code·Codex 가 클립보드를 직접 읽는다. `agentdeck-paste` |
|
|
109
|
+
| 우클릭 | 선택이 있으면 복사, 없으면 붙여넣기. 길게(기본 250ms) 누르면 컨텍스트 메뉴 |
|
|
110
|
+
| (미배정) | `agentdeck-toggle` — 사이드바/4:3 즉시 on-off |
|
|
111
|
+
| (미배정) | `agentdeck-repair` — 화면 복구 |
|
|
112
|
+
|
|
113
|
+
키 배정은 Tabby 설정 → 단축키의 `agentdeck-*` 항목에서 바꾼다.
|
|
114
|
+
`Ctrl+V` 는 플러그인이 기동할 때 `agentdeck-paste` 에 넣고 순정 `hotkeys.paste` 에서는 뺀다(둘 다 있으면 두 번 붙는다).
|
|
115
|
+
터미널 앱에 리터럴 `Ctrl+V`(0x16)를 보내야 하면 `claimCtrlV: false`.
|
|
116
|
+
|
|
117
|
+
### 화면 복구 (`↻`)
|
|
118
|
+
|
|
119
|
+
statusline 이 사라지거나 입력창 구분선이 화면 중간에서 끊기는 등 화면이 깨졌을 때 누른다.
|
|
120
|
+
폭 재계산 → pty 크기 동기화 → 터미널 상태 초기화 → 앱에 전체 재렌더 요청(`Ctrl+L`) 순으로 진행한다.
|
|
121
|
+
기본값은 스크롤백을 보존한다(`repairHard: false`). 잔상까지 지우려면 `repairHard: true`.
|
|
122
|
+
|
|
123
|
+
## 설정
|
|
124
|
+
|
|
125
|
+
**설정 창(설정 → AgentDeck)** 에는 실제로 바꿀 일이 있는 것만 있다 — 레이아웃 on/off, 마우스로 바꾼 배치 초기화,
|
|
126
|
+
기동 시 탭 복원 끄기, Claude Code 훅 설치/제거, 작업 루트 프로필. 나머지는 Tabby 설정 파일(`%APPDATA%\tabby\config.yaml`)의
|
|
127
|
+
`agentDeck` 아래에서 조절한다.
|
|
128
|
+
|
|
129
|
+
| 키 | 기본값 | 설명 |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| `enabled` | `true` | 사이드바 + 4:3 레이아웃 on/off |
|
|
132
|
+
| `aspectW` / `aspectH` | `4` / `3` | 터미널 뷰포트 비율 |
|
|
133
|
+
| `sidebarDock` | `right` | 사이드바 위치 `left` / `right` / `top` / `bottom`. 헤더 드래그로도 바뀐다 |
|
|
134
|
+
| `sidebarWidth` | `0` | 좌/우 도킹 시 폭(px). 0 = 화면비로 자동 계산 |
|
|
135
|
+
| `sidebarHeight` | `200` | 상/하 도킹 시 높이(px) |
|
|
136
|
+
| `sidebarMin` / `sidebarMax` | `200` / `560` | 자동 계산 폭의 범위(px). 넓은 모니터에서 정확히 4:3 을 원하면 `sidebarMax` 를 `창 너비 − 창 높이 × 4/3` 으로 |
|
|
137
|
+
| `idleAfterMs` | `2500` | 이 시간 동안 출력이 없으면 `대기` 로 |
|
|
138
|
+
| `autoDetect` | `true` | 출력·제목 패턴으로 상태 추론 |
|
|
139
|
+
| `showElapsed` | `true` | 경과 시간 표시 |
|
|
140
|
+
| `sortByStatus` | `false` | 사이드바 탭을 상태 우선순위(승인대기 → 오류 → 한도 도달 → 진행중 → 완료 → 대기)로 정렬한다. 같은 상태끼리는 탭 순서 유지. 끄면 순정 탭바와 같은 순서 |
|
|
141
|
+
| `keepRenderingWhenHidden` | `true` | 창이 가려져 있어도 사이드바를 갱신한다. 끄면 상태 변화가 최대 1분까지 늦게 보일 수 있다 |
|
|
142
|
+
| `enterAsLabel` | `true` | Enter 로 프롬프트를 보낼 때 입력창 원문을 작업 라벨로 삼는다 |
|
|
143
|
+
| `labelAsTitle` | `true` | 사이드바 제목 줄에 탭 제목 대신 작업 라벨을 쓴다. Tabby 의 탭 제목 자체는 건드리지 않는다 |
|
|
144
|
+
| `noTabRecovery` | `false` | 기동 시 지난 탭을 복원하지 않는다 — Tabby `recoverTabs` 를 false 로 강제. 복원되는 건 셸뿐이고 안의 Claude 세션은 죽어 있어 의미가 없다 (설정 창에서 켠다) |
|
|
145
|
+
| `notifyChannel` | `true` | 훅이 보낸 상태를 받는 통로(로컬 TCP + 상태 파일). 훅을 설치하면 자동으로 켜진다 |
|
|
146
|
+
| `notifyPort` | `47500` | 그 TCP 포트(127.0.0.1 전용). 물려 있으면 임의 포트로 물러나고 실제 번호는 `%LOCALAPPDATA%\tabby-agentdeck\port` 에 적힌다 |
|
|
147
|
+
| `hookPromptDismissed` | `false` | 기동 시 뜨는 훅 설치 안내를 다시 띄우지 않는다 |
|
|
148
|
+
| `claimCtrlV` | `true` | 기동 시 `agentdeck-paste` 에 `Ctrl-V` 를 넣고 순정 `hotkeys.paste` 에서는 뺀다 |
|
|
149
|
+
| `pasteImageWithCtrlV` | `true` | 클립보드에 이미지만 있으면 텍스트 붙여넣기 대신 이미지 붙여넣기 키를 보낸다 |
|
|
150
|
+
| `imagePasteKey` | `alt-v` | 그때 보낼 키. `ctrl-v`(0x16) 는 Claude Code·Codex 둘 다, `alt-v`(ESC v) 는 Claude Code 전용 |
|
|
151
|
+
| `claimRightClick` | `true` | 우클릭을 플러그인이 처리한다 (Tabby 의 `terminal.rightClick` 은 `off` 로) |
|
|
152
|
+
| `rightClickMenuMs` | `250` | 이 시간 이상 누르면 붙여넣기 대신 컨텍스트 메뉴 |
|
|
153
|
+
| `terminalOpacity` | `75` | 터미널 배경 불투명도(%). 100 미만이면 `tabby-background` 의 배경 이미지가 비친다. 100 = 순정 |
|
|
154
|
+
| `sidebarOpacity` | `75` | 사이드바 / 창 여백 불투명도(%) |
|
|
155
|
+
| `clipBackgroundToTerminal` | `true` | `tabby-background` 이미지를 터미널 영역으로 잘라 사이드바 밑까지 비치지 않게 한다 |
|
|
156
|
+
| `screenWatch` | `true` | 2초마다 화면이 깨졌는지 판정해 `~/.agentdeck-screen.log` 에 기록만 한다 (복구는 하지 않음) |
|
|
157
|
+
| `autoRepairScreen` | `false` | 깨졌다고 판정되면 조용히 화면 복구까지 한다 |
|
|
158
|
+
| `autoRepairMinStreak` | `2` | 깨짐이 이만큼 연속으로 보여야 복구한다 (그리는 도중의 중간 프레임 오탐 방지) |
|
|
159
|
+
| `autoRepairCooldownMs` | `10000` | 자동 복구 후 이만큼은 다시 하지 않는다 |
|
|
160
|
+
| `autoRepairMaxPerTab` | `3` | 한 탭에서 자동 복구 최대 횟수. 0 = 무제한 |
|
|
161
|
+
| `repairHard` | `false` | 화면 복구가 `xterm.reset()` 까지 한다 (스크롤백도 지워진다) |
|
|
162
|
+
| `repairSendRedrawKey` | `true` | 화면 복구 마지막에 `Ctrl+L` 을 보내 전체 재렌더를 시킨다 |
|
|
163
|
+
| `rootProfile` | `false` | 작업 루트 프로필을 만들어 기본 프로필로 삼는다 (설정 창에서 켠다) |
|
|
164
|
+
| `rootProfileName` | `Agent Root` | 그 프로필 이름 |
|
|
165
|
+
| `rootProfileCwd` | `''` | 새 탭이 열릴 경로. 비우면 프로필을 만들지 않는다. 슬래시로 적는다 (예: `D:/Project`) |
|
|
166
|
+
| `rootProfileCommand` | `powershell.exe` | 셸 |
|
|
167
|
+
| `rootProfileArgs` | `-NoLogo -ExecutionPolicy Bypass` | 셸 인자. `Bypass` 는 npm 전역 `.ps1` 래퍼(`claude` 등)가 실행 정책에 막히지 않게 한다 — 그 세션에만 적용 |
|
|
168
|
+
| `rootProfileEnv` | `TERM=xterm-256color`, `COLORTERM=truecolor` | 셸 환경변수 (빠진 것만 채운다) |
|
|
169
|
+
| `alertFlash` | `true` | 창이 뒤에 있을 때 탭이 `승인대기`/`오류`/`한도 도달` 로 넘어가면 작업표시줄 아이콘을 깜빡인다. 창이 포커스를 받으면 멈춘다 |
|
|
170
|
+
| `alertBadge` | `true` | 작업표시줄 아이콘 위에 `승인대기`+`오류`+`한도 도달` 탭 개수를 뱃지(원+숫자)로 얹는다. 0 이면 지운다 |
|
|
171
|
+
| `alertToast` | `false` | 그때 OS 토스트도 띄운다. 누르면 창을 앞으로 가져오고 그 탭을 고른다 |
|
|
172
|
+
|
|
173
|
+
## 알려진 문제
|
|
174
|
+
|
|
175
|
+
### Tabby 1.0.235 에서 새 탭이 열리지 않음
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
Error: ENOENT, node_modules\node-pty\lib\conpty_console_list_agent not found in ...\resources\app.asar
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Tabby 설치본의 패키징 버그로 플러그인과 무관하다. ConPTY 를 끄면 이 경로를 타지 않는다.
|
|
182
|
+
|
|
183
|
+
```yaml
|
|
184
|
+
# %APPDATA%\tabby\config.yaml
|
|
185
|
+
terminal:
|
|
186
|
+
useConPTY: false
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## 라이선스
|
|
190
|
+
|
|
191
|
+
MIT
|
|
192
|
+
|
|
193
|
+
개발 절차·구조·설계 근거·실측 함정은 리포의 `docs/DEVELOPMENT.md`, 회귀 체크리스트는 `docs/REGRESSION.md` 에 있다.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { NgZone } from '@angular/core';
|
|
2
|
+
import { AppService, ConfigService } from 'tabby-core';
|
|
3
|
+
import { WorkStatusService } from './status.service';
|
|
4
|
+
/**
|
|
5
|
+
* 창이 뒤로 가 있을 때의 OS 알림.
|
|
6
|
+
*
|
|
7
|
+
* 사이드바는 창이 보일 때만 의미가 있다. 에이전트 탭을 여섯 개쯤 굴리면서 Slack·VS 를 보고
|
|
8
|
+
* 있으면 어느 탭이 `승인대기` 로 멈춰 있어도 알 길이 없어서, 돌아와 보면 몇 분씩 놀고 있던
|
|
9
|
+
* 일이 잦았다. 그래서 상태가 **`waiting` / `error` 로 넘어가는 순간** 창이 포커스를 잃은
|
|
10
|
+
* 상태면 OS 쪽에 세 가지로 알린다.
|
|
11
|
+
*
|
|
12
|
+
* 1. **작업표시줄 깜빡임** (`flashFrame`) — 창이 포커스를 받으면 끈다. `alertFlash`
|
|
13
|
+
* 2. **작업표시줄 뱃지** — 지금 `waiting`+`error` 인 탭 수를 아이콘 위에 얹는다. Windows 에는
|
|
14
|
+
* `setBadgeCount` 가 없어서 `setOverlayIcon` 에 캔버스로 그린 원+숫자를 넣는다.
|
|
15
|
+
* 전이 순간만이 아니라 상태가 바뀔 때마다 갱신해 실제 개수를 따라간다. `alertBadge`
|
|
16
|
+
* 3. **OS 토스트** (`Notification`) — 기본은 끔. 누르면 창을 앞으로 가져오고 그 탭을 고른다. `alertToast`
|
|
17
|
+
*
|
|
18
|
+
* 창이 앞에 있을 때는 아무것도 하지 않는다 — 사이드바가 이미 보이고 있다.
|
|
19
|
+
* Electron 을 만지는 모든 곳은 try/catch 로 감싼다. 알림이 안 되는 것은 불편이지만
|
|
20
|
+
* 예외가 새어 나가 다른 배선을 죽이는 것은 사고다.
|
|
21
|
+
*/
|
|
22
|
+
export declare class AgentDeckAlertService {
|
|
23
|
+
private app;
|
|
24
|
+
private config;
|
|
25
|
+
private zone;
|
|
26
|
+
private status;
|
|
27
|
+
/** 탭별로 마지막에 본 상태 — "전이" 를 판정하려고 들고 있는다 */
|
|
28
|
+
private last;
|
|
29
|
+
/** flashFrame(true) 를 걸어 둔 상태인가 — 포커스가 오면 끈다 */
|
|
30
|
+
private flashing;
|
|
31
|
+
/** 마지막으로 그린 뱃지 숫자 (0 = 안 그림). 같은 숫자면 다시 그리지 않는다 */
|
|
32
|
+
private badgeShown;
|
|
33
|
+
/** 뱃지 그림 캐시 — key 는 `${count}:${color}` */
|
|
34
|
+
private badgeCache;
|
|
35
|
+
/**
|
|
36
|
+
* 진단/검증용 카운터 — CDP 에서 `__agentdeck.alert` 로 읽는다.
|
|
37
|
+
* `forceUnfocused` 를 true 로 두면 포커스 판정을 건너뛰고 "창이 뒤에 있다" 로 친다
|
|
38
|
+
* (테스트 인스턴스가 앞에 떠 있는 상태에서 알림 경로를 밟아 보려고)
|
|
39
|
+
*/
|
|
40
|
+
debug: {
|
|
41
|
+
flashes: number;
|
|
42
|
+
badgeCount: number;
|
|
43
|
+
badgeDraws: number;
|
|
44
|
+
toasts: number;
|
|
45
|
+
transitions: number;
|
|
46
|
+
lastFocused: boolean;
|
|
47
|
+
forceUnfocused: boolean;
|
|
48
|
+
};
|
|
49
|
+
constructor(app: AppService, config: ConfigService, zone: NgZone, status: WorkStatusService);
|
|
50
|
+
init(): void;
|
|
51
|
+
private setup;
|
|
52
|
+
/**
|
|
53
|
+
* 상태가 바뀔 때마다 — 뱃지는 항상 실제 개수로 맞추고,
|
|
54
|
+
* 알림 상태로 **새로 들어온** 탭이 있고 창이 뒤에 있으면 깜빡임/토스트를 낸다
|
|
55
|
+
*/
|
|
56
|
+
private onChanged;
|
|
57
|
+
private countAlerting;
|
|
58
|
+
/** `@electron/remote` 의 현재 창. 못 잡으면 null — 호출부는 전부 null 을 감안한다 */
|
|
59
|
+
private win;
|
|
60
|
+
private nativeImage;
|
|
61
|
+
/**
|
|
62
|
+
* 창이 앞에 있나. Electron 의 판정을 우선하고(devtools 를 따로 띄워도 본창 기준으로 본다),
|
|
63
|
+
* remote 를 못 잡으면 DOM 의 `document.hasFocus()` 로 대신한다
|
|
64
|
+
*/
|
|
65
|
+
private isFocused;
|
|
66
|
+
private flash;
|
|
67
|
+
private stopFlash;
|
|
68
|
+
/**
|
|
69
|
+
* 작업표시줄 아이콘 위의 숫자를 지금 개수로 맞춘다. 0 이면 지운다.
|
|
70
|
+
* `alertBadge` 가 꺼져 있으면 그려 둔 것이 있을 때만 지우고 끝낸다
|
|
71
|
+
*/
|
|
72
|
+
private updateBadge;
|
|
73
|
+
/**
|
|
74
|
+
* 원 위에 숫자를 얹은 오버레이 이미지. 오류 탭이 하나라도 있으면 오류색, 아니면 승인대기색.
|
|
75
|
+
* Windows 오버레이는 16px 기준이라 16@1x + 32@2x 두 표현을 넣는다 (고배율에서 흐려지지 않게).
|
|
76
|
+
* `addRepresentation` 을 못 쓰는 빌드면 32px 하나로 물러난다
|
|
77
|
+
*/
|
|
78
|
+
private badgeImage;
|
|
79
|
+
/** 오프스크린 canvas 에 원+숫자를 그려 data URL 로 돌려준다 */
|
|
80
|
+
private drawBadge;
|
|
81
|
+
/** OS 토스트. 누르면 창을 앞으로 가져오고 그 탭을 고른다 */
|
|
82
|
+
private toast;
|
|
83
|
+
/** 토스트 tag 용 탭 식별자 — 객체 자체는 문자열이 안 되니 인덱스로 대신한다 */
|
|
84
|
+
private tabKey;
|
|
85
|
+
/** deck.service 와 같은 파일(`~/.agentdeck-diag.log`)에 남긴다. 실패해도 동작에는 영향 없다 */
|
|
86
|
+
private diag;
|
|
87
|
+
}
|
package/dist/api.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 사이드바에 표시되는 작업 상태.
|
|
3
|
+
*
|
|
4
|
+
* `limited`(한도 도달)는 에이전트가 사용량 한도에 걸려 턴이 끊긴 상태다 — Claude Code 의
|
|
5
|
+
* `StopFailure` 훅이 `error: rate_limit` 로 알려준다. 사람이 승인할 것은 없고 리셋 시각까지 기다려야
|
|
6
|
+
* 하므로 승인대기와는 구분해서 보여준다 (2026-09-07 요청).
|
|
7
|
+
*/
|
|
8
|
+
export type WorkStatus = 'idle' | 'running' | 'waiting' | 'limited' | 'done' | 'error';
|
|
3
9
|
export interface StatusStyle {
|
|
4
10
|
icon: string;
|
|
5
11
|
label: string;
|
|
@@ -12,6 +18,14 @@ export interface TabState {
|
|
|
12
18
|
status: WorkStatus;
|
|
13
19
|
/** 작업 이름 (사용자 지정 또는 훅이 보낸 값) */
|
|
14
20
|
label: string;
|
|
21
|
+
/**
|
|
22
|
+
* 상태의 부연 — 훅이 보낸 문구를 줄인 것.
|
|
23
|
+
* - waiting: 승인 이유 (예: `Bash 권한`, `입력 대기`) → 배지 `⏸ 승인대기 · Bash 권한`
|
|
24
|
+
* - limited: 리셋 시각 (예: `12pm 리셋`) → 배지 `⛔ 한도 도달 · 12pm 리셋`
|
|
25
|
+
* - error: StopFailure 의 error 코드 (예: `overloaded`)
|
|
26
|
+
* 그 밖의 상태로 바뀌면 비운다 (status.service REASON_STATUSES)
|
|
27
|
+
*/
|
|
28
|
+
reason: string;
|
|
15
29
|
/** 상태가 마지막으로 바뀐 시각 */
|
|
16
30
|
since: number;
|
|
17
31
|
/** true = 수동/훅 지정. 자동 감지가 덮어쓰지 않는다 */
|
package/dist/bind.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 훅 보고를 어느 탭에 붙일지 고르는 순수 규칙 — Angular/Tabby 에 기대지 않아 단위 테스트가 된다.
|
|
3
|
+
*
|
|
4
|
+
* 왜 PID 인가 — 예전 규칙 "처음 보고할 때의 활성 탭" 은 사용자가 방금 프롬프트를 넣은 탭이
|
|
5
|
+
* 곧 활성 탭이라는 가정인데, 파일 폴링이 400ms 마다 못 묶은 보고를 다시 시도하는 탓에
|
|
6
|
+
* **끝난 세션의 done 이 다음에 열리는 빈 탭을 붙잡았다** (2026-09-02 실측: 작업 중인 탭이
|
|
7
|
+
* "완료" 로, 그 탭의 진짜 세션은 주인이 있다며 거절돼 running 이 버려졌다).
|
|
8
|
+
*
|
|
9
|
+
* 훅은 자기 조상 프로세스 PID 를 함께 보낸다 — claude.exe → 탭 셸 → Tabby.exe 순서다.
|
|
10
|
+
* 탭마다 pty 가 띄운 셸 PID 를 알고 있으면 어느 탭의 보고인지 추측 없이 확정된다.
|
|
11
|
+
*/
|
|
12
|
+
export type BindMode = 'pid' | 'pid-miss' | 'legacy';
|
|
13
|
+
export interface BindPick<T> {
|
|
14
|
+
tab: T | null;
|
|
15
|
+
/**
|
|
16
|
+
* pid — 조상 PID 가 어떤 탭의 셸 PID 와 맞았다 (확정)
|
|
17
|
+
* pid-miss — pids 도 왔고 탭 PID 표도 있는데 맞는 탭이 없다. 활성 탭으로 추측하지 **않는다**
|
|
18
|
+
* (탭 PID 표가 아직 안 채워진 것일 수 있으니 호출자는 다음 폴링에 다시 본다)
|
|
19
|
+
* legacy — pids 가 없거나(옛 훅·수동 호출) 탭 PID 를 하나도 모른다. 호출자가 예전 활성 탭 규칙을 쓴다
|
|
20
|
+
*/
|
|
21
|
+
mode: BindMode;
|
|
22
|
+
}
|
|
23
|
+
export declare function pickTabByPids<T>(pids: number[] | undefined, tabPids: Map<T, number[]>): BindPick<T>;
|
package/dist/claudeHooks.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ export declare function notifyScriptPath(): string;
|
|
|
4
4
|
/** 이 환경에서 훅을 걸 수 있나 — 통보 스크립트가 PowerShell 이라 Windows 전용이다 */
|
|
5
5
|
export declare function hooksSupported(): boolean;
|
|
6
6
|
/**
|
|
7
|
-
* 우리 훅이
|
|
7
|
+
* 우리 훅이 PLAN 의 모든 이벤트에 걸려 있나 — 파일을 읽지 않는 순수 판정.
|
|
8
|
+
* 이벤트가 늘어난 버전으로 올라오면 옛 설치는 "설치 안 됨" 으로 보인다 — 설정 창에서 설치를 다시 누르면 된다.
|
|
8
9
|
* 파일 접근과 분리해 둔 이유는 이 판단을 테스트로 묶어 두기 위해서다.
|
|
9
10
|
*/
|
|
10
11
|
export declare function isMerged(settings: any): boolean;
|