# Clawd on Desk

> 도입을 실측으로 정당화하려다 실패했습니다. 실패했다는 사실을 그 자리에 적어 뒀습니다.

- 수치: 7종 중 순증 1.5
- 사람이 보는 화면: https://aitryed.com/ko/teardowns/harness/clawd-on-desk/
- 반대 언어: https://aitryed.com/en/teardowns/harness/clawd-on-desk/index.md
- 저장소: https://github.com/rullerzhou-afk/clawd-on-desk
- 이 사이트 안내(AI용): https://aitryed.com/ko/llms.txt

---

**화면 구석에 사는 픽셀 캐릭터입니다. AI가 지금 무슨 일을 하고 있는지에 따라 행동이 바뀝니다. 스물한 편 중 제 컴퓨터에 «실제로 들어온 유일한 것»인데, 생산성 근거로는 정당화되지 않았습니다. 그 사실을 그 자리에 적어 뒀습니다.**

> **[도판]** 에이전트를 고쳐 쓰지 않는다. 각 에이전트가 이미 제공하는 훅 규격에 자기 스크립트를 얹을 뿐이다.
>
> 세 층으로 도는 구조. 설치기가 에이전트 21종의 설정 파일에 훅을 심고, 에이전트가 이벤트마다 훅 스크립트를 띄우면 그 스크립트가 로컬 HTTP로 상태를 보내고, 앱이 상태를 모아 그림 하나로 줄여 그린다. 권한 요청만 앱에서 에이전트로 역방향으로 답이 돌아간다.

## 보통 데스크톱 캐릭터와 다른 점

화면에 캐릭터를 띄워 두는 프로그램은 옛날부터 있었습니다. 마우스를 따라다니거나 가끔 말을 겁니다.

이건 다릅니다. **AI가 지금 무엇을 하고 있는지를 실시간으로 구독**합니다.

| AI가 하는 일 | 캐릭터가 하는 짓 |
|---|---|
| 아무것도 안 함 | 두리번거리며 돌아다님 |
| 생각 중 | 생각 말풍선 |
| 작업 중 | 타자 치는 시늉 |
| **동시에 세 가지 이상** | **공사 현장처럼 바쁘게** |
| 보조 일꾼을 부림 | 헤드폰 쓰고 저글링 |
| **허락을 구하는 중** | **말풍선 + 창을 자동으로 앞으로** |
| 다 끝남 | 기뻐하며 효과음 |

재미있는 건 **단순 1:1이 아니라는 것**입니다. 같은 「작업 중」이라도 **동시에 몇 개를 돌리는지 세어서** 그림이 달라집니다.

그리고 실용적인 게 하나 있습니다 — **허락을 구할 때 창을 자동으로 앞으로 끌어옵니다.** 딴짓하다가 「허락해 주세요」를 못 보고 10분을 날리는 일이 줄어듭니다.

## 그런데 이 물건의 진짜 값어치는 캐릭터가 아니었습니다

겉보기는 픽셀 캐릭터인데, <strong>실제로 배울 게 있던 건 「설치하는 방식」</strong>이었습니다.

이 프로그램이 동작하려면 **남의 설정 파일 26개에 자기 배선을 심어야** 합니다. 그런데 그 설정 파일들은 **제가 이미 쓰고 있는 것**입니다. 잘못 건드리면 제 작업 환경이 망가집니다.

이 사람이 그걸 어떻게 처리했는지가 교재였습니다.

| 방식 | 무슨 사고를 막나 |
|---|---|
| **덮어쓰지 않고 «덧붙인다»** | 원래 있던 설정이 날아가는 사고 |
| **자기가 심은 줄에 표시를 남긴다** | 지울 때 **남의 줄까지 같이 지우는 사고** |
| **설치기가 «제거기»를 같이 심는다** | 나중에 뺄 수 없어서 못 지우는 상태 |

세 번째가 특히 좋습니다. 보통 설치 프로그램은 **넣는 것만** 만듭니다. 빼는 건 「나중에 하지 뭐」가 되고, 그래서 안 만들어집니다.

**넣으면서 빼는 길을 같이 만드는 것** — 이건 제가 규격으로 가져왔습니다.

## 실제로 확인해 봤습니다 — 그리고 한 건 깨졌습니다

