클로드 코드 세션을 픽셀 사무실의 캐릭터로 다루는 로컬 웹 UI.
폴더 하나가 방 하나, 세션 하나가 캐릭터 하나입니다. 캐릭터에게 다가가 말을 걸면 그 세션에 명령이 들어가고, 같은 대화가 터미널·데스크톱 앱에서도 그대로 보입니다. 별도의 세션을 새로 파는 게 아니라 여러분이 이미 쓰던 세션을 그대로 붙잡습니다.
캐릭터 = 세션 = 폴더 하나
| Node.js | 22 이상 (24 이상 권장 — 22 에서는 실험 기능 경고가 뜹니다) |
| 클로드 코드 CLI | claude 가 PATH 에 있어야 합니다. 최신 버전을 권합니다 — 오피스가 쓰는 명령줄 플래그(--append-system-prompt 등) 중 하나라도 없으면 캐릭터가 안 뜹니다. npm run doctor 가 어느 것이 없는지 짚어 줍니다 |
| 운영체제 | macOS · Windows |
| 데스크톱 앱 | 없어도 됩니다. 있으면 세션 제목·목록 날짜가 같이 맞춰집니다 |
서버만 켜 두면 됩니다. 데스크톱 앱을 띄워 둘 필요는 없습니다.
npm install
npm start브라우저에서 http://localhost:4300 을 엽니다.
처음에는 빈 사무실이 뜹니다. + 캐릭터 추가 로 직원을 앉히세요.
- 기존 세션에서 — 이미 하던 대화를 캐릭터로 데려옵니다
- 새로 만들기 — 폴더를 골라 새 캐릭터를 만듭니다
| 키 | |
|---|---|
WASD · 방향키 |
걷기 |
Space |
점프 |
1…9, 0 |
그 번호 캐릭터에게 말 걸기 (다가가지 않아도 됩니다) |
Z |
보고 있는 쪽으로 던지기 |
Enter |
대화 ↔ 이동 전환 |
Tab |
대화 기록창 접기/펼치기 |
? |
단축키 전체 목록 |
Esc |
꾸미는 중 손에 든 가구 내려놓기 |
기록창은 브라우저 절반으로 열립니다. 사이를 끌면 넓이가 바뀌고(두 번 누르면 기본값),
머리글의 가- 가+ 로 글씨 크기를 바꿉니다. 둘 다 브라우저에 기억됩니다.
아래 안내줄은 한 번씩 써 보면 그 항목부터 사라집니다. 익숙해지면 줄 자체가 없어집니다.
휴대폰에서는 캐릭터를 탭하면 대화, 바닥을 탭하면 이동입니다.
캐릭터에게 정해진 시각에 다시 지시가 들어가게 할 수 있습니다. 캐릭터가 스스로 겁니다.
schedule_self(prompt, cron | after_minutes) ← 캐릭터가 부르는 도구
list_my_schedules() · cancel_schedule(id)
클로드 코드의 CronCreate · ScheduleWakeup 은 그 프로세스 메모리에만 삽니다
(도구 설명에 nothing is written to disk 라고 적혀 있습니다). 캐릭터를 재우면 같이 죽습니다.
데스크톱 앱 쪽은 파일로 남지만 앱이 켜져 있을 때만 돕니다.
오피스 서버는 늘 떠 있으니, 여기가 예약을 들고 있는 게 제일 낫습니다.
- 예약이 걸린 캐릭터는 재우지 않습니다. 서버를 다시 켜면 알아서 깨웁니다
- 일하는 중이면 끝나는 대로 넣습니다 (6시간 넘게 밀리면 그 차례는 접습니다)
- 서버가 꺼져 있던 동안 밀린 건 몰아치지 않습니다 — 한 번만 따라잡습니다
- 앱과 달리
--resume으로 같은 세션에 이어 붙입니다. "버퍼가 몇 개 남았나" 같은 상태가 이어집니다
예약은 state/schedules.json 에 남습니다.
한도는 계정 전체가 나눠 씁니다. 그래서 캐릭터별이 아니라 헤더에 게이지 하나뿐입니다.
| 80% | 게이지가 경고색 |
| 95% | 예약을 멈춥니다. 헤더 아래 띠 + 사무실 정전 |
| 풀림 | 띠가 사라지고 예약 캐릭터가 자동 복귀 |
정전 중에도 전자시계와 예약 표식은 켜져 있습니다 — 그때 알아야 할 게 그 둘뿐이라서입니다. 캐릭터는 여전히 걸어다니고 던지기도 됩니다. 멈춘 건 AI 쪽이지 화면이 아닙니다.
사용량은 살아 있는
claude프로세스에서만 옵니다. 한도로 다 멈추면 소식을 들을 길이 없어서, 초기화 시각이 지나면 오피스가 먼저 풀고 깨웁니다. 아직 안 풀렸으면 다시 걸려 도로 잠깁니다.
이동 중에 Z 를 누르면 보고 있는 쪽으로 던집니다. 포물선을 그리고 한 번 튄 뒤 터집니다.
앉아 있는 캐릭터나 다른 접속자에게 맞으면 잠깐 흔들립니다 — 보기만 그럴 뿐,
세션에는 아무 영향도 없습니다.
던질 것은 🎨 모양 → 던지는 것 에서 고릅니다. 종이 뭉치 · 커피 · 공 · 별 · 하트 · 폭탄.
고른 건 이 브라우저에 기억되고, 던질 때 종류를 같이 실어 보내므로
같이 접속한 사람 화면에서도 같은 게 날아갑니다.
머리글의 🪑 꾸미기 를 누르면 아래에 가구 팔레트가 열립니다.
가구를 누른다 → 손에 들린다 → 사무실을 누른다 → 놓인다
- 한 번 든 가구는 계속 들려 있습니다. 의자 여섯 개를 연달아 놓을 수 있습니다
- 놓인 가구는 끌어서 옮깁니다
🧹 지우개를 켜고 누르면 치웁니다- 내려놓기는
Esc또는 오른쪽 버튼
특별 묶음에 전자시계가 있습니다. 놓으면 그 자리에 지금 시각이 뜨고 콜론이 1초마다 깜빡입니다.
예약이 "몇 시에 돈다" 로 말하니 사무실에 시계가 하나쯤 있는 게 편합니다 —
처음 켜면 대표님실에 하나 걸려 있고, 필요 없으면 지우개로 치우면 됩니다.
가구는 16px 격자에 붙고, 놓은 자리는 방 기준으로 기억합니다 — 좌석 수를 늘려 방이 커져도 가구가 방을 따라갑니다. 양탄자는 책상 밑으로 깔리고 나머지는 위에 얹힙니다.
인테리어 테마 다섯 개 전부에서 나옵니다. 시트 원본이 어두운 방에서 혼자 튀지 않도록
테마마다 색을 얇게 덧입힙니다. 놓은 배치는 state/config.json 에 남고
다른 기기에도 바로 반영됩니다.
상태를 글자로 찾을 필요 없이 책상 위 모니터가 말해 줍니다.
| 화면 | 뜻 |
|---|---|
| 꺼짐 | 자는 중 |
| 조용히 켜짐 | 깨어 있고 할 일 없음 |
| 깜빡임 | 일하는 중 |
밝게 깜빡임 + ! |
권한을 묻거나 멈춤 — 손이 필요합니다 |
손이 필요한 일은 헤더 왼쪽에도 뜹니다. 평소에는 그 자리가 비어 있습니다.
🔒 나만 을 눌러 같은 와이파이의 다른 기기 접속을 켤 수 있습니다.
켜면 주소와 8자리 암호가 나옵니다.
http://192.168.0.x:4300/?t=xxxxxxxx
접속한 사람은 사무실 안에 손님 캐릭터로 나타나고, 움직임·말풍선·점프가 서로 보입니다. 손님도 캐릭터에게 명령을 내릴 수 있습니다.
암호는 이 컴퓨터 안에만 저장됩니다(
state/config.json). 껐다 켜도 유지되고,새 암호를 누르면 이미 붙어 있던 원격 기기는 즉시 끊깁니다. 인터넷 전체에 열지는 마세요 — 같은 와이파이 안에서 쓰라고 만든 기능입니다.
전부 환경변수입니다. 없으면 알아서 찾습니다.
PORT |
서버 포트 (기본 4300) |
HOST |
바인딩 주소 (기본 0.0.0.0). npm run start:local 이면 이 컴퓨터에서만 열립니다 |
PO_STATE_DIR |
명부·설정·기록을 둘 자리 (기본 state/) |
PO_CLAUDE_BIN |
claude 실행 파일을 직접 지정 |
PO_CLAUDE_APP_DIR |
데스크톱 앱 데이터 폴더를 직접 지정 |
로그인이 안 된 겁니다. 오피스 채팅창에 /login 을 쳐도 안 됩니다 —
오피스는 claude 를 대화형 터미널이 아니라 프로그램 모드(stream-json)로 띄우는데,
/login 은 브라우저를 열고 사람을 기다리는 대화형 흐름이라 그 자리에 들어설 수가 없습니다.
터미널에서 한 번만 하면 됩니다.
claude auth login창을 대신 띄워 드릴 수도 있습니다 — 명령을 쳐 둔 채 엔터를 기다립니다.
npm run login오피스 화면에도 이때 띠가 뜨고 터미널 열기 버튼이 생깁니다
(그 버튼은 이 컴퓨터에서만 눌립니다 — 같은 와이파이의 손님이 남의 화면에 창을 띄우면 안 되니까요).
로그인이 끝나면 서버를 다시 켜세요. 이미 떠 있던 캐릭터는 옛 상태를 들고 있습니다.
윈도우에서 자주 걸리는 것 — WSL 과 윈도우는 인증이 따로 놉니다. 인증은
%USERPROFILE%\.claude\.credentials.json에 저장되는데 WSL 안에서는 다른 파일입니다. 오피스를 돌리는 그 셸에서 로그인하세요. 그리고 데스크톱 앱 로그인은 안 쳐줍니다 — 앱과 CLI 는 인증을 따로 들고 있습니다.
npm run doctor클로드 코드 쪽에서 우리가 붙잡고 있는 것들 — 실행 파일, 명령줄 플래그, 대화 파일 구조, 세션 목록, 앱 데이터 폴더 — 을 전부 훑어 무엇이 달라졌는지 알려 줍니다. 캐릭터가 갑자기 안 뜨면 여기부터 보세요.
클로드 코드가 업데이트되면 가장 먼저 돌려 볼 만합니다.
같은 세션을 두 곳에서 동시에 쓰지 마세요. 오피스가 캐릭터를 깨워 둔 채 데스크톱 앱에서 같은 대화에 말을 걸면, 두 프로세스가 각자의 기억으로 같은 파일에 덧붙습니다. 잠금 장치는 없습니다.
대화가 새 세션으로 옮겨갈 수 있습니다. 앱에서 대화를 다시 이어받으면
클로드 코드가 새 세션 파일을 만듭니다. 그러면 오피스가 옛 세션을 붙잡은 채
갈라지는데, 이 경우 헤더에 ⇄ 대화가 옮겨감 이 뜨고 새 세션 이어받기 로 합칠 수 있습니다.
npm run loop # 환경 → 서버 → UI → 실제 세션. 전부.
npm run loop -- --fast # 느린 단계 빼고
npm run loop -- --watch # 파일이 바뀔 때마다 다시자세한 건 TESTING.md 를 보세요.
의존성은 ws 하나뿐이고 빌드 단계가 없습니다. 프론트는 순수 HTML/JS/캔버스입니다.
테스트도 노드 내장 러너(node --test)와 크롬 개발자도구 프로토콜만 씁니다 —
playwright 같은 걸 넣으면 브라우저 100MB 가 딸려 오기 때문입니다.
캐릭터·가구 그림은 Kenney 의 CC0 에셋입니다
(public/assets/kenney-*/LICENSE.txt).
던지는 물건·전자시계·바닥 무늬·모니터는 시트에서 가져온 게 아니라 점 단위로 직접 그렸습니다 (throwables.js · decor-catalog.js · themes.js). 16px 가구를 6px 로 줄이면 뭔지 알아볼 수가 없어서입니다. 이쪽은 이 저장소의 MIT 라이선스를 따릅니다.
MIT — LICENSE