tabby-agentdeck 1.1.2 → 1.1.3

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
@@ -1,62 +1,71 @@
1
1
  # tabby-agentdeck
2
2
 
3
- Tabby 터미널 플러그인. **Claude Code · Codex 같은 AI 에이전트 CLI 를 여러 탭에 띄워 놓고 쓰는 사람**을 위한 것이다.
3
+ [![npm](https://img.shields.io/npm/v/tabby-agentdeck)](https://www.npmjs.com/package/tabby-agentdeck)
4
+ [![downloads](https://img.shields.io/npm/dm/tabby-agentdeck)](https://www.npmjs.com/package/tabby-agentdeck)
5
+ [![CI](https://github.com/jghwang2/tabby-agentdeck/actions/workflows/ci.yml/badge.svg)](https://github.com/jghwang2/tabby-agentdeck/actions/workflows/ci.yml)
6
+ [![license](https://img.shields.io/npm/l/tabby-agentdeck)](LICENSE)
4
7
 
5
- 터미널 뷰포트를 **4:3 으로 고정**하고 남는 공간에 **세션 목록 + 작업 상태 사이드바**를 그린다.
6
- 어느 에이전트가 돌고 있고 어느 쪽이 내 입력을 기다리는지 탭을 옮겨 다니지 않고 한눈에 본다.
7
- 에이전트가 만든 문서·그림은 **미리보기 패널**에서 터미널 옆에 띄워 확인한다.
8
- 거기에 에이전트 CLI 가 터미널에서 겪는 문제들(이미지 붙여넣기, 줄바꿈 키, pty 폭 어긋남)을 같이 손봐 둔다.
8
+ **[Website](https://jghwang2.github.io/tabby-agentdeck/) · [User guide](https://jghwang2.github.io/tabby-agentdeck/guide/) · [한국어 README](README.ko.md) · [한국어 사용 설명서](https://jghwang2.github.io/tabby-agentdeck/guide/ko.html)**
9
+
10
+ A [Tabby](https://tabby.sh) terminal plugin for **people who keep Claude Code, Codex and Gemini CLI open in several tabs at once**.
11
+
12
+ It pins the terminal viewport to **4:3** and spends the leftover space on a **session deck with live status**.
13
+ You see which agent is running and which one is waiting for you without clicking through tabs.
14
+ Documents and images the agents produce open in a **preview panel** beside the terminal.
15
+ On top of that it fixes the things agent CLIs get wrong inside a terminal — image paste, newline keys, pty width drift.
9
16
 
10
17
  ```
11
18
  ┌────────────────────┬──────────────────┬──────────────────┐
12
19
  │ │ note.md + ⟳ ✕ │ AGENT DECK 4 │
13
- │ 터미널 (4:3 기준) ├──────────────────┼──────────────────┤
14
- │ │ note.md shot.png│ ● 진행중 리팩터링 │
15
- │ Tabby 순정 탭바는 ├──────────────────┤ ⏸ 승인대기 재빌드 │
16
- │ 숨김 │ # 제목 │ ✔ 완료 테스트 │
17
- │ │ 본문이 그려진다 │ ○ 대기 │
18
- │ │ [그림] ├──────────────────┤
19
- │ │ 742 B · 방금 │ + 새 탭 │ 설정 │
20
+ │ terminal (4:3) ├──────────────────┼──────────────────┤
21
+ │ │ note.md shot.png│ ● running refactor│
22
+ │ Tabby's own tab ├──────────────────┤ ⏸ waiting rebuild │
23
+ │ bar is hidden │ # Title │ ✔ done tests │
24
+ │ │ body is rendered │ ○ idle │
25
+ │ │ [image] ├──────────────────┤
26
+ │ │ 742 B · just now │ + new tab │ config│
20
27
  └────────────────────┴──────────────────┴──────────────────┘
21
- 터미널 미리보기 패널 세션 목록
28
+ terminal preview panel session deck
22
29
  ```
23
30
 
24
- Windows 에서 만들고 검증했다. 상태 통보 훅은 PowerShell 스크립트라 Windows 전용이고, 그 외 기능은 플랫폼을 가리지 않는다.
31
+ Built and verified on Windows. The status-notification hook is a PowerShell script and is therefore Windows-only;
32
+ everything else is platform-agnostic but has not been exercised elsewhere.
33
+ If you run Tabby on macOS or Linux, an [issue](https://github.com/jghwang2/tabby-agentdeck/issues) saying what broke is genuinely useful.
25
34
 
26
- ## 기능
35
+ ## Features
27
36
 
28
- | | 동작 |
37
+ | | What it does |
29
38
  |---|---|
30
- | **4:3 기준 폭 계산** | 창 높이에서 폭을 역산해 터미널을 고정폭으로 만든다. 남는 폭은 사이드바가 갖고, 그러고도 남으면 터미널이 흡수한다 |
31
- | **사이드바 탭 관리** | 클릭=선택, `×`=닫기, 더블클릭=작업 이름 편집, 우클릭=상태 직접 지정 |
32
- | **검색 · 상태 필터** | 헤더 아래 검색창으로 제목·작업이름·작업폴더를 좁히고, 상태 칩을 눌러 그 상태만 본다. Esc 로 해제 |
33
- | **순서 바꾸기** | 사이드바 줄을 끌어 옮긴다(순정 탭바 순서도 함께). 목록 끝에 커서를 대고 있으면 **저절로 흘러가** 화면 밖 자리로도 한 손짓에 옮긴다. 상태순 정렬이 켜져 있으면 막고 이유를 알린다 |
34
- | **키보드로 다루기** | `Ctrl+Shift+L` 로 목록에 들어가 `↑↓` 로 훑고 Enter 로 고른다. **훑는 동안 탭은 바뀌지 않는다** — 지나가는 탭의 출력이 화면을 채우지 않게 포커스와 선택을 갈랐다. `Ctrl+W` 로 지금 탭(목록에서는 포커스 줄)을 닫는다 |
35
- | **결과물 미리보기** | 에이전트가 만진 md · 이미지 · 표(csv/tsv) · 코드를 터미널 옆 패널에서 본다. 화면에 찍힌 경로를 스스로 주우므로 Claude Code · Codex · Gemini 를 가리지 않는다 |
36
- | **끌어다 놓기** | 파일을 패널에 놓으면 바로 열리고, **터미널 위에 놓으면** `패널에 띄우기` / `경로 붙여넣기` 를 물어본다 |
37
- | **변경 보기** | 같은 패널의 `변경` 탭이 작업트리의 `git diff` 를 보여준다 — 파일 목록 · `+N -M` · 줄번호 붙은 유니파이드 diff. 누가 고쳤는지와 무관하게 성립한다 |
38
- | **`파일:라인` 참조** | diff 나 코드 보기에서 줄을 누르면 그 위치를 터미널에 넣는다(Shift+클릭=범위). "이 줄 고쳐" 를 타이핑 없이 |
39
- | **스테이지 · 커밋** | `변경` 탭에서 파일 딱지를 눌러 `git add`/`unstage` 하고, 메시지를 적어 커밋한다. **두 번 눌러야 커밋된다**(첫 누름은 확인 대기) |
40
- | **세션 그룹** | 탭을 프로젝트별로 묶고 접는다. 경계는 저장소 루트(`.git` 등)를 위로 훑어 자동으로 잡으므로 설정이 없다. 그룹이 하나뿐이면 헤더를 그리지 않고 순서도 건드리지 않는다 |
41
- | **지난 세션 이어받기** | 그룹 안 `⟲ 지난 세션` 을 펴면 **닫힌 Claude Code 세션**이 사람이 친 프롬프트로 보인다. 누르면 그 세션의 작업 폴더에서 `claude --resume` 으로 대화가 되살아난다 |
42
- | **한글 조합 보정** | 조합 중인 음절이 커서를 따라가거나 새 줄로 내려가지 않게, pty 에 쓰기 전에 조합이 끝나기를 기다린다 |
43
- | **에이전트 프로필** | 어느 CLI 가 도는 탭인지 알아내고(프로세스 → 제목) 그에 맞는 규칙을 쓴다. 새 CLI 지원은 프로필 한 덩이 추가로 끝난다 |
44
- | **마우스 도킹** | 헤더를 끌어 좌/우/상/하 어느 가장자리에나 붙이고, 경계선을 끌어 크기를 바꾼다 |
45
- | **작업 상태** | 진행중 / 승인대기 / 한도 도달 / 완료 / 오류 / 대기 를 색·배지·경과시간으로 표시. 훅이 없어도 화면 문구로 판정하고, **왜 멈췄는지**(승인 대상·한도)를 배지에 붙인다 |
46
- | **상태별 집계** | 헤더 오른쪽에 상태별 탭 수를 `⏸ 2 ● 3 ○ 1` 처럼 급한 순서(승인대기 → 오류 → 한도 도달 → 진행중 → 완료 → 대기)로 보여준다. `sortByStatus` 를 켜면 같은 순서로 탭이 정렬된다 |
47
- | **서브에이전트 개수** | 그 세션이 백그라운드 에이전트를 몇 개 돌리고 있는지 줄에 `❖3` 으로 보인다. 대화 기록에서 **띄운 것과 끝난 것을 대조**해 세므로 훅이 알려주지 않아도 맞는다 |
48
- | **작업 이름** | Enter 로 프롬프트를 보내는 순간 입력창 원문을 읽어 라벨로 삼는다 |
49
- | **Claude Code 훅 연동** | 설정 창에서 한 번 설치하면 에이전트가 상태를 직접 알려준다 (선택) |
50
- | **기본 프로필** | 새 탭을 항상 지정한 작업 루트에서 연다 |
51
- | **자동 업데이트** | 기동할 때 npm 을 보고 새 버전이 있으면 물어본 뒤, Tabby 를 닫고 → 설치하고 → **스스로 다시 켠다**. 개발 설치(소스 링크)에는 손대지 않는다 |
52
- | **입력 보정** | `Ctrl+V` 이미지 붙여넣기, `Ctrl+Enter`/`Shift+Enter` 줄바꿈, 우클릭 복사/붙여넣기 |
53
- | **화면 복구** | 깨진 TUI 의 **입력창 잔상만** 지우고 크기를 맞춰 다시 그리게 한다 — 보고 있던 대화는 건드리지 않는다. 사이드바 `↻` / 탭 우클릭 / `agentdeck-repair` 핫키 |
54
-
55
- ## 설치
56
-
57
- **Tabby 안에서**: 설정 → 플러그인 → `agentdeck` 검색 → 설치 → Tabby 재시작.
58
-
59
- **소스에서**:
39
+ | **4:3 width** | Derives terminal width from window height and fixes it. Leftover width goes to the sidebar; whatever is still left is absorbed by the terminal |
40
+ | **Sidebar tab management** | Click to select, `×` to close, double-click to rename the task, right-click to set status by hand |
41
+ | **Search · status filter** | The search box narrows by title, task name and working folder; status chips keep only one state. `Esc` clears |
42
+ | **Reordering** | Drag a row to move it (Tabby's own tab order follows). Hold at the edge and the list **scrolls by itself**, so off-screen positions are one gesture away. Blocked with an explanation while status sorting is on |
43
+ | **Keyboard control** | `Ctrl+Shift+L` enters the list; `↑↓` walks it and Enter picks. **The tab does not change while you walk** — focus and selection are separate so passing output does not flood the screen. `Ctrl+W` closes the current tab (the focused row when the list has the keyboard) |
44
+ | **Output preview** | Markdown, images, tables (csv/tsv) and code the agent touched, in a panel beside the terminal. It picks up paths printed on screen, so Claude Code, Codex and Gemini all work |
45
+ | **Drag and drop** | Drop a file on the panel and it opens. **Drop it on the terminal** and you are asked: open in panel / paste the path |
46
+ | **Diff view** | The `Changes` tab of the same panel shows `git diff` for the working tree — file list, `+N -M`, unified diff with line numbers. It holds regardless of who made the change |
47
+ | **`file:line` reference** | Click a line in a diff or code view and that position is typed into the terminal (Shift+click for a range). "Fix this line" without typing it out |
48
+ | **Stage · commit** | Click a file tag to `git add`/unstage, write a message and commit. **It takes two presses** (the first one asks to confirm) |
49
+ | **Session groups** | Tabs group by project. The boundary is found by walking up for a repository root (`.git` and friends), so there is nothing to configure. With a single group no header is drawn and order is left alone |
50
+ | **Resume a past session** | `⟲ Past sessions` in a group lists **closed Claude Code sessions by the prompt you typed**. Click one and the conversation comes back with `claude --resume` in its own working folder |
51
+ | **IME composition guard** | Waits for composition to settle before writing to the pty, so a half-composed syllable no longer follows the cursor or drops onto a new line |
52
+ | **Agent profiles** | Works out which CLI is running in a tab (process → title) and applies that agent's rules. Supporting a new CLI is one profile block |
53
+ | **Mouse docking** | Drag the header to any edge (left/right/top/bottom); drag the divider to resize |
54
+ | **Status** | running / waiting / rate limited / done / error / idle, as colour, badge and elapsed time. It judges from screen text even with no hook, and a badge says **why** it stopped (what needs approval, which limit) |
55
+ | **Per-status counts** | The header shows counts in urgency order — `⏸ 2 ● 3 ○ 1`. Turn on `sortByStatus` and tabs sort the same way |
56
+ | **Subagent count** | How many background agents that session is running, as `❖3`. Counted by **matching launches against completions** in the transcript, so it is right even when no hook reports |
57
+ | **Task names** | The moment you press Enter, the text in the input box becomes the row's label |
58
+ | **Claude Code hook** | Install once from the settings window and the agent reports status directly (optional) |
59
+ | **Root profile** | Always open new tabs in a chosen working root |
60
+ | **Auto-update** | On startup it asks npm for a newer version, and with your consent closes Tabby, installs, and **starts itself back up**. Development installs (source links) are left alone |
61
+ | **Input fixes** | `Ctrl+V` image paste, `Ctrl+Enter`/`Shift+Enter` newline, right-click copy/paste |
62
+ | **Screen repair** | Clears **only the input-box remnant** of a broken TUI and re-syncs the size — the conversation you were reading is untouched. Sidebar `↻`, tab right-click, or the `agentdeck-repair` hotkey |
63
+
64
+ ## Install
65
+
66
+ **Inside Tabby**: Settings → Plugins → search `agentdeck` → Install → restart Tabby.
67
+
68
+ **From source**:
60
69
 
61
70
  ```powershell
62
71
  npm install
@@ -64,481 +73,465 @@ npm run build
64
73
  powershell -NoProfile -ExecutionPolicy Bypass -File install.ps1
65
74
  ```
66
75
 
67
- `install.ps1` 은 Tabby 플러그인 디렉토리(`%APPDATA%\tabby\plugins\node_modules\tabby-agentdeck`)에
68
- 이 폴더를 가리키는 junction 을 건다. 소스를 고치고 `npm run build` 하면 Tabby 재시작으로 반영된다.
76
+ `install.ps1` puts a junction in Tabby's plugin directory (`%APPDATA%\tabby\plugins\node_modules\tabby-agentdeck`)
77
+ pointing at this folder. Edit the source, run `npm run build`, restart Tabby.
69
78
 
70
- ### 자동 업데이트
79
+ ### Auto-update
71
80
 
72
- 기동하고 8초 뒤, npm 레지스트리에 `tabby-agentdeck` 의 최신 버전을 묻는다.
73
- 새 버전이 있으면 **물어본다** — `지금 업데이트` / `나중에` / `다시 묻지 않기`.
74
- 승낙하면 이렇게 흐른다:
81
+ Eight seconds after startup it asks the npm registry for the latest `tabby-agentdeck`.
82
+ If there is a newer one it **asks** — `Update now` / `Later` / `Skip this version`.
83
+ Say yes and it goes:
75
84
 
76
85
  ```
77
- Tabby 가 닫힌다 → (밖에서) npm install → Tabby 가 스스로 다시 켜진다
86
+ Tabby closes → (outside) npm install → Tabby starts itself back up
78
87
  ```
79
88
 
80
- **사람이 할 일은 처음 한 번 누르는 것뿐이다.** 설치가 끝나면 알아서 다시 켜진다.
81
- 설치가 실패해도 Tabby 는 반드시 다시 켠다 — 업데이트를 고르느라 터미널을 잃는 일은 없어야 한다.
82
- 기록은 `%LOCALAPPDATA%\tabby-agentdeck\update.log` 에 남는다.
89
+ **The only human step is that first click.** It comes back on its own when the install finishes,
90
+ and it comes back even if the install fails — losing your terminals to an update must never happen.
91
+ The record is in `%LOCALAPPDATA%\tabby-agentdeck\update.log`.
83
92
 
84
- | 설정 | 기본값 | |
93
+ | Setting | Default | |
85
94
  |---|---|---|
86
- | `autoUpdate` | `true` | 끄면 확인도 하지 않는다 |
87
- | `updateCheckIntervalHours` | `6` | 기동마다 묻지 않는다 |
88
- | `updateRegistry` | `https://registry.npmjs.org` | 사내 미러를 쓰면 바꾼다 |
89
- | `updateSkipVersion` | — | `다시 묻지 않기` 를 누른 버전. **그 버전만** 건너뛰고 다음 버전은 다시 묻는다 |
90
-
91
- > **왜 Tabby 를 닫고 까나.** 두 가지 때문이다. ① 돌고 있는 플러그인은 자기를 갈아끼울 수 없다 —
92
- > Tabby 는 기동할 때 `dist/index.js` 를 한 번 읽어 메모리에 올리므로, 디스크를 바꿔도 돌던 코드는
93
- > 옛것 그대로다. ② Windows 는 로드된 파일을 잡고 있어서, 떠 있는 동안 npm 이 그 폴더를 지우려 들면
94
- > 반쯤 지운 채 실패할 수 있다 — 플러그인이 깨진 채 남는 것이 가장 나쁜 결과다.
95
- > 그래서 설치는 임시 폴더로 떼어낸 `updater/agentdeck-update.ps1` 이 **Tabby 종료를 확인한 뒤** 한다.
96
- > 기다리는 대상은 **업데이트를 건 그 인스턴스의 메인 프로세스 PID** 하나다 — 이름으로 전부 세면
97
- > 다른 Tabby 창 하나 때문에 업데이트가 영영 안 된다.
98
-
99
- > **개발 설치에는 설치하지 않는다.** 플러그인 폴더의 `tabby-agentdeck` 이 소스 트리를 가리키는
100
- > 링크일 때(`install.ps1` 로 깐 개발 환경), 거기에 `npm install` 이 돌면 **작업 중인 소스를 덮어쓴다.**
101
- > `src/`·`.git`·`webpack.config.js` 중 하나라도 보이거나 항목이 링크면 새 버전이 있다는 것만 알리고
102
- > 손대지 않는다 (판정은 `update.ts` 의 `canSelfUpdate`).
103
-
104
- ### 버전은 한 곳에만 적는다
105
-
106
- **`package.json` 의 `version` 이 유일한 출처다.** 나머지는 전부 거기서 파생된다 —
107
- `npm run build` 가 매번 `tools/sync-version.js` 를 먼저 돌려(`prebuild`) `package-lock.json` 과
108
- 사용설명서(`docs/guide/index.html` 의 `<span class="ad-version">`)를 맞추고,
109
- 진단 로그의 `plugin=` 은 런타임에 `package.json` 을 읽는다(`diag.ts` `pluginVersion`).
110
-
111
- ```powershell
112
- npm run sync-version # 지금 맞추기
113
- node tools/sync-version.js --check # 어긋난 곳만 알리기 (어긋나면 종료코드 1)
114
- ```
95
+ | `autoUpdate` | `true` | Off means it does not even check |
96
+ | `updateCheckIntervalHours` | `6` | So it does not ask on every startup |
97
+ | `updateRegistry` | `https://registry.npmjs.org` | Change for an internal mirror |
98
+ | `updateSkipVersion` | — | The version you pressed `Skip` on. **Only that one** is skipped; the next release asks again |
115
99
 
116
- `test/version.test.js` 가 어긋남을 잡으므로 빌드를 안 거친 수정도 `npm test` 에서 걸린다.
117
- **문서·주석의 `0.18.0 부터 …` 같은 이력 표기는 대상이 아니다** — 그건 "지금 버전" 이 아니라
118
- 그 기능이 들어온 시점이라 갱신하면 오히려 거짓이 된다.
100
+ > **Why close Tabby to install.** Two reasons. ① A running plugin cannot swap itself out — Tabby reads
101
+ > `dist/index.js` once at startup, so changing the disk leaves the running code as it was. ② Windows holds
102
+ > loaded files open, so an npm install against that folder while Tabby is up can fail half-deleted — a
103
+ > broken plugin is the worst outcome. So the install is done by `updater/agentdeck-update.ps1`, copied out
104
+ > to a temp folder, **after it confirms Tabby has exited**. It waits on the main process PID of the instance
105
+ > that started the update — counting by name would let one other Tabby window block updates forever.
119
106
 
120
- > 이 규칙이 생긴 이유: 2026-09-11 에 같은 버전을 네 곳이 각자 적고 있었고 **전부 달랐다**
121
- > (`package.json` 1.0.0 / `package-lock.json` 0.3.0 / 사용설명서 0.17.0 / 커밋된 값 0.17.0).
107
+ > **Development installs are left alone.** When `tabby-agentdeck` in the plugin folder is a link to a source
108
+ > tree (an `install.ps1` setup), running `npm install` there would **overwrite the source you are working on**.
109
+ > If `src/`, `.git` or `webpack.config.js` is visible, or the entry is a link, it only reports that a new
110
+ > version exists (the check is `canSelfUpdate` in `update.ts`).
122
111
 
123
- ## 작업 이름과 상태
112
+ ## Task names and status
124
113
 
125
- 사이드바 한 줄은 **작업 이름(라벨)** 과 **상태 배지** 로 이루어진다.
126
- 둘 다 **설정 없이 플러그인만으로 돈다.** 더 정확하게 하려면 Claude Code 훅을 건다.
114
+ A sidebar row is a **task name (label)** and a **status badge**.
115
+ Both work **with the plugin alone, no configuration**. Install the Claude Code hook to make them exact.
127
116
 
128
- ### 작업 이름
117
+ ### Task names
129
118
 
130
- Enter 로 프롬프트를 보내는 그 순간, 화면에 그려져 있는 입력창(`❯ ...`, `> ...`)을 읽어 40자로 잘라 라벨에 넣는다.
131
- 붙여넣기·↑ 히스토리·IME 로 들어온 글자도 화면에 그려진 대로 잡힌다.
132
- Shift+Enter / Ctrl+Enter 는 줄바꿈이라 라벨을 바꾸지 않고, 입력창 머리를 못 찾으면(일반 셸, y/n 확인 등) 라벨을 그대로 둔다.
119
+ The moment you press Enter, it reads the input box drawn on screen (`❯ ...`, `> ...`) and takes 40 characters as the label.
120
+ Text that arrived by paste, `↑` history or IME is caught as drawn.
121
+ Shift+Enter / Ctrl+Enter are newlines and do not change the label; if no input-box head is found (a plain shell, a y/n prompt) the label is left as it was.
133
122
 
134
- ### 상태
123
+ ### Status
135
124
 
136
- - **자동 감지(기본)**: PTY 출력이 흐르면 `진행중`, `idleAfterMs`(기본 2.5초) 동안 조용하면 `대기`.
137
- `Do you want to`, `❯ 1. Yes`, `(y/n)` 같은 패턴이 보이면 `승인대기`. Claude Code 가 제목에 넣는 스피너도 진행중으로 읽는다.
138
- `승인대기` 인 탭에 `esc to interrupt` 같은 작업 중 문구가 다시 보이면 사람이 승인한 것으로 보고 `진행중` 으로 올린다 —
139
- 훅이 고정한 탭에도 적용된다 (승인 뒤 첫 훅은 도구가 끝난 뒤라, 긴 빌드를 승인하면 그동안 승인대기에 박혀 있었다).
140
- - **Claude Code 훅(권장)**: 설정 → AgentDeck → "상태 통보 훅" 설치. `~/.claude/settings.json` 의
141
- UserPromptSubmit / Notification / PostToolUse / PostToolUseFailure / PermissionDenied / Stop / StopFailure 에 통보 스크립트를 건다.
142
- 다른 훅은 건드리지 않고 쓰기 전에 백업을 남긴다. 0.3.0 에서 이벤트가 늘었으므로 옛 설치는 "설치 안 됨" 으로 보인다 — 설치를 다시 누르면 된다.
143
- 에이전트가 "지시를 받았다 / 승인을 기다린다 / 도구가 돌았다(=승인됐다) / 끝났다 / 실패로 끝났다" 를 직접 알려주므로 판정이 흔들리지 않는다. 설정 창의 "제거" 로 되돌린다.
144
- 승인대기에는 이유(예: `Bash 권한`, `입력 대기`)가 함께 표시된다 — `⏸ 승인대기 · Bash 권한`. 상태가 바뀌면 이유는 사라진다.
145
- - **한도 도달**: Claude Code 가 사용량 한도(세션/주간)에 걸려 턴이 끊기면 `StopFailure` 훅이 `error: rate_limit` 로 알려주고
146
- 사이드바는 `⛔ 한도 도달 · 12pm 리셋` 처럼 리셋 시각과 함께 보여준다. 승인할 것이 없는 상태라 승인대기와 구분한다.
147
- 한도 외의 실패(overloaded, server_error …)는 `✖ 오류 · overloaded` 로 표시된다. 한도가 풀려 세션이 이어지면(다음 프롬프트·도구 실행) 진행중으로 돌아온다.
148
- 훅 보고는 플러그인이 탭 셸에 심은 `AGENTDECK_TAB` 환경변수로 어느 탭인지 확정한다
149
- (0.2.2 이전에 열린 탭·재시작으로 복원된 탭은 프로세스 계보로 폴백).
125
+ - **Auto-detection (default)**: PTY output flowing means `running`; silence for `idleAfterMs` (2.5s default) means `idle`.
126
+ Patterns like `Do you want to`, `❯ 1. Yes` and `(y/n)` mean `waiting`. The spinner Claude Code puts in the title also reads as running.
127
+ If a `waiting` tab shows working text again (`esc to interrupt`), it is taken as approved and lifted back to `running` —
128
+ this applies to hook-pinned tabs too, because the first hook after an approval only arrives when the tool finishes, so approving a long build used to leave the row stuck on waiting.
129
+ - **Claude Code hook (recommended)**: Settings → AgentDeck → "status notification hook". It wires a notify script into
130
+ UserPromptSubmit / Notification / PostToolUse / PostToolUseFailure / PermissionDenied / Stop / StopFailure in `~/.claude/settings.json`.
131
+ Other hooks are untouched and a backup is written first. The event set grew in 0.3.0, so older installs read as "not installed" — press install again.
132
+ The agent then states directly that it was given an instruction, is waiting for approval, ran a tool (= was approved), finished, or failed — so the reading never wobbles. "Remove" in the settings window reverts it.
133
+ Waiting rows carry the reason: `⏸ waiting · Bash permission`. The reason disappears when the status changes.
134
+ - **Rate limited**: when Claude Code hits a session or weekly usage limit the turn is cut short, `StopFailure` reports `error: rate_limit`,
135
+ and the sidebar shows the reset time — `⛔ rate limited · resets 12pm`. There is nothing to approve, so it is kept distinct from waiting.
136
+ Other failures (overloaded, server_error …) show as `✖ error · overloaded`. When the limit lifts and the session continues, it returns to running.
137
+ Hook reports are tied to a tab by the `AGENTDECK_TAB` environment variable the plugin plants in the tab's shell
138
+ (tabs opened before 0.2.2, and tabs restored on restart, fall back to the process ancestry).
150
139
 
151
- ### 어느 에이전트인지 알아내는 법
140
+ ### Working out which agent is running
152
141
 
153
- 탭마다 **어떤 CLI 가 도는지** 알아내고(자식 프로세스 이름 → 안 잡히면 탭 제목), 그 에이전트의 규칙을 쓴다.
154
- 지금 아는 것은 Claude Code · Codex CLI · Gemini CLI 셋이고, 새 CLI 는 프로필 한 덩이를 더하면 된다.
142
+ For each tab it works out **which CLI is running** (child process name, falling back to the tab title) and applies that agent's rules.
143
+ It knows Claude Code, Codex CLI and Gemini CLI; a new CLI is one more profile block.
155
144
 
156
- 프로필이 정하는 것 — 상태 문구(대기·작업중), 제목 스피너, **이미지 붙여넣기 키**(Claude=`ESC v` / Codex=`0x16`),
157
- 입력창 머리글자. 셸만 떠 있는 탭은 `알 수 없음` 이고, 그때는 아는 규칙을 모두 합쳐 판정한다.
145
+ A profile decides: status phrases (idle/working), the title spinner, the **image-paste key**
146
+ (Claude = `ESC v`, Codex = `0x16`), and the input-box head character.
147
+ A tab with only a shell in it is `unknown`, and there every known rule is combined.
158
148
 
159
- > **관측된 값만 좁게 쓴다.** Codex·Gemini 의 화면 문구는 이 리포에서 관측된 바가 없어, 그 두 에이전트는
160
- > 상태 판정에 합집합(= 예전과 같은 규칙)을 쓴다. 프로필을 붙였다는 이유로 판정이 예전보다 나빠지면
161
- > 개선이 아니기 때문이다. 실측이 생기면 그 프로필의 `patternsProven` 을 켜면 된다.
149
+ > **Only observed values are used narrowly.** Codex and Gemini screen phrases have not been observed in this
150
+ > repository, so those two agents use the union (= the old rules) for status. Attaching a profile must not make
151
+ > detection worse than it was. When real measurements exist, turn on `patternsProven` for that profile.
162
152
 
163
- ### 직접 지정
153
+ ### Setting it by hand
164
154
 
165
- - 사이드바에서 **우클릭 → 상태 고르기**, **더블클릭 → 이름 편집**.
166
- - 셸 스크립트 안에서라면 콘솔 제목을 `[AD:<status>] <라벨>` 로 바꾼다. 접두사는 표시에서 지워진다.
155
+ - In the sidebar, **right-click → pick a status**, **double-click → rename**.
156
+ - From inside a shell script, set the console title to `[AD:<status>] <label>`. The prefix is stripped from the display.
167
157
 
168
158
  ```powershell
169
- $host.UI.RawUI.WindowTitle = "[AD:waiting] 배포 승인 대기"
159
+ $host.UI.RawUI.WindowTitle = "[AD:waiting] waiting for deploy approval"
170
160
  ```
171
161
 
172
- status 는 `running` / `waiting` / `done` / `error` / `idle`.
173
- 직접 지정한 상태는 **고정**되어 자동 감지가 덮어쓰지 않는다(배지에 점선 밑줄). 우클릭 → `↺ 자동 감지로` 로 해제한다.
174
- 이 경로는 셸 안에서 직접 실행할 때만 통한다 — 에이전트 훅에서는 콘솔 제목이 터미널까지 오지 않는다.
162
+ `status` is one of `running` / `waiting` / `done` / `error` / `idle`.
163
+ A status set this way is **pinned** and auto-detection will not overwrite it (the badge gets a dotted underline).
164
+ Right-click → `↺ back to auto` releases it.
165
+ This route only works when run directly in the shell — console titles from agent hooks never reach the terminal.
175
166
 
176
- ### 서브에이전트 몇 개 돌고 있나
167
+ ### How many subagents are running
177
168
 
178
- Claude Code 가 백그라운드로 에이전트를 띄우면 그 개수가 줄에 `❖3` 으로 붙는다.
179
- 줄에 마우스를 올리면 무엇이 도는지 목록과 가장 오래된 것의 경과가 나온다.
169
+ When Claude Code launches background agents, the count appears on the row as `❖3`.
170
+ Hover the row for the list and how long the oldest has been going.
180
171
 
181
- 세는 방법은 **그 세션의 대화 기록에서 띄운 것과 끝난 것을 대조**하는 것이다
182
- (`~/.claude/projects/*/<세션 id>.jsonl`). 훅이 알려 주는 값이 아니라 기록이 근거이므로,
183
- 훅이 상태를 안 보내는 동안에도 개수는 맞는다. 세션과 탭을 잇는 것은 훅이 쓰는 상태 파일이라
184
- **훅을 설치하지 않으면 이 표시도 나오지 않는다**(`notifyChannel` 이 꺼져 있어도 마찬가지다).
172
+ It counts by **matching launches against completions in that session's transcript**
173
+ (`~/.claude/projects/*/<session id>.jsonl`). The evidence is the transcript, not what a hook says,
174
+ so the count stays right while no hook is reporting. The session-to-tab link is the hook's status file, so
175
+ **without the hook installed this indicator does not appear** either (the same holds if `notifyChannel` is off).
185
176
 
186
- 기록 파일은 수십 MB까지 자라므로 **자란 만큼만** 읽는다 — 2초에 한 번 크기만 확인하고,
187
- 커진 경우에만 그 뒤쪽을 읽어 누적한다. 처음 붙는 세션은 한 번 전체를 훑어야 해서
188
- 개수가 몇 초 늦게 나타날 수 있다.
177
+ Transcripts grow to tens of megabytes, so it reads **only the growth** — it checks the size every two seconds
178
+ and reads the tail only when it grew. A session being picked up for the first time has to be scanned once,
179
+ so its count can appear a few seconds late.
189
180
 
190
- 한 가지 알아 둘 것 — 에이전트를 Esc 로 취소하거나 CLI 가 죽으면 **끝났다는 기록이 안 남아**
191
- 개수가 줄지 않을 수 있다. 그걸 시간으로 감추지 않는다(진짜 오래 도는 것을 지우게 된다).
192
- 대신 툴팁의 경과가 계속 늘어나므로 그것으로 알아볼 수 있다.
181
+ One thing to know: if you cancel an agent with Esc, or the CLI dies, **no completion is recorded** and the
182
+ count may not come down. That is not hidden with a timeout (that would erase genuinely long-running ones).
183
+ The elapsed time in the tooltip keeps climbing instead, which is how you spot it.
193
184
 
194
- ### 알림
185
+ ### Alerts
195
186
 
196
- 창이 다른 앱 뒤에 가 있을 때(포커스 없음) 어느 탭이 `승인대기` · `오류` · `한도 도달` 로 넘어가면 OS 쪽에 알린다 —
197
- 작업표시줄 아이콘이 깜빡이고(`alertFlash`), 아이콘 위에 그런 탭의 개수가 뱃지로 얹힌다(`alertBadge`).
198
- 뱃지는 상태가 풀리는 대로 실제 개수를 따라가고 0 이면 사라진다. 깜빡임은 창을 다시 앞으로 가져오면 멈춘다.
199
- OS 토스트(`alertToast`)는 기본으로 꺼져 있다 — 켜면 토스트를 눌러 바로 그 탭으로 갈 수 있다.
200
- 창이 앞에 있을 때는 셋 다 아무 일도 하지 않는다. 사이드바가 이미 보이고 있기 때문이다.
187
+ When the window is behind another app (unfocused) and a tab moves to `waiting`, `error` or `rate limited`, the OS is told —
188
+ the taskbar icon flashes (`alertFlash`) and a badge with the count of such tabs is drawn on it (`alertBadge`).
189
+ The badge follows the real count and disappears at zero. Flashing stops when you bring the window forward.
190
+ OS toasts (`alertToast`) are off by default — turn them on and clicking one jumps straight to that tab.
191
+ When the window is in front, all three do nothing: the sidebar is already visible.
201
192
 
202
- ## 지난 세션 이어받기
193
+ ## Resuming past sessions
203
194
 
204
- Tabby 가 꺼져도 **Claude Code 대화는 디스크에 남는다** (`~/.claude/projects/<프로젝트>/<세션id>.jsonl`).
205
- `claude --resume <세션id>` 로 그대로 이어받을 수 있는데, 실제로 막히는 곳은 명령이 아니라
206
- **UUID 목록에서 내 작업을 찾는 것**이다.
195
+ **Claude Code conversations survive on disk** even when Tabby is closed (`~/.claude/projects/<project>/<session id>.jsonl`).
196
+ `claude --resume <session id>` picks one back up — but what actually blocks you is not the command,
197
+ it is **finding your work in a list of UUIDs**.
207
198
 
208
- agentdeck 은 그 답을 이미 갖고 있다 — Enter 를 칠 때 입력창에서 주운 프롬프트 원문.
209
- 그래서 그룹 끝에 서랍을 하나 둔다:
199
+ agentdeck already holds the answer: the prompt text it picked out of the input box when you pressed Enter.
200
+ So there is a drawer at the end of each group:
210
201
 
211
202
  ```
212
203
  ▾ Root ⏸1 ●2
213
- ● Agent Root 진행중 ❖2
214
- 시즌패스 보상 지급경로 정리 3분
215
- ⟲ 지난 세션 5 ▸ ← 기본 접힘. 누르면 펴진다
204
+ ● Agent Root running ❖2
205
+ rework season pass payout path 3m
206
+ ⟲ Past sessions 5 ▸ ← collapsed by default
216
207
  ```
217
208
 
218
- 편 모습:
209
+ Expanded:
219
210
 
220
211
  ```
221
- ⟲ 지난 세션 5 ▾
222
- 백그라운드에서 뭐 돌고있나본데 이거 뭐야
223
- 완료 14:12
224
- 시즌패스 미수령 보상 우편지급 전환
225
- 한도 도달 어제
212
+ ⟲ Past sessions 5 ▾
213
+ what is that thing running in the background
214
+ done 14:12
215
+ move unclaimed season pass rewards to mail
216
+ rate limited yesterday
226
217
  ```
227
218
 
228
- | 조작 | 하는 일 |
219
+ | Action | What it does |
229
220
  |---|---|
230
- | 클릭 | **그 세션의 작업 폴더**에서 새 탭을 열고 `claude --resume <세션id>` 를 보낸다 |
231
- | 우클릭 → `분기해서 이어받기` | `--fork-session`. 원본 기록을 그 시점 그대로 두고 **복사본**에서 이어간다 — 같은 지점에서 다른 방향을 시도할 때만 쓴다 (매번 쓰면 기록이 불어난다) |
232
- | 우클릭 → `세션 ID 복사` · `목록에서 숨기기` | 목록에서만 감춘다. 기록 파일은 건드리지 않는다 |
221
+ | Click | Opens a new tab **in that session's working folder** and sends `claude --resume <session id>` |
222
+ | Right-click → `resume as a branch` | `--fork-session`. Leaves the original transcript at that point and continues in a **copy** — for trying a different direction from the same spot. Used every time, it just multiplies transcripts |
223
+ | Right-click → `copy session id` · `hide from list` | Hides it from the list only. The transcript file is untouched |
233
224
 
234
- 알아 둘 것:
225
+ Worth knowing:
235
226
 
236
- - **작업 폴더가 다르면 목록에 없다.** `--resume` 은 cwd 로 세션을 묶으므로 이어받기도 그 폴더에서 연다.
237
- - **이미 열려 있는 세션**은 `● 열림` 으로 보이고, 누르면 이어받지 않고 그 탭으로 간다 —
238
- 같은 세션을 두 탭에서 이어받으면 두 프로세스가 한 기록 파일에 덧쓴다.
239
- - **대화만 돌아온다.** 그때 띄워 둔 로컬 서버나 백그라운드 프로세스는 되살아나지 않는다.
240
- - 죽은 줄은 색이 아니라 **형태**(점선 바 + 흐림)로 구분한다. 상태 6색은 이미 살아 있는 탭이 쓰고 있어서,
241
- 일곱 번째 색을 들이면 배지가 뜻하는 바가 흐려진다.
242
- - 라벨은 두 곳에서 온다 — 살아 있을 때 주운 프롬프트(원장, `%LOCALAPPDATA%\tabby-agentdeck\sessions.json`)와
243
- 기록 파일 앞부분에서 읽은 첫 프롬프트. 앞엣것이 우선이고, 플러그인을 깔기 전 세션이나 다른 터미널에서
244
- 띄운 세션은 뒤엣것으로 잡힌다.
245
- - 기록 파일이 사라진 세션은 목록에서도 원장에서도 지운다. 이어받아도 복원할 것이 없기 때문이다.
227
+ - **A different working folder means it is not in the list.** `--resume` keys sessions by cwd, so resuming opens there too.
228
+ - **Already-open sessions** show as `● open` and clicking goes to that tab instead of resuming —
229
+ resuming the same session in two tabs would have two processes appending to one transcript.
230
+ - **Only the conversation comes back.** Local servers and background processes you had running do not.
231
+ - Dead rows are distinguished by **shape** (dotted bar + dimmed), not colour. The six status colours are already
232
+ spoken for by live tabs, and a seventh would blur what a badge means.
233
+ - Labels come from two places: the prompt picked up while it was alive (the ledger,
234
+ `%LOCALAPPDATA%\tabby-agentdeck\sessions.json`) and the first prompt read from the head of the transcript.
235
+ The former wins; sessions from before the plugin was installed, or started in another terminal, get the latter.
236
+ - Sessions whose transcript is gone are dropped from both the list and the ledger — there is nothing left to resume.
246
237
 
247
- 이 기능이 있는 이유는 아래 `기동 시 탭 복원 끄기` 와 한 쌍이다 — 순정 복원은 **셸만** 되살리고
248
- 그 안의 세션은 이미 죽어 있어서 빈 프롬프트 탭만 줄줄이 남는다. 그래서 그쪽은 끄고, 진짜 복원을 여기 둔다.
238
+ This exists as a pair with `noTabRecovery` below — Tabby's own restore brings back **only the shell**, and the
239
+ session inside it is already dead, leaving a row of empty prompts. So that is turned off and the real restore lives here.
249
240
 
250
- ## 결과물 미리보기 패널
241
+ ## Preview panel
251
242
 
252
- 에이전트가 만든 것이 문서나 그림이면 터미널 안에서는 확인할 수 없다. 그래서 탐색기로 나가서 열게 되고,
253
- 그 왕복 때문에 결과물을 안 보고 넘어간다. 그 자리를 메우는 패널이다 — 사이드바의 **▤** 버튼이나
254
- `agentdeck-view` 단축키로 여닫는다. 여닫은 상태는 다음 기동에도 복원된다.
243
+ If what an agent produced is a document or an image, you cannot check it inside the terminal. So you go out to the
244
+ file explorer, and because of that round trip you end up not looking at the output at all. This panel fills that gap —
245
+ open it with the **▤** button in the sidebar or the `agentdeck-view` shortcut. Its open/closed state is restored on next start.
255
246
 
256
- **보여주는 것**
247
+ **What it renders**
257
248
 
258
- | 종류 | 어떻게 |
249
+ | Kind | How |
259
250
  |---|---|
260
- | `md` `markdown` `mdx` | 제목·표·목록·코드·인용·체크박스·이미지까지 그려서 보여준다. 문서 안의 이미지도 같이 뜬다 |
261
- | `png` `jpg` `gif` `webp` `svg` `bmp` `ico` `avif` | 원본 크기로(패널보다 크면 폭에 맞춰) 그린다 |
262
- | `csv` `tsv` | 표로 그린다. 따옴표로 감싼 칸(`"a,b"`)을 한 칸으로 읽는다 |
263
- | 코드·텍스트 (`.ts` `.cs` `.py` `.json` `.log` …) | 줄 번호를 붙여 보여준다 |
264
-
265
- **파일이 패널에 올라오는 세 경로**
266
-
267
- 1. **화면에 찍힌 경로를 줍는다** — `Edited src/hero.tsx`, `Wrote D:\a\b.md`, `Read build.py` 처럼
268
- 에이전트가 만진 파일을 찍으면 그것을 최근 목록(위쪽 칩)에 쌓는다. **어느 에이전트든 통한다** —
269
- 훅이 있는 Claude Code 뿐 아니라 Codex·Gemini 도 경로는 화면에 찍기 때문이다.
270
- 상대경로는 그 탭의 작업 폴더로 풀고, 실제로 있는 파일만 올린다. 최근 목록은 **탭마다 따로**다.
271
- 2. **끌어다 놓기** — 탐색기·에디터에서 파일을 패널에 떨어뜨린다.
272
- 3. **경로 직접 입력** — **+** 를 눌러 경로를 넣는다(`Enter` 로 열고 `Esc` 로 접는다).
273
- **없는 파일이면 만들어 준다** — `Enter` 를 한 번 더 치면 (필요하면 상위 폴더까지) 만들고
274
- 곧바로 편집으로 들어간다. 메모 한 장 시작하려고 탐색기로 나갈 일이 없다. 두 번 치게 한 이유는
275
- 오타로 친 경로에 빈 파일이 조용히 생기면 나중에 그 오타를 찾는 값이 더 크기 때문이다.
276
-
277
- 열어 둔 파일이 바뀌면 **스스로 다시 읽는다** — 에이전트가 문서를 고치는 동안 옆에서 따라간다.
278
- 패널이 닫혀 있어도 **읽어는 둔다**(`문서 패널에 읽어두기`, 기본 켬) — 그리지만 않고 최근 칩과
279
- "다음에 열면 보여줄 파일" 을 계속 갈아 두므로, 작업이 한창일 때 `▤` 를 누르면 **그때까지 건드린
280
- 파일들이 칩으로 쌓여 있고 본문은 가장 최근 파일**이다(`변경` 을 보고 있었으면 그 자리에서 diff 를
281
- 다시 읽는다). 같은 파일이라도 여는 김에 다시 읽는다 — 닫힌 동안에는 파일 감시가 꺼져 있어서다.
282
- **여닫기는 사람 몫이 기본**이다 — 결과물이 나오는 순간 패널까지 저절로 열리기를 원하면
283
- **설정 → 미리보기 패널 → `패널 자동으로 열기`** 를 켠다(기본 꺼짐). 반대로 `읽어두기` 를 끄면
284
- 아무것도 자동으로 하지 않는다 — 경로는 최근 칩에만 쌓이고 무엇을 볼지는 사람이 고른다.
285
- 문서 안의 링크는 웹이면 브라우저로, 로컬 파일이면 이 패널에서 연다.
286
-
287
- **탭을 옮기면 패널도 그 탭 것으로 바뀐다** — 최근 칩과 `변경` 탭뿐 아니라 **본문도** 그 세션이
288
- 마지막으로 보던 파일로 돌아간다. 아무것도 안 본 탭에서는 빈 화면이다. 옆에 남의 탭 문서가 떠 있으면
289
- 그것이 지금 탭의 것이라고 착각하기 때문이다. 탭을 옮기는 것만으로 패널이 **열리지는 않는다** —
290
- 닫혀 있으면 다음에 열 때 맞춰진다.
291
-
292
- **고쳐서 저장한다 — `✎`**
293
-
294
- 읽기만 되면 오타 하나에도 에디터를 따로 열어야 하고, 그 왕복이 이 패널이 없애려던 것과 같다.
295
- `✎` 를 누르면 본문 자리가 편집기가 된다. `저장`(`Ctrl+S`) · `취소`(`Esc`).
296
-
297
- - 글자 파일(`md` · 코드 · 텍스트 · `csv`)만 편집한다. 이미지·바이너리에서는 버튼이 흐려진다.
298
- - **너무 큰 파일은 열지 않는다** (1.5MB 넘음). 보기는 앞부분만 읽어도 되지만 저장은 파일을 통째로
299
- 다시 쓰므로, 앞부분만 들고 저장하면 뒷부분이 사라진다. 그래서 전체를 읽을 수 있을 때만 연다.
300
- - **BOM 과 개행(CRLF/LF)을 원본 그대로 되돌린다.** 안 그러면 한 줄만 고쳐도 P4·git diff 가
301
- 파일 전체를 바뀐 것으로 본다.
302
- - 편집하는 동안에는 **아무도 화면을 덮지 못한다** — 파일 감시의 자동 재읽기도, 새 파일 따라가기도
303
- 비켜 간다. 그 사이 파일이 밖에서 바뀌었으면 저장할 때 한 번 더 묻는다(두 번째 누름이 덮어쓴다).
304
- - **읽기 전용 파일은 열자마자 알린다** (`읽기 전용` 표시). 다 쳐 놓고 저장할 때 알면 그 타이핑이
305
- 헛일이 되기 때문이다. 저장을 누르면 `읽기 전용이다 (P4 면 p4 edit 먼저) — 다시 누르면 속성을
306
- 풀고 저장한다` 로 한 번 막는다. **말없이 속성을 풀지 않는 이유** — 이 환경에서 읽기 전용의
307
- 정체는 대개 P4 에서 체크아웃하지 않은 파일이고, 체크아웃 없이 쓴 내용은 다음 `p4 sync` 에
308
- 조용히 덮인다.
309
- - 저장하지 않은 편집이 있으면 다른 파일이나 `변경` 탭으로 넘어가지 않는다.
310
-
311
- **찾는다 — `🔍` / `Ctrl+F`**
312
-
313
- 대소문자를 가리지 않고 본문에서 찾아 표시하고, `Enter`(다음) · `Shift+Enter`(이전) 로 오간다.
314
- `Esc` 로 닫으면 표시만 걷히고 본문 글자는 그대로다. 편집 중이면 편집기 안에서 찾아 그 자리를
315
- 선택한다. **`Ctrl+F` 는 패널 안에서만 듣는다** — 터미널의 `Ctrl+F`(less·vim)를 뺏지 않으려는 것이라,
316
- 본문을 한 번 누른 뒤에 쓴다.
317
-
318
- 패널 폭은 터미널과 닿는 경계선을 끌어 바꾼다. **패널을 열면 4:3 이 완화되고 터미널이 그만큼 좁아진다** —
319
- 사이드바는 줄지 않는다. 울트라와이드에서는 패널을 열어도 4:3 이 그대로 유지된다.
320
-
321
- > 문서 안의 원문 HTML 은 **글자로만** 보여준다(태그로 만들지 않는다). 참조 링크(`[a][1]`)와 각주는 지원하지 않는다.
322
-
323
- ### `변경` 탭 — 작업트리의 diff
324
-
325
- 헤더 아래 `파일` / `변경` 스위치로 바꾼다. `변경` 은 그 탭의 작업 폴더에서 `git diff HEAD` 를 읽어
326
-
327
- - `3개 파일 · +716 -15` 요약과 파일 목록(상태 딱지 + `+N -M`). 파일명을 누르면 그 파일 diff 로 스크롤한다
328
- - 파일별 유니파이드 diff — 구/신 줄번호를 양쪽에 붙이고 추가·삭제·문맥·헝크를 색으로 가른다
329
- - 추적되지 않은 파일은 이름만 따로 (내용 diff 는 하지 않는다)
330
-
331
- 를 보여준다. **에이전트를 가리지 않는 이유가 미리보기와 같다** — 근거가 훅이 아니라 git 작업트리라서
332
- 누가 고쳤든 성립한다. 저장소가 아니거나 git 이 없거나 작업 폴더를 아직 모르면 그 사실을 한 줄로 알린다.
333
-
334
- #### 스테이지 · 커밋
335
-
336
- 파일 줄 왼쪽의 딱지가 **스테이지 상태**다 — `unstaged` / `staged` / `both`(일부만 올라감) /
337
- `untracked` / `conflict`. 누르면 그 파일을 `git add` 하거나 되돌린다(`git reset`). 아래 줄에
338
- `staged N · unstaged M` 요약과 메시지 입력창, 커밋 버튼이 있다.
339
-
340
- **우발 커밋을 막는 네 겹 —**
341
-
342
- 1. 메시지가 비어 있으면 버튼이 잠긴다
343
- 2. 공백만 넣으면 거부하고 이유를 적는다
344
- 3. 첫 누름은 커밋하지 않고 `커밋 확인` 으로 바뀐다(색도 경고색). **두 번째 누름**에 실행된다
345
- 4. 확인 대기 중에 메시지를 고치면 그 대기가 풀린다 (다른 메시지로 잘못 커밋되지 않게)
346
-
347
- 스테이지된 것이 없으면 커밋하지 않는다 — `git commit -a` 로 넓히지 않는다.
348
-
349
- > 작업 폴더는 **탭이 열릴 때의 cwd** 다. 셸에서 `cd` 로 옮겨도 Tabby 가 알려주는 값은 바뀌지 않으므로
350
- > (Windows 로컬 세션 실측), 다른 저장소를 보려면 그 폴더에서 새 탭을 연다.
351
- > `git` 은 상위 폴더로 올라가며 저장소를 찾는다 — 홈 디렉토리가 저장소면 아무 폴더에서나 그것이 잡힌다.
352
-
353
- ## 키
354
-
355
- | 키 | 동작 |
251
+ | `md` `markdown` `mdx` | Headings, tables, lists, code, quotes, checkboxes and images. Images inside the document render too |
252
+ | `png` `jpg` `gif` `webp` `svg` `bmp` `ico` `avif` | At original size (fit to width when larger than the panel) |
253
+ | `csv` `tsv` | As a table. A quoted cell (`"a,b"`) is read as one cell |
254
+ | Code and text (`.ts` `.cs` `.py` `.json` `.log` …) | With line numbers |
255
+
256
+ **Three ways a file gets into the panel**
257
+
258
+ 1. **Paths printed on screen are picked up** — `Edited src/hero.tsx`, `Wrote D:\a\b.md`, `Read build.py`.
259
+ Whatever the agent touched is stacked into the recent list (the chips at the top). **This works for any agent** —
260
+ Codex and Gemini print paths just like Claude Code, hook or no hook.
261
+ Relative paths are resolved against that tab's working folder, and only files that actually exist are shown.
262
+ The recent list is **per tab**.
263
+ 2. **Drag and drop** — from the file explorer or your editor onto the panel.
264
+ 3. **Type a path** — press **+** and enter one (`Enter` opens, `Esc` collapses).
265
+ **If the file does not exist it is created** — press `Enter` once more and it is created (parent folders included)
266
+ and opened for editing. No trip to the file explorer to start a note. It takes two presses because a typo'd path
267
+ silently creating an empty file costs more later than the extra keystroke does now.
268
+
269
+ An open file that changes is **re-read by itself** — the panel follows along while the agent edits.
270
+ Even while closed it **still reads** (`preload into the panel`, on by default) — it does not draw, but it keeps the
271
+ recent chips and "the file to show next time" current, so pressing `▤` mid-task gives you **the files touched so far
272
+ as chips with the most recent one in the body** (if you were on `Changes`, the diff is re-read in place).
273
+ The same file is re-read on open, because file watching is off while the panel is closed.
274
+ **Opening and closing is yours to do by default** — if you want the panel to open by itself the moment output appears,
275
+ turn on **Settings → Preview panel → `open the panel automatically`** (off by default).
276
+ Turn `preload` off instead and nothing happens automatically: paths only stack as chips and you choose what to look at.
277
+ Links inside a document open in the browser if they are web links, in this panel if they are local files.
278
+
279
+ **Switching tabs switches the panel** — not just the recent chips and the `Changes` tab, but **the body**, back to
280
+ the file that session last had open. A tab that has looked at nothing shows an empty panel. Otherwise another
281
+ session's document sitting open beside you reads as if it belonged to this one. Switching tabs alone does **not open**
282
+ the panel — if it is closed, it is brought up to date the next time you open it.
283
+
284
+ **Edit and save — `✎`**
285
+
286
+ Read-only means a single typo sends you to a separate editor, and that round trip is exactly what this panel was meant to remove.
287
+ Press `✎` and the body becomes an editor. `Save` (`Ctrl+S`) · `Cancel` (`Esc`).
288
+
289
+ - Only text files (`md`, code, text, `csv`) are editable. The button dims on images and binaries.
290
+ - **Very large files are not opened** (over 1.5 MB). Viewing can read just the head, but saving rewrites the whole
291
+ file — saving while holding only the head would drop the tail. So it opens only when it can read all of it.
292
+ - **BOM and line endings (CRLF/LF) are restored exactly as they were.** Otherwise a one-line edit makes P4 and git
293
+ diff see the whole file as changed.
294
+ - **Nothing overwrites the screen while you edit** — neither the watcher's re-read nor following a new file.
295
+ If the file changed outside in the meantime, saving asks once more (the second press overwrites).
296
+ - **Read-only files are announced on open** (a `read-only` marker). Finding out at save time wastes everything you typed.
297
+ Pressing save stops once with `this is read-only (p4 edit first, if P4) — press again to clear the attribute and save`.
298
+ **Why it is not cleared silently** — in this environment read-only usually means a file not checked out from P4,
299
+ and anything written without a checkout is quietly lost on the next `p4 sync`.
300
+ - With unsaved edits, it will not move to another file or to the `Changes` tab.
301
+
302
+ **Find — `🔍` / `Ctrl+F`**
303
+
304
+ Case-insensitive, highlights matches, `Enter` (next) and `Shift+Enter` (previous) move between them.
305
+ `Esc` closes it and only the highlighting goes away. While editing it searches inside the editor and selects in place.
306
+ **`Ctrl+F` is heard only inside the panel** — it must not steal the terminal's `Ctrl+F` (less, vim) — so click the body once first.
307
+
308
+ Panel width is changed by dragging the divider it shares with the terminal. **Opening the panel relaxes the 4:3 rule and
309
+ the terminal narrows by that much**; the sidebar does not shrink. On ultrawide displays 4:3 holds even with the panel open.
310
+
311
+ > Raw HTML inside a document is shown **as text** (never turned into tags). Reference links (`[a][1]`) and footnotes are not supported.
312
+
313
+ ### The `Changes` tab — the working tree's diff
314
+
315
+ Switch with `Files` / `Changes` under the header. `Changes` reads `git diff HEAD` in that tab's working folder and shows
316
+
317
+ - a `3 files · +716 -15` summary and the file list (status tag + `+N -M`). Click a filename to scroll to its diff
318
+ - per-file unified diff — old and new line numbers on both sides, with additions, deletions, context and hunks coloured apart
319
+ - untracked files by name only (no content diff)
320
+
321
+ **It is agent-agnostic for the same reason the preview is** — the evidence is the git working tree, not a hook, so it
322
+ holds no matter who made the change. If this is not a repository, git is missing, or the working folder is not known yet, it says so in one line.
323
+
324
+ #### Stage · commit
325
+
326
+ The tag at the left of a file row is its **staging state** — `unstaged` / `staged` / `both` (partially staged) /
327
+ `untracked` / `conflict`. Click it to `git add` the file or take it back (`git reset`). Below is a
328
+ `staged N · unstaged M` summary, a message box and the commit button.
329
+
330
+ **Four layers against an accidental commit —**
331
+
332
+ 1. An empty message locks the button
333
+ 2. Whitespace-only is rejected with a reason
334
+ 3. The first press does not commit; it turns into `confirm commit` (in a warning colour). The **second press** runs it
335
+ 4. Editing the message while confirmation is pending cancels that pending state (so it cannot commit under a different message)
336
+
337
+ With nothing staged it does not commit — it never widens to `git commit -a`.
338
+
339
+ > The working folder is **the cwd the tab was opened with**. `cd` in the shell does not change what Tabby reports
340
+ > (measured on local Windows sessions), so open a new tab in that folder to look at another repository.
341
+ > `git` walks up looking for a repository — if your home directory is one, it is found from anywhere.
342
+
343
+ ## Keys
344
+
345
+ | Key | Action |
356
346
  |---|---|
357
- | `Ctrl+Enter` / `Shift+Enter` | 줄바꿈 (`0x0A` 전송). `agentdeck-newline` |
358
- | `Ctrl+V` | 붙여넣기. 클립보드에 **이미지만** 있으면 텍스트 대신 이미지 붙여넣기 키를 앱에 넘긴다 — Claude Code·Codex 가 클립보드를 직접 읽는다. `agentdeck-paste` |
359
- | 우클릭 | 선택이 있으면 복사, 없으면 붙여넣기. 길게(기본 250ms) 누르면 컨텍스트 메뉴 |
360
- | `Ctrl+Shift+L` | 사이드바 목록에 포커스를 준다 / 같은 키로 터미널로 돌아온다. `agentdeck-focus-list` |
361
- | `Ctrl+W` | 지금 탭을 닫는다 — 터미널에서 누르면 **활성 탭**, 목록이 키보드를 가졌으면 **포커스 줄의 탭**. `keyboardNav` + `keyboardCloseTab` 이 켜져 있을 때만이고, 끄면 터미널의 앞 단어 지우기(`0x17`)로 그대로 흐른다 |
362
- | (미배정) | `agentdeck-toggle` — 사이드바/4:3 즉시 on-off |
363
- | (미배정) | `agentdeck-repair` — 화면 복구 |
364
- | (미배정) | `agentdeck-view` — 미리보기 패널 여닫기 (사이드바 `▤` 와 같다) |
365
- | (미배정) | `agentdeck-view-mode` — 패널의 `파일` / `변경` 모드 전환 |
366
-
367
- 키 배정은 Tabby 설정 → 단축키의 `agentdeck-*` 항목에서 바꾼다.
368
- `Ctrl+V` 는 **핫키가 아니라 캡처 단계에서 한 번만** 처리한다. 그래서 기동할 때 순정 `hotkeys.paste` 와
369
- `agentdeck-paste` **양쪽에서** `Ctrl-V` 를 뺀다 — 핫키에 남겨 두면 Tabby 가 같은 키를 두 경로로 밀어 넣어
370
- 한 번 눌러 두 번 붙는 일이 있었다(`docs/DEVELOPMENT.md` 에 원인).
371
-
372
- 터미널 앱에 리터럴 `Ctrl+V`(0x16, quoted-insert)를 보내야 하면 `claimCtrlV: false`.
373
- 그러면 우리도 잡지 않고 핫키에도 없으므로 xterm 이 0x16 을 그대로 PTY 로 흘린다 —
374
- **대신 그 상태에서는 `Ctrl+V` 붙여넣기 자체가 안 된다**(그게 이 설정의 목적이다).
375
- 붙여넣기는 `Ctrl+Shift+V`·`Shift+Insert`(Tabby 순정) 또는 우클릭으로 한다.
376
-
377
- ### 키보드로 사이드바 다루기
378
-
379
- `Ctrl+Shift+L` 로 목록에 들어간다. 마우스 없이 탭을 훑어보려고 만든 것이고, 규칙은 이렇다.
380
-
381
- | 키 | 하는 일 |
347
+ | `Ctrl+Enter` / `Shift+Enter` | Newline (sends `0x0A`). `agentdeck-newline` |
348
+ | `Ctrl+V` | Paste. If the clipboard holds **only an image**, the image-paste key is handed to the app instead of text — Claude Code and Codex read the clipboard themselves. `agentdeck-paste` |
349
+ | Right-click | Copy with a selection, paste without one. Hold (250 ms default) for the context menu |
350
+ | `Ctrl+Shift+L` | Focus the sidebar list / same key returns to the terminal. `agentdeck-focus-list` |
351
+ | `Ctrl+W` | Close the current tab — the **active tab** from the terminal, the **focused row** when the list has the keyboard. Only while `keyboardNav` + `keyboardCloseTab` are on; off, it flows through as the shell's delete-previous-word (`0x17`) |
352
+ | (unbound) | `agentdeck-toggle` — sidebar / 4:3 on-off |
353
+ | (unbound) | `agentdeck-repair` — screen repair |
354
+ | (unbound) | `agentdeck-view` — open/close the preview panel (same as the sidebar `▤`) |
355
+ | (unbound) | `agentdeck-view-mode` — switch the panel between `Files` and `Changes` |
356
+
357
+ Bind keys under Tabby Settings → Hotkeys, in the `agentdeck-*` entries.
358
+ `Ctrl+V` is handled **in the capture phase, not as a hotkey**. On startup it is removed from **both** Tabby's own
359
+ `hotkeys.paste` and `agentdeck-paste` — leaving it in the hotkey table let Tabby push the same key down two paths,
360
+ so one press pasted twice (the cause is written up in `docs/DEVELOPMENT.md`).
361
+
362
+ If you need a literal `Ctrl+V` (0x16, quoted-insert) to reach the terminal app, set `claimCtrlV: false`.
363
+ Then neither we nor the hotkey table claim it and xterm passes 0x16 straight to the PTY —
364
+ **but `Ctrl+V` paste stops working in that state** (that is the point of the setting).
365
+ Paste with `Ctrl+Shift+V` / `Shift+Insert` (Tabby's own) or right-click instead.
366
+
367
+ ### Driving the sidebar from the keyboard
368
+
369
+ `Ctrl+Shift+L` enters the list. It exists for looking through tabs without the mouse, and the rules are these.
370
+
371
+ | Key | What it does |
382
372
  |---|---|
383
- | `↑` `↓` | 줄 사이 이동. **활성 탭은 바뀌지 않는다** |
384
- | `Home` `End` | 첫 줄 / 마지막 줄 |
385
- | `Enter` | 탭 줄이면 그 탭으로 전환하고 키를 터미널에 돌려준다. 그룹 헤더면 접기/펴기 |
386
- | `Esc` | 검색어·필터가 걸려 있으면 **먼저 그것을 지운다**. 지울 게 없을 때 터미널로 나간다 |
387
- | `Tab` `Shift+Tab` | 검색창으로 |
388
- | `Ctrl+W` | 포커스 줄의 탭을 닫는다 (그룹 헤더에서는 아무 일도 하지 않는다). 목록 밖 — 터미널에서 누르면 활성 탭이다 |
373
+ | `↑` `↓` | Move between rows. **The active tab does not change** |
374
+ | `Home` `End` | First row / last row |
375
+ | `Enter` | On a tab row, switch to it and hand the keys back to the terminal. On a group header, collapse/expand |
376
+ | `Esc` | With a search or filter set, **clear that first**. With nothing to clear, leave for the terminal |
377
+ | `Tab` `Shift+Tab` | To the search box |
378
+ | `Ctrl+W` | Close the focused row's tab (nothing on a group header). Outside the list — in the terminal — it is the active tab |
389
379
 
390
- **포커스와 선택을 가른 이유** — 줄을 지날 때마다 탭이 바뀌면 그 탭의 출력이 화면을 덮고
391
- 터미널 폭이 매번 다시 적용되어 화면이 튄다. 그러면 "어느 탭이었나" 를 훑어볼 수가 없다.
392
- 그래서 `↑↓` 는 테두리(키보드 포커스)만 옮기고, 탭을 실제로 여는 것은 `Enter` 하나다.
380
+ **Why focus and selection are separate** — if the tab changed on every row you passed, that tab's output would cover
381
+ the screen and the terminal width would be re-applied each time, making the display jump. Looking through your tabs
382
+ would be impossible. So `↑↓` move only the outline (keyboard focus) and `Enter` is the single thing that opens a tab.
393
383
 
394
- 검색창과 목록은 `↓`(검색창 → 결과 첫 줄)와 `↑`(첫 줄 → 검색창)로 오간다.
395
- 검색창의 `↑` 는 가로채지 않는다 — 한 줄 입력에서 `↑` 는 커서를 맨 앞으로 보내는
396
- 편집 동작이고, 치던 검색어를 고칠 때 실제로 쓴다.
384
+ The search box and the list are joined by `↓` (box → first result) and `↑` (first row → box).
385
+ `↑` inside the search box is not intercepted — in a single-line input that key moves the cursor to the start,
386
+ and you really do use it when fixing a search term.
397
387
 
398
- 포커스가 사이드바에 없는 동안에는 **키를 한 개도 가로채지 않는다**(리스너가 목록
399
- 엘리먼트에 걸려 있어서 이벤트가 아예 오지 않는다). 그래도 끄고 싶으면 `keyboardNav: false`.
388
+ While focus is not on the sidebar it **intercepts not one key** (the listener is on the list element, so the events
389
+ never arrive). If you want it off anyway, `keyboardNav: false`.
400
390
 
401
- `Ctrl+W` 만 예외다 — 그건 터미널에서도 받아야 하므로 **document 캡처 단계**에서 잡는다.
402
- 대신 **닫을 탭이 정해졌을 때만** 키를 먹는다: 그룹 헤더에 포커스가 있거나 설정 화면 입력창이면
403
- 그대로 흘린다. 핫키 테이블에 넣지 않은 이유도 그것이다 — Tabby 핫키는 등록만으로 키를 먹어서
404
- 설정을 꺼도 터미널의 `Ctrl+W`(앞 단어 지우기)가 죽는다. 그 키를 그대로 쓰려면
405
- `keyboardCloseTab: false`(설정 창의 `Ctrl+W 로 탭 닫기`)로 끄면 되고 목록 조작은 남는다.
406
- 닫기는 사이드바 `✕` 와 같은 경로라 돌아가는 프로세스가 있으면 Tabby 가 평소처럼 한 번 물어본다.
391
+ `Ctrl+W` is the one exception — it has to be received from the terminal too, so it is caught in the **document capture phase**.
392
+ In exchange it only swallows the key **when there is a tab to close**: on a group header, or in a settings input, it flows through.
393
+ That is also why it is not in the hotkey table — a Tabby hotkey swallows the key merely by being registered, so turning the
394
+ setting off would still kill the terminal's `Ctrl+W` (delete previous word). To keep that key, set
395
+ `keyboardCloseTab: false` (`Close tab with Ctrl+W` in the settings window) and list navigation stays.
396
+ Closing goes through the same path as the sidebar `✕`, so Tabby asks as usual when a process is still running.
407
397
 
408
- ### 한글 입력 — 조합 중인 음절이 커서를 따라가지 않게
398
+ ### IME input — keeping a composing syllable from following the cursor
409
399
 
410
- 한글을 치다가 `Home` · `End` · `Shift+Enter` 를 누르면 **조합 중인 마지막 음절이 옮겨간 자리로 따라가는**
411
- 문제가 있었다. 방향키만 멀쩡한데 그 차이가 원인이다 — xterm 은 자기 키 경로로 들어온 키에 대해서는
412
- 조합을 **먼저 확정**하고 키를 보내지만, 그 경로를 거치지 않고 pty 에 바이트를 직접 쓰면
413
- (터미널 핫키·플러그인의 줄바꿈 전송) 확정이 `setTimeout` 으로 밀려 **바이트가 먼저, 음절이 나중**에 나간다.
400
+ Typing Korean (or any IME language) and pressing `Home`, `End` or `Shift+Enter` used to make **the last composing
401
+ syllable follow the cursor to its new position**. Arrow keys were fine, and that difference is the cause — xterm
402
+ **commits the composition first** for keys that come through its own key path, but when bytes are written straight
403
+ to the pty without that path (terminal hotkeys, our newline), the commit is deferred by a `setTimeout`, so
404
+ **the bytes go first and the syllable after**.
414
405
 
415
- 그래서 pty 에 쓰는 지점을 한 곳으로 모아, 쓰기 직전에 조합 상태를 보고
406
+ So every write to the pty is funnelled through one place, and just before writing it looks at the composition state:
416
407
 
417
- - 조합 중이면 **조합이 끝나기를 기다렸다가** 쓴다
418
- - 확정 전송이 이미 예약돼 있으면 우리가 한 틱 물러난다
419
- - 상태를 못 읽으면 그냥 쓴다 (이 보정이 정상 입력을 막는 일은 없어야 한다)
408
+ - composing → **wait for composition to end**, then write
409
+ - a commit is already scheduled → step back one tick
410
+ - state unreadable → just write (this guard must never block normal input)
420
411
 
421
- 로 갈라 준다. 조합이 끝나지 않으면 0.4초 뒤에는 확정시키고 쓴다 — 입력이 안 나가는 것이 최악이다.
412
+ If composition does not end, it is forced after 0.4 s and written — input not going out at all is the worst outcome.
422
413
 
423
- > **왜 기다리나 (0.6.3).** 예전에는 조합 중이면 우리가 확정을 재촉하고 바로 썼다. 그런데 우리가
424
- > 확정시켜도 IME 는 자기 일정대로 확정을 한 번 더 알리고, 그때 음절이 **또** 나간다 — 그 두 번째가
425
- > 개행 뒤에 붙어 **문자가 새 줄로 내려갔다.** 지금은 IME 의 순서를 건드리지 않으므로 음절이 한 번만,
426
- > 개행보다 먼저 나간다.
414
+ > **Why wait (0.6.3).** It used to force the commit and write immediately. But even after we forced it, the IME
415
+ > announced its own commit on its own schedule, and the syllable went out **again** — that second one landed after
416
+ > the newline, so **the character dropped to the next line**. Now the IME's ordering is untouched, so the syllable
417
+ > goes out once, before the newline.
427
418
 
428
- 끄려면 `imeOrderGuard: false`.
419
+ Turn it off with `imeOrderGuard: false`.
429
420
 
430
- ### 화면 복구 (`↻`)
421
+ ### Screen repair (`↻`)
431
422
 
432
- statusline 이 사라지거나 입력창 구분선이 화면 중간에서 끊기는 등 화면이 깨졌을 때 누른다.
433
- 폭 재계산 → pty 크기 동기화 → **입력창 자리의 잔상만** 지우기 → 흔들어 SIGWINCH 주기 순으로 진행한다.
434
- 지운 자리는 앱이 자기 렌더 주기에 다시 그린다.
423
+ Press it when the screen is broken — the statusline gone, the input-box divider cut off mid-screen.
424
+ It recalculates width → syncs the pty size → clears **only the input box's remnant** → nudges to deliver a SIGWINCH.
425
+ The app redraws the cleared area on its own render cycle.
435
426
 
436
- **보고 있던 화면은 지우지 않는다.** 예전에는 마지막에 `Ctrl+L` 을 보내 "전부 다시 그려라" 를 시켰는데,
437
- Claude Code 는 그걸 **화면 지우기**로 받아 대화가 통째로 스크롤백으로 밀려났다
438
- (2026-09-11 채증: 정상 화면을 복구했더니 78행 중 0~72행이 비고 입력창만 남았다).
439
- 그래서 `repairSendRedrawKey` 는 기본으로 꺼져 있다 — 실제로 고치는 것은 잔상 지우기와 크기 정합이라
440
- 없어도 복구된다. 스크롤백까지 비우는 `repairHard: true` 도 기본은 꺼져 있다.
427
+ **It does not erase what you were reading.** It used to send `Ctrl+L` at the end to mean "redraw everything", but
428
+ Claude Code takes that as **clear screen** and pushed the whole conversation into the scrollback
429
+ (captured 2026-09-11: repairing a healthy screen emptied rows 0–72 of 78 and left only the input box).
430
+ So `repairSendRedrawKey` is off by default — what actually fixes things is clearing the remnant and matching the size,
431
+ and it works without it. `repairHard: true`, which also empties the scrollback, is off by default too.
441
432
 
442
- ## 설정
433
+ ## Settings
443
434
 
444
- **설정 창(설정 → AgentDeck)** 에는 실제로 바꿀 일이 있는 것만 있다 — 레이아웃 on/off, 마우스로 바꾼 배치 초기화,
445
- 기동 시 탭 복원 끄기, 미리보기 패널(열기 · 경로 자동 수집 · 새 파일 따라가기), Claude Code 훅 설치/제거, 작업 루트 프로필. 나머지는 Tabby 설정 파일(`%APPDATA%\tabby\config.yaml`)의
446
- `agentDeck` 아래에서 조절한다.
435
+ The **settings window (Settings → AgentDeck)** holds only what you would actually change — layout on/off, resetting a
436
+ mouse-dragged arrangement, disabling tab restore on startup, the preview panel (open · path scraping · follow new files),
437
+ installing/removing the Claude Code hook, and the working-root profile. The rest live under `agentDeck` in Tabby's
438
+ config file (`%APPDATA%\tabby\config.yaml`).
447
439
 
448
- | 키 | 기본값 | 설명 |
440
+ | Key | Default | Description |
449
441
  |---|---|---|
450
- | `enabled` | `true` | 사이드바 + 4:3 레이아웃 on/off |
451
- | `aspectW` / `aspectH` | `4` / `3` | 터미널 뷰포트 비율 |
452
- | `sidebarDock` | `right` | 사이드바 위치 `left` / `right` / `top` / `bottom`. 헤더 드래그로도 바뀐다 |
453
- | `sidebarWidth` | `0` | 좌/우 도킹 시 폭(px). 0 = 화면비로 자동 계산 |
454
- | `sidebarHeight` | `200` | 상/하 도킹 시 높이(px) |
455
- | `sidebarMin` / `sidebarMax` | `200` / `560` | 자동 계산 폭의 범위(px). 넓은 모니터에서 정확히 4:3 을 원하면 `sidebarMax` 를 `창 너비 − 창 높이 × 4/3` 으로 |
456
- | `sortByStatus` | `false` | 급한 순서(승인대기 → 오류 → 한도 → 진행중 → 완료 → 대기)로 정렬한다. 켜면 **드래그 재정렬은 막힌다** — 옮겨도 다음 렌더에 제자리로 돌아가기 때문 |
457
- | `collapsedGroups` | `[]` | 접어 둔 그룹 키. 헤더를 누르면 여기 쌓인다. 설정 창의 `모두 펼치기` 로 비운다 |
458
- | `viewerOpen` | `false` | 미리보기 패널이 열려 있나. `▤` / `agentdeck-view` 로 토글하거나 **새 파일을 주워 저절로 열리면** 여기 남아 다음 기동에 복원된다. 열림을 사람이 켜 두는 값이 아니다 |
459
- | `viewerDock` | `right` | 패널이 붙는 방향 `left` / `right`. 사이드바와 같은 쪽이면 사이드바가 창 가장자리(바깥) |
460
- | `viewerWidth` | `420` | 패널 폭(px). 경계선 드래그로 바뀐다. 좁은 창에서는 `창폭 − 320 − 140` 까지만 |
461
- | `searchBox` | `true` | 사이드바에 검색 줄을 보인다. 끄면 걸려 있던 필터도 함께 지운다(감춰진 필터는 만들지 않는다) |
462
- | `keyboardNav` | `true` | `Ctrl+Shift+L` 로 목록에 들어가 `↑↓`·Enter·Esc 로 다룬다. 포커스가 사이드바에 없으면 아무 키도 가로채지 않으므로 켜 둬서 잃는 것이 없다 |
463
- | `keyboardCloseTab` | `true` | `Ctrl+W` 로 탭을 닫는다 — 터미널에서는 활성 탭, 목록이 키보드를 가졌으면 포커스 줄의 탭. `keyboardNav` 를 끄면 이 값과 무관하게 꺼진다. 끄면 `Ctrl+W` 가 터미널로 그대로 간다(셸의 앞 단어 지우기) |
464
- | `keyboardNavWrap` | `false` | 목록 끝에서 `↑↓` 가 반대쪽으로 감긴다. 끄면 끝에서 멈춘다 — "맨 아래에 왔다" 가 보이고 목록이 통째로 튀지 않는다. 끝↔끝은 Home/End 로 |
465
- | `viewerScrape` | `true` | 화면에 찍힌 파일 경로를 주워 최근 목록에 쌓는다. 끄면 끌어다 놓기·경로 입력만 |
466
- | `viewerDropOpen` | `ask` | 터미널 위에 파일을 끌어다 놓았을 때 — `ask` 물어본다 / `always` 패널에 띄운다 / `paste` 경로를 붙여넣는다 / `never` 개입하지 않는다(순정) |
467
- | `viewerPreload` | `true` | 에이전트가 만진 파일을 **닫혀 있는 동안에도** 패널에 얹어 둔다(최근 칩 + 다음에 열 때 띄울 파일). 끄면 아무것도 자동으로 하지 않는다. 설정 창의 `문서 패널에 읽어두기` |
468
- | `viewerAutoOpen` | `false` | 새 파일을 주우면 **닫힌 패널을 스스로 연다.** 기본 꺼짐 — 여닫기는 사람 몫이고, 내용은 위 `viewerPreload` 가 채워 둔다. 설정 창의 `패널 자동으로 열기` |
469
- | `viewerFollowMode` | `''` | (옛 값) 0.18.0 부터 위 토글 두 개로 갈랐다. `open`/`show`/`manual` 이 적혀 있으면 기동 때 한 번 두 토글로 옮기고 비운다 |
470
- | `viewerFollow` | `true` | (더 옛 값) 0.17.0 에 `viewerFollowMode` 로 옮겼다. `false` 였으면 마이그레이션이 `viewerPreload: false` 로 읽고 기본값으로 되돌린다 |
471
- | `viewerRecentMax` | `12` | 최근 목록에 남겨 두는 파일 수 |
472
- | `imeOrderGuard` | `true` | pty 에 바이트를 쓰기 전에 조합 중인 한글 음절을 먼저 확정한다 (아래 "한글 입력") |
473
- | `releaseHomeEnd` | `true` | Home / End 를 Tabby 핫키에서 걷어내 xterm 순정 경로로 돌려준다 |
474
- | `idleAfterMs` | `2500` | 이 시간 동안 출력이 없으면 `대기` 로 |
475
- | `autoDetect` | `true` | 출력·제목 패턴으로 상태 추론 |
476
- | `showElapsed` | `true` | 경과 시간 표시 |
477
- | `sortByStatus` | `false` | 사이드바 탭을 상태 우선순위(승인대기 → 오류 → 한도 도달 → 진행중 → 완료 → 대기)로 정렬한다. 같은 상태끼리는 탭 순서 유지. 끄면 순정 탭바와 같은 순서 |
478
- | `dragAutoScroll` | `true` | 줄을 끌 때 목록 끝에서 저절로 스크롤된다. 끄면 손을 뗀 뒤 스크롤하고 다시 끌어야 하지만, 그 대신 **맨 끝 줄 뒤에 놓는 조작이 미끄러지지 않는다** |
479
- | `keepRenderingWhenHidden` | `true` | 창이 가려져 있어도 사이드바를 갱신한다. 끄면 상태 변화가 최대 1분까지 늦게 보일 수 있다 |
480
- | `subagentCount` | `true` | 사이드바 줄에 도는 서브에이전트 개수를 보인다. 0 개면 아무것도 그리지 않으므로 켜 둬서 잃는 것이 없다. 끄면 대화 기록을 **읽지도 않는다** |
481
- | `enterAsLabel` | `true` | Enter 로 프롬프트를 보낼 때 입력창 원문을 작업 라벨로 삼는다 |
482
- | `labelAsTitle` | `true` | 사이드바 제목 줄에 탭 제목 대신 작업 라벨을 쓴다. Tabby 의 탭 제목 자체는 건드리지 않는다 |
483
- | `noTabRecovery` | `false` | 기동 시 지난 탭을 복원하지 않는다 — Tabby `recoverTabs` 를 false 로 강제. 복원되는 건 셸뿐이고 안의 Claude 세션은 죽어 있어 의미가 없다 (설정 창에서 켠다) |
484
- | `notifyChannel` | `true` | 훅이 보낸 상태를 받는 통로(로컬 TCP + 상태 파일). 훅을 설치하면 자동으로 켜진다 |
485
- | `notifyPort` | `47500` | 그 TCP 포트(127.0.0.1 전용). 물려 있으면 임의 포트로 물러나고 실제 번호는 `%LOCALAPPDATA%\tabby-agentdeck\port` 에 적힌다 |
486
- | `hookPromptDismissed` | `false` | 기동 시 뜨는 훅 설치 안내를 다시 띄우지 않는다 |
487
- | `claimCtrlV` | `true` | `Ctrl+V` 를 캡처 단계에서 직접 처리한다. 기동 시 `hotkeys.paste`·`agentdeck-paste` **양쪽에서** `Ctrl-V` 를 뺀다(두 번 붙는 것 방지). `false` 면 리터럴 0x16 이 앱으로 가고 **붙여넣기는 안 된다** |
488
- | `pasteImageWithCtrlV` | `true` | 클립보드에 이미지만 있으면 텍스트 붙여넣기 대신 이미지 붙여넣기 키를 보낸다 |
489
- | `imagePasteKey` | `alt-v` | 그때 보낼 키. `ctrl-v`(0x16) 는 Claude Code·Codex 둘 다, `alt-v`(ESC v) 는 Claude Code 전용 |
490
- | `claimRightClick` | `true` | 우클릭을 플러그인이 처리한다 (Tabby 의 `terminal.rightClick` 은 `off` 로) |
491
- | `rightClickMenuMs` | `250` | 이 시간 이상 누르면 붙여넣기 대신 컨텍스트 메뉴 |
492
- | `terminalOpacity` | `75` | 터미널 배경 불투명도(%). 100 미만이면 `tabby-background` 의 배경 이미지가 비친다. 100 = 순정 |
493
- | `sidebarOpacity` | `75` | 사이드바 / 창 여백 불투명도(%) |
494
- | `clipBackgroundToTerminal` | `true` | `tabby-background` 이미지를 터미널 영역으로 잘라 사이드바 밑까지 비치지 않게 한다 |
495
- | `screenWatch` | `true` | 2초마다 화면이 깨졌는지 판정해 `~/.agentdeck-screen.log` 에 기록만 한다 (복구는 하지 않음). 4MB 를 넘으면 `.1` 로 밀린다 |
496
- | `autoRepairScreen` | `false` | 깨졌다고 판정되면 조용히 화면 복구까지 한다 |
497
- | `autoRepairMinStreak` | `2` | 깨짐이 이만큼 연속으로 보여야 복구한다 (그리는 도중의 중간 프레임 오탐 방지) |
498
- | `autoRepairCooldownMs` | `10000` | 자동 복구 후 이만큼은 다시 하지 않는다 |
499
- | `autoRepairMaxPerTab` | `3` | 한 탭에서 자동 복구 최대 횟수. 0 = 무제한 |
500
- | `repairHard` | `false` | 화면 복구가 `xterm.reset()` 까지 한다 (스크롤백도 지워진다) |
501
- | `repairSendRedrawKey` | `false` | 화면 복구 마지막에 `Ctrl+L` 을 보낸다. **끄는 것이 기본** — Claude Code 는 이걸 재렌더가 아니라 **화면 지우기**로 받아 보고 있던 대화를 스크롤백으로 밀어낸다 (2026-09-11 채증). 켜면 자동 복구에도 적용된다 |
502
- | `rootProfile` | `false` | 작업 루트 프로필을 만들어 기본 프로필로 삼는다 (설정 창에서 켠다) |
503
- | `rootProfileName` | `Agent Root` | 그 프로필 이름 |
504
- | `rootProfileCwd` | `''` | 새 탭이 열릴 경로. 비우면 프로필을 만들지 않는다. 슬래시로 적는다 (예: `D:/Project`) |
505
- | `rootProfileCommand` | `powershell.exe` | 셸 |
506
- | `rootProfileArgs` | `-NoLogo -ExecutionPolicy Bypass` | 셸 인자. `Bypass` 는 npm 전역 `.ps1` 래퍼(`claude` 등)가 실행 정책에 막히지 않게 한다 — 그 세션에만 적용 |
507
- | `rootProfileEnv` | `TERM=xterm-256color`, `COLORTERM=truecolor` | 셸 환경변수 (빠진 것만 채운다) |
508
- | `alertFlash` | `true` | 창이 뒤에 있을 때 탭이 `승인대기`/`오류`/`한도 도달` 로 넘어가면 작업표시줄 아이콘을 깜빡인다. 창이 포커스를 받으면 멈춘다 |
509
- | `alertBadge` | `true` | 작업표시줄 아이콘 위에 `승인대기`+`오류`+`한도 도달` 탭 개수를 뱃지(원+숫자)로 얹는다. 0 이면 지운다 |
510
- | `alertToast` | `false` | 그때 OS 토스트도 띄운다. 누르면 창을 앞으로 가져오고 그 탭을 고른다 |
511
-
512
- ## 문제 신고
513
-
514
- 버그를 만났으면 **설정 → AgentDeck → 문제 신고 → `모으기`** 를 누른다.
515
- 진단 로그를 zip 하나로 묶고 그 파일이 있는 폴더를 열어 주므로, 그 zip 을 이슈에 붙이면 된다.
516
-
517
- 담기는 것
518
-
519
- | 파일 | 내용 |
442
+ | `enabled` | `true` | Sidebar + 4:3 layout on/off |
443
+ | `aspectW` / `aspectH` | `4` / `3` | Terminal viewport ratio |
444
+ | `sidebarDock` | `right` | Sidebar position `left` / `right` / `top` / `bottom`. Also changed by dragging the header |
445
+ | `sidebarWidth` | `0` | Width in px when docked left/right. 0 = derived from the aspect ratio |
446
+ | `sidebarHeight` | `200` | Height in px when docked top/bottom |
447
+ | `sidebarMin` / `sidebarMax` | `200` / `560` | Range for the derived width (px). For exactly 4:3 on a wide monitor, set `sidebarMax` to `window width − window height × 4/3` |
448
+ | `sortByStatus` | `false` | Sort by urgency (waiting → error → rate limited → running → done → idle). Turning it on **blocks drag reordering** — a moved row would snap back on the next render |
449
+ | `collapsedGroups` | `[]` | Keys of collapsed groups. Clicking a header adds one here. `Expand all` in the settings window empties it |
450
+ | `viewerOpen` | `false` | Whether the preview panel is open. Toggled by `▤` / `agentdeck-view`, or set when **it opens itself on a new file**, and restored on next start. Not a value you set by hand |
451
+ | `viewerDock` | `right` | Which side the panel attaches to, `left` / `right`. On the same side as the sidebar, the sidebar takes the outer edge |
452
+ | `viewerWidth` | `420` | Panel width in px. Changed by dragging the divider. In a narrow window, capped at `window width − 320 − 140` |
453
+ | `searchBox` | `true` | Show the search row in the sidebar. Turning it off also clears any active filter (no hidden filters) |
454
+ | `keyboardNav` | `true` | `Ctrl+Shift+L` into the list, then `↑↓`/Enter/Esc. Nothing is intercepted while focus is elsewhere, so leaving it on costs nothing |
455
+ | `keyboardCloseTab` | `true` | `Ctrl+W` closes a tab — the active one from the terminal, the focused row when the list has the keyboard. Off (or with `keyboardNav` off) `Ctrl+W` goes to the terminal as delete-previous-word |
456
+ | `keyboardNavWrap` | `false` | `↑↓` wrap around at the ends. Off, they stop — you can see you are at the bottom and the list does not jump wholesale. End-to-end is Home/End |
457
+ | `viewerScrape` | `true` | Pick up file paths printed on screen into the recent list. Off, only drag-drop and typed paths |
458
+ | `viewerDropOpen` | `ask` | When a file is dropped on the terminal — `ask` / `always` open in panel / `paste` the path / `never` (stock behaviour) |
459
+ | `viewerPreload` | `true` | Keep files the agent touched loaded **even while the panel is closed** (recent chips + what to show on next open). Off, nothing happens automatically. `Preload into the panel` in the settings window |
460
+ | `viewerAutoOpen` | `false` | **Open the closed panel by itself** on a new file. Off by default — opening is yours to do, and the contents are kept current by `viewerPreload` above. `Open the panel automatically` in the settings window |
461
+ | `viewerFollowMode` | `''` | (old value) Split into the two toggles above in 0.18.0. An `open`/`show`/`manual` left here is migrated once on startup and cleared |
462
+ | `viewerFollow` | `true` | (older value) Moved to `viewerFollowMode` in 0.17.0. A `false` is read as `viewerPreload: false` by the migration and reset to the default |
463
+ | `viewerRecentMax` | `12` | How many files stay in the recent list |
464
+ | `imeOrderGuard` | `true` | Commit a composing syllable before writing bytes to the pty (see "IME input") |
465
+ | `releaseHomeEnd` | `true` | Take Home / End out of Tabby's hotkeys and hand them back to xterm's own path |
466
+ | `idleAfterMs` | `2500` | No output for this long means `idle` |
467
+ | `autoDetect` | `true` | Infer status from output and title patterns |
468
+ | `showElapsed` | `true` | Show elapsed time |
469
+ | `dragAutoScroll` | `true` | The list scrolls by itself at the edges while dragging. Off, you have to drop, scroll and drag again — but **dropping past the last row stops slipping** |
470
+ | `keepRenderingWhenHidden` | `true` | Keep the sidebar updating while the window is covered. Off, a status change can show up to a minute late |
471
+ | `subagentCount` | `true` | Show the running subagent count on a row. Nothing is drawn at zero, so leaving it on costs nothing. Off, transcripts are **not read at all** |
472
+ | `enterAsLabel` | `true` | Take the input box text as the task label when Enter sends a prompt |
473
+ | `labelAsTitle` | `true` | Use the task label instead of the tab title on the sidebar title row. Tabby's own tab title is untouched |
474
+ | `noTabRecovery` | `false` | Do not restore previous tabs on startup — forces Tabby's `recoverTabs` to false. Only the shell is restored and the Claude session inside it is dead, so it is meaningless (turn it on in the settings window) |
475
+ | `notifyChannel` | `true` | The channel hook reports arrive on (local TCP + status file). Installing the hook turns it on automatically |
476
+ | `notifyPort` | `47500` | That TCP port (127.0.0.1 only). If taken, it falls back to a random port and the real number is written to `%LOCALAPPDATA%\tabby-agentdeck\port` |
477
+ | `hookPromptDismissed` | `false` | Do not show the hook-install prompt on startup again |
478
+ | `claimCtrlV` | `true` | Handle `Ctrl+V` in the capture phase. On startup, `Ctrl-V` is removed from **both** `hotkeys.paste` and `agentdeck-paste` (this is what stops the double paste). `false` sends a literal 0x16 to the app and **paste stops working** |
479
+ | `pasteImageWithCtrlV` | `true` | With only an image on the clipboard, send the image-paste key instead of pasting text |
480
+ | `imagePasteKey` | `alt-v` | Which key that is. `ctrl-v` (0x16) covers Claude Code and Codex; `alt-v` (ESC v) is Claude Code only |
481
+ | `claimRightClick` | `true` | The plugin handles right-click (Tabby's `terminal.rightClick` is set to `off`) |
482
+ | `rightClickMenuMs` | `250` | Hold longer than this for the context menu instead of paste |
483
+ | `terminalOpacity` | `75` | Terminal background opacity (%). Below 100 lets a `tabby-background` image show through. 100 = stock |
484
+ | `sidebarOpacity` | `75` | Sidebar / window margin opacity (%) |
485
+ | `clipBackgroundToTerminal` | `true` | Clip the `tabby-background` image to the terminal area so it does not show under the sidebar |
486
+ | `screenWatch` | `true` | Judge every two seconds whether the screen is broken and **only record** it to `~/.agentdeck-screen.log` (no repair). Rolls to `.1` past 4 MB |
487
+ | `autoRepairScreen` | `false` | Quietly run screen repair when it is judged broken |
488
+ | `autoRepairMinStreak` | `2` | Require this many consecutive broken readings before repairing (so a half-drawn frame is not mistaken for one) |
489
+ | `autoRepairCooldownMs` | `10000` | Do not repair again for this long after an automatic repair |
490
+ | `autoRepairMaxPerTab` | `3` | Maximum automatic repairs per tab. 0 = unlimited |
491
+ | `repairHard` | `false` | Screen repair also runs `xterm.reset()` (which clears the scrollback) |
492
+ | `repairSendRedrawKey` | `false` | Send `Ctrl+L` at the end of a repair. **Off is the default** — Claude Code takes it as a **screen clear**, not a redraw, and pushes the conversation you were reading into the scrollback (captured 2026-09-11). On, it applies to automatic repairs too |
493
+ | `rootProfile` | `false` | Create a working-root profile and make it the default (turn it on in the settings window) |
494
+ | `rootProfileName` | `Agent Root` | That profile's name |
495
+ | `rootProfileCwd` | `''` | Where new tabs open. Empty means the profile is not created. Write it with forward slashes (e.g. `D:/Project`) |
496
+ | `rootProfileCommand` | `powershell.exe` | The shell |
497
+ | `rootProfileArgs` | `-NoLogo -ExecutionPolicy Bypass` | Shell arguments. `Bypass` keeps global npm `.ps1` wrappers (`claude` and friends) from being blocked by execution policy — for that session only |
498
+ | `rootProfileEnv` | `TERM=xterm-256color`, `COLORTERM=truecolor` | Shell environment variables (only missing ones are filled in) |
499
+ | `alertFlash` | `true` | Flash the taskbar icon when a tab moves to `waiting`/`error`/`rate limited` while the window is behind. Stops when the window is focused |
500
+ | `alertBadge` | `true` | Draw a badge (circle + number) on the taskbar icon with the count of `waiting` + `error` + `rate limited` tabs. Cleared at zero |
501
+ | `alertToast` | `false` | Also raise an OS toast. Clicking it brings the window forward and selects that tab |
502
+
503
+ ## Reporting a problem
504
+
505
+ **[Open an issue](https://github.com/jghwang2/tabby-agentdeck/issues/new/choose)** — a bug report or a feature request.
506
+
507
+ Before you write it up, press **Settings → AgentDeck → Report a problem → `collect`**.
508
+ It bundles the diagnostics into a single zip and opens the folder it is in, so you can attach that zip to the issue.
509
+
510
+ What goes in
511
+
512
+ | File | Contents |
520
513
  |---|---|
521
- | `report.txt` | 플러그인/Tabby/Electron 버전, OS, 설정 값(도킹·화면비·`useConPTY` 등), 이 세션의 최근 진단 200줄 |
522
- | `agentdeck-diag.log` | `~/.agentdeck-diag.log` — 세션 머리말, 배치·입력·pty 판정, 잡히지 않은 예외와 스택, 삼켜진 실패(`CATCH …`) |
523
- | `agentdeck-diag.log.1` | 그 직전 분량 (2MB 를 넘겨 밀려난 것) |
524
- | `agentdeck-screen.log` | **"화면 원문까지 넣기" 를 켤 때만.** 깨진 순간의 터미널 화면이 글자 그대로 들어간다 |
514
+ | `report.txt` | Plugin/Tabby/Electron version, OS, settings (docking, aspect ratio, `useConPTY` …), the last 200 diagnostic lines of this session |
515
+ | `agentdeck-diag.log` | `~/.agentdeck-diag.log` — session header, batching/input/pty decisions, uncaught exceptions with stacks, swallowed failures (`CATCH …`) |
516
+ | `agentdeck-diag.log.1` | The previous rollover (pushed aside past 2 MB) |
517
+ | `agentdeck-screen.log` | **Only when "include screen contents" is on.** The terminal screen, verbatim, at the moment it broke |
525
518
 
526
- 알아 둘 것
519
+ Worth knowing
527
520
 
528
- - 로그는 **기동해도 지워지지 않는다.** 2MB 를 넘길 때 `.1` 로 한 세대 밀리므로, 어제 겪은 문제도 대개 남아 있다.
529
- - 로그에는 **탭 제목과 열어 본 파일 경로**가 들어간다. 보내기 전에 열어 봐도 되고, 화면 원문은 기본으로 빠진다.
530
- - 설정 창을 열 수 없을 만큼 깨졌으면 devtools 콘솔에서 `__agentdeck.collectDiag()` — 같은 zip 을 만들고 경로를 돌려준다.
531
- 최근 진단 줄만 보려면 `__agentdeck.kickLog`.
521
+ - Logs **are not cleared on startup.** They roll one generation to `.1` past 2 MB, so yesterday's problem is usually still there.
522
+ - The logs contain **tab titles and the paths of files you opened**. Read it before sending if you like; screen contents are excluded by default.
523
+ - Too broken to open the settings window? From the devtools console, `__agentdeck.collectDiag()` builds the same zip and returns its path.
524
+ For just the recent diagnostic lines, `__agentdeck.kickLog`.
532
525
 
533
- ## 알려진 문제
526
+ ## Known issues
534
527
 
535
- ### Tabby 1.0.235 에서 새 탭이 열리지 않음
528
+ ### New tabs will not open on Tabby 1.0.235
536
529
 
537
530
  ```
538
531
  Error: ENOENT, node_modules\node-pty\lib\conpty_console_list_agent not found in ...\resources\app.asar
539
532
  ```
540
533
 
541
- Tabby 설치본의 패키징 버그로 플러그인과 무관하다. ConPTY 를 끄면 이 경로를 타지 않는다.
534
+ A packaging bug in the Tabby build, unrelated to this plugin. Turning ConPTY off avoids that path.
542
535
 
543
536
  ```yaml
544
537
  # %APPDATA%\tabby\config.yaml
@@ -546,8 +539,24 @@ terminal:
546
539
  useConPTY: false
547
540
  ```
548
541
 
549
- ## 라이선스
542
+ ## Development
550
543
 
551
- MIT
544
+ ```powershell
545
+ npm install
546
+ npm run build # runs tools/sync-version.js first (prebuild)
547
+ npm test # unit tests + Codex regression
548
+ npm run typecheck
549
+ ```
552
550
 
553
- 개발 절차·구조·설계 근거·실측 함정은 리포의 `docs/DEVELOPMENT.md`, 회귀 체크리스트는 `docs/REGRESSION.md` 에 있다.
551
+ **`version` in `package.json` is the single source of truth** — `package-lock.json` and the four web pages under
552
+ `docs/` are derived from it by `tools/sync-version.js`, and `test/version.test.js` fails on drift.
553
+ Releases go through one command (`npm run release -- 1.1.4`), which stamps the version, derives, tests, commits and tags.
554
+ `test/tags.test.js` checks that every committed version has a matching tag.
555
+
556
+ Development procedure, architecture, design rationale and the measured pitfalls are in
557
+ [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md); the regression checklist is in [`docs/REGRESSION.md`](docs/REGRESSION.md);
558
+ npm publishing is in [`docs/NPM-PUBLISH.md`](docs/NPM-PUBLISH.md).
559
+
560
+ ## License
561
+
562
+ MIT