문서에 적힌 대로 도는지 직접 확인했습니다. 위 표의 <strong>「보조 일꾼이 둘 이상이면 공 세 개로 바뀐다」</strong>를 재 봤습니다.

판정 근거를 **기록과 화면 두 갈래**로 잡았습니다. 기준 그림은 원본 창고에서 받아서 확정했습니다.

| 보조 일꾼 | 기록상 | 실제 화면 | |
|---|---|---|---|
| 1개 | 저글링 상태 | 헤드폰 | 규격대로 |
| **2개** | 저글링 상태 | **여전히 헤드폰** | **규격 위반** |
| 끝난 뒤 | 작업 중으로 복귀 | 타자 | 규격대로 |

**기록은 맞는데 화면이 안 바뀌었습니다.**

이게 이 확인 방법이 필요한 이유입니다. **기록만 봤으면 「정상」으로 통과**했을 것입니다. 화면을 안 봤으면 몰랐습니다.

## 제 것과 대 봤더니 — 일곱 중 넷은 이미 있었습니다

이 프로그램이 파는 기능 일곱 개를 제 환경과 대 봤습니다.

- **넷은 이미** 다른 형태로 돌고 있었습니다
- 남은 셋도 실제로 재 보니 **하나 반**으로 줄었습니다

## 설치 전후를 재서 「안 망가졌다」를 확인했습니다

남의 설정 파일 26개를 건드리는 물건이라, **설치 전 상태를 통째로 찍어 두고 설치 후와 대조**했습니다.

| 잰 것 | 결과 |
|---|---|
| 안전장치 개수 | **15개 → 30개** (늘기만 함) |
| **사라진 것** | **0건** |
| 상태 표시줄 | 변경 없음 |

<strong>「사라진 것 0건」</strong>이 핵심입니다. 위에서 본 「표시를 남기고 자기 것만 건드린다」가 실제로 작동한 것입니다.

## 그래서 판정 — 「취향이었다」고 적어 뒀습니다

여기가 이 편에서 제일 중요한 자리입니다.

저는 이걸 **설치했습니다.** 스물한 편 중 유일합니다.

그런데 위에서 보셨듯이 **일곱 중 넷은 이미 있었고, 남은 것도 하나 반**입니다. 생산성이 올라간다는 증거가 없습니다.

그래서 **정직하게 적었습니다.**

> **생산성 때문에 넣은 게 아니다. 그냥 쓰고 싶어서 넣었다.**

왜 굳이 적었냐면 — **기억이 나중에 바뀌기 때문**입니다.

몇 달 지나면 사람은 자기 선택을 합리적으로 고쳐 씁니다. 「그때 효율 때문에 넣었지」로 기억이 변합니다. 그러면 **다음에 비슷한 결정을 할 때 잘못된 근거를 쓰게** 됩니다.

**당시 이유를 그 자리에 적어 두는 것**이 유일한 방어입니다.

## 여기부터는 자세한 기록입니다

**설치했고, 그 설치는 생산성 근거로 정당화되지 않았습니다.** 이 앱이 파는 기능 일곱 가지를 제 환경과 대조해 보니 **넷이 이미 돌고 있었고**, 남은 셋도 실측하니 **하나 반**으로 줄었습니다. 그런데 값어치는 앱이 아닌 데서 나왔습니다 — 이 레포는 **남의 설정 파일 26종에 자기 배선을 심고, 안 깨뜨리고, 되돌릴 수 있게** 만드는 물건이고, 그 방식 세 가지를 규격으로 가져왔습니다.



## 무엇을 하는 물건인가

**데스크톱 펫이다.** 다만 마우스를 따라다니는 종류가 아니라 **AI 코딩 에이전트의 생애 이벤트를 구독한다.** 프롬프트를 넣으면 생각하고, 툴이 돌면 타이핑하고, 서브에이전트가 뜨면 저글링하고, 권한 요청이 오면 말풍선을 띄우고, 방치하면 잔다.

지원 대상이 **에이전트 21종**이다. Claude Code·Codex CLI·Copilot CLI·Gemini CLI·Cursor Agent·Kiro·opencode 등등. 설정 스키마가 제각각이라(JSON·주석 있는 JSON·플러그인 패키지·파이썬 플러그인) **설치기만 26개**를 따로 갖고 있다.

규모가 장난감이 아니다. 훅과 소스 자바스크립트만 5.8MB, 테스트가 384개 파일이고 **어댑터마다 각각 붙어 있다.** 별 5,894개, 커밋 1,906건, 기여자 91명.

### 이벤트를 상태로 옮기는 규칙

단순 1:1 매핑이 아니다. **동시 세션 수와 서브에이전트 수를 세서 티어를 올린다** — 같은 이벤트가 세션 수에 따라 다른 그림이 된다.

| 에이전트 이벤트 | 상태 | 그림 |
|---|---|---|
| 무활동 | idle | 커서 눈추적 · 랜덤 순찰 |
| 프롬프트 제출 | thinking | 생각 말풍선 |
| 툴 실행 — 1세션 | working | 타이핑 |
| 툴 실행 — **3세션 이상** | working (건설) | 건설 |
| 서브에이전트 1개 | juggling | 헤드폰 |
| 서브에이전트 **2개 이상** | juggling (2티어) | **공 세 개 저글링** |
| 권한 요청 | attention | 권한 카드 + 터미널 자동 포커스 |
| 작업 완료 | celebration | 기뻐하기 + 효과음 |

마지막에서 두 번째 줄이 뒤에 문제가 된다.

## 배선을 심는 방식이 이 레포의 본체다

겉보기는 픽셀 게인데, 실제로 값나가는 건 **남의 설정 파일을 안 깨뜨리는 방법**이다. 훅과 크론을 손으로 심는 사람에게는 이쪽이 교재다.

**① 설치기가 회수기를 같이 심는다.** 설치할 때 제거 스크립트를 **설치 폴더로 복사해 두고**, 마커 파일에 **설치 당시의 사용자 홈**을 적어 둔다. 제거하면 그 파일을 읽어 그때의 환경을 복원하고 21종 설정에서 자기 배선만 걷어낸다. 요점 둘 — **레포가 사라져도 회수가 되고, 제거 시점 환경이 달라도 정확한 대상을 찾는다.** 노드가 안 깔려 있어도 되도록 앱 바이너리를 노드처럼 써서 회수 스크립트를 돌린다.

**② 덧붙이되 덮어쓰지 않는다.** 설치기 첫머리 주석이 계약을 못 박는다 — *"기존 훅을 덮어쓰지 않는다. 배열에 덧붙인다."* 임시 파일에 쓰고 원자적으로 교체하고, **이미 있던 파일만** 백업하고 보관 개수를 관리한다. 배열이 아닌 값이 오면 배열로 감싸서 보존한다.

**③ 마커로 소유권을 판정한다.** 상태줄이 이미 있으면 마커 문자열을 보고 **남의 것이면 손대지 않고 로그만 남긴다.** 체이닝은 명시 요청이 있을 때만.

세 가지 다 **코드가 아니라 규격만** 가져왔다. AGPL-3.0이고 로컬 HTTP 서버를 띄우는 구조라 네트워크 조항이 죽은 문구도 아니어서, 한 줄이라도 옮기면 파생물 전체가 공개 의무에 걸린다.

## 확인된 결함 — 문서가 약속한 티어가 안 올라간다

위 표의 "서브에이전트 2개 이상 → 공 세 개"를 실제로 확인했다. 판정 근거를 **로그와 화면 두 갈래**로 잡고, 기준 이미지는 레포 원본 두 종을 받아 확정했다.

| 서브에이전트 | 로그 | 화면 | |
|---|---|---|---|
| 1개 | `state=juggling` | 헤드폰 | 규격대로 |
| **2개** | `state=juggling` | **여전히 헤드폰** | **규격 위반** |
| 종료 후 | `state=working` 복귀 | 타이핑 | 규격대로 |

**이벤트는 정확히 도착하고 논리 상태도 전이하는데, 그림이 1개짜리 티어에 머문다.** 재현 2회, 대조군 1개 조건은 정상.

여기서 하마터면 틀릴 뻔했다. **로그에 `state=juggling`이 찍힌 것만 보고 "저글링 된다"로 닫을 수 있었다.** 티어는 로그에 안 찍힌다 — **어느 그림을 골랐는지는 화면에만 있다.** 시각 상태를 판정하면서 스크린샷을 빼면 절반만 검증하고 통과시킨다.

배제해야 할 오답도 있었다. 문서상 "동시 세션 2개"도 같은 헤드폰 그림이라, 제가 본 게 서브에이전트가 아니라 **세션 수 때문**일 수 있었다. 캡처 시점 로그가 `juggling`(`working`이 아니라)임을 확인해 걸렀다. **이 확인을 빼먹었으면 정반대 결론이 나온다.**

업스트림에 등록했다. 배제 근거 셋과 함께, 로그에 티어와 에셋 이름을 남겨 달라는 제안을 붙여서.

그리고 문서 쪽에도 함정이 하나 있다. 조사 문서 하나가 "이 앱이 안 떠 있으면 에이전트가 파일 편집을 전부 자동 거부한다"고 적고 상류 수정을 기다린다고 끝맺는데, **그 상류 이슈는 석 달 전에 닫혔다.** 문서만 그 시점에 멈춰 있다 — 읽고 "지금도 터진다"로 오판하기 쉽다.

## 내 환경에 대보니 넷이 이미 있었다

설치 전 스냅샷을 떠 두고 대조했다. **훅 15개 → 30개, 소실 0건, 상태줄 변경 없음.** 위 ③번 마커 소유권 판정이 실제로 작동한 것이고, 파괴 위험은 이걸로 배제했다.

> **[도판]** 설치 전 <code>settings.json</code>에 무엇이 있었는지로 판정했다. 일곱 중 넷이 이미 돌고 있었다.
>
> 이 앱이 파는 기능 일곱 가지와 내 환경에 이미 있던 것이 크게 겹친다. 겹치는 넷은 완료 알림·상태 표시·자리 비움 통보·세션 종료 처리이고, 겹치지 않는 셋만이 새로 얻는 것이다. 실측 뒤 그 셋마저 1.5로 줄었다.

중복 넷의 정체는 이렇다. **완료 알림**은 이미 종료 훅이 토스트를 띄우고 있었고, **현재 상태**는 상태줄이 상시 표시하고 있었고, **자리 비움 중 통보**는 슬랙 자동 발화가 하고 있었고, **세션 종료 처리**도 훅 두 개가 하고 있었다.

**"완료 알림이 필요하다"고 느껴서 도구를 찾았는데, 그 일을 하는 것이 이미 있었다.** 이 조사의 실소득은 앱이 아니라 그 대조표다 — 다음에 비슷한 도구를 볼 때 이 표부터 채우면 도입 판정이 몇 분에 끝난다.

## 판정 — 취향이었다고 그 자리에 적었다

| | |
|---|---|
| 앱 설치 | 채택 — 파괴 위험은 실측으로 배제. 다만 근거는 아래대로 얄팍하다 |
| 규격 3종 (회수기 동반 · 설정 안전 · 마커 소유권) | **채택** — 셋 다 제 쪽 과거 사고와 1:1로 대응한다 |
| 코드 차용 | ⛔ 금지 — AGPL-3.0. 조건 없는 금지 |

> 이 설치는 생산성 근거로 정당화되지 않았다. 쓰고 싶어서 설치한 것이 맞다.

이 문장을 그 자리에 적어 둔 게 이 조사에서 제일 쓸모 있는 일이었다. **나중에 "효율 때문에 넣었다"로 기억이 바뀌기 때문이다.**

비용도 정직하게 적는다. 훅이 **툴 호출마다 프로세스를 하나 더 띄우므로** 파이프라인 런에서 지연이 붙을 수 있는데, **재보지 않았다.** 배선에서 연역한 것이지 실측이 아니라 아직 추정치다. 승격하려면 같은 입력으로 설치 전후 런을 한 번씩 돌려 구간 시간을 비교해야 한다.

안전 판정에도 유효기간이 있다. 제가 확인한 건 **설치 직후 1회 스냅샷**인데, 이 앱은 **실행할 때마다 훅을 재동기화한다.** 즉 앞으로 매 실행마다 같은 병합이 반복되고, 업데이트가 병합 로직을 바꾸면 조용히 달라진다. 다음 업데이트 뒤에 훅 개수와 제 훅 존재를 한 번 더 봐야 이 판정이 유지된다.

⚠ 그리고 상시 가드 하나. **제가 거절하지 않았는데 "도구 사용이 거절됐다"가 뜨면 이 앱이 꺼진 채 권한 훅만 살아 있는 경우를 의심한다.** 위 도판의 점선 하나가 그 경로다 — 증상이 조용해서 무인 런을 통째로 날릴 수 있는 유형이다.
