IceCmd — 오르카가 무거워서 직접 만든 경량 터미널 매니저 2026.08.14

색이 틀린 게 아니라 아예 없었다 — IceCmd 0.6.2

다른 PC에서 claude가 전부 흑백으로 나왔다. 원인은 우리가 칠하는 쪽이 아니라 자식 프로세스가 물려받은 환경이었다. 고친 셋 다 증상이 있던 자리와 원인이 있던 자리가 달랐다.

IceCmd 0.6.2를 냈다. 고친 것이 셋인데, 셋 다 증상이 있던 자리와 원인이 있던 자리가 달랐다.
색이 안 나오는 문제의 원인은 렌더러가 아니었고, 탐색기가 제멋대로 뜨는 문제의 원인은 속도가 아니었다.

덤으로, 이 셋을 잡는 동안 검사 하나가 틀린 질문을 하고 있었다는 것도 알게 됐다. 그게 제일 오래 걸렸다.

어떤 PC에서는 claude가 전부 흑백이었다

다른 기계에서 IceCmd를 띄웠더니 claude 출력에 색이 하나도 없었다.

여기서 중요한 건 색이 틀리게 나온 게 아니라 아예 안 나왔다는 것이다. 색이 이상하면 우리가 칠하는 쪽을 의심하면 되는데, 없으면 얘기가 다르다. 그건 CLI가 색을 안 쓰기로 결정했다는 뜻이고, 그 결정의 근거는 우리가 아니라 자식 프로세스가 물려받은 환경이다.

우리는 원래 TERMCOLORTERM을 넘기고 있었다. 그건 "여기는 컬러 터미널이다"라고 알려주는 것이다. 대부분의 기계에서는 그걸로 충분하다. 충분하지 않은 경우가 둘 있다.

  • CLI는 대부분 자기 stdout이 진짜 터미널인지를 먼저 본다. 우리가 뭐라고 했는지보다 그게 앞선다.
  • 기계에 NO_COLOR가 박혀 있으면 그 하나가 위의 모든 것을 이긴다.

둘 다 우리가 무슨 말을 했는지와 무관하게 작동한다. 그래서 알려주는 것을 그만두고 통보하기로 했다.

claude·codex 칸에는 FORCE_COLOR=3을 넘긴다. Node의 supports-color가 TTY 검사보다 먼저 읽는 값이고, claude와 codex는 둘 다 Node CLI다. BSD/Go 계열을 위해 CLICOLOR_FORCE=1도 같이 넘기고, 물려받은 NO_COLOR는 지운다.

일반 셸은 기본으로 두었다. 거기서 색을 강제하면 dir > list.txt처럼 파일로 흘려보내는 출력에도 이스케이프 문자가 섞인다. 셸 칸에서 CLI를 손으로 띄우는 사람을 위해 설정에 스위치만 하나 뒀다.

더블클릭이 두 가지 일을 하고 있었다

폴더 트리에서 폴더 행은 클릭하면 펼치고, 더블클릭하면 탐색기를 띄웠다.

써보면 안다. 트리를 빠르게 두 번 내려가는 순간 아무도 부르지 않은 탐색기 창이 뜬다.

버그처럼 보이지만 코드는 적힌 대로 돌고 있었다. 문제는 트리를 훑는 손짓과 창을 띄우는 손짓이 같은 손짓이었다는 것이다. 둘을 구분하는 유일한 기준이 "얼마나 빨리 눌렀나"였다. 빠르게 훑는 건 트리를 쓰는 정상적인 방법이지, 창을 띄워달라는 뜻이 아니다.

그래서 폴더를 여는 것은 우클릭 메뉴로 옮겼다. 원래부터 거기 있던 기능이라 새로 만들 것도 없었다. 파일은 펼침과 충돌할 게 없으므로 더블클릭으로 연다.

사용량이 /usage를 쳐야만 움직였다

하단 바에 claude 사용량을 띄우는데, 한 창을 3분의 1쯤 태워도 숫자가 그대로였다.

claude는 이유가 있을 때만 ~/.claude.json의 사용량 캐시를 갱신한다. 시작할 때, 그리고 /usage를 열 때. 그 사이에 아무리 써도 파일은 몇 시간 전 숫자 그대로다.

우리 바는 그 옆에 "2시간 전"이라고 정직하게 적고 있었다. 정직했고, 정직하게 쓸모가 없었다.

그래서 캐시가 낡았을 때만, CLI가 읽는 것과 같은 엔드포인트에서 직접 읽는다. 토큰은 claude가 저장해 둔 것을 그대로 쓴다. 조건은 짜게 걸었다 — 창이 보일 때만 · 90초에 한 번 · 약 2KB. 만료된 토큰은 쓰지 않는다(갱신은 claude가 할 일이지 우리가 낄 자리가 아니다).

실패하거나, 토큰이 없거나, macOS라 토큰이 키체인에 있으면 조용히 캐시로 돌아간다. 0.6.1과 같은 답이지 더 나쁜 답이 아니다.

검사 하나가 틀린 질문을 하고 있었다

이 앱에는 하네스가 있다. 앱을 진짜로 띄워 160개쯤을 자동으로 확인한다. 그중 하나가 계속 실패했다.

검사의 이름은 "개발 중에 설치본의 설정 파일을 건드리지 않는다"였다. 2026년 8월 9일에 실제로 설치본 설정을 날린 적이 있어서 만든 검사다. 그런데 그것을 파일 바이트 수가 그대로인가로 보고 있었다.

여기서 함정은, 이 앱은 이 앱 안에서 개발한다는 것이다. 하네스가 도는 동안 설치본 IceCmd가 거의 항상 열려 있고, 그 창에서 칸을 하나만 옮겨도 설치본이 자기 상태를 저장한다. 바이트 수가 바뀐다. 검사는 실패하는데 그 이유가 검사 대상과 아무 상관이 없었다.

막아야 하는 것은 파일이 바뀌는 게 아니라 지워지거나 덮어써지는 것이다. 지워짐은 크기 0으로, 덮어써짐은 개발용 스냅샷과 똑같은 크기로 드러난다. 그 둘만 본다.

하네스가 통과했다고 기능이 사는 건 아니다

이번 릴리스는 162개 통과 / 0 실패 / 건너뜀 2로 나갔다(건너뛴 둘은 창에 포커스가 없으면 못 하는 클립보드 왕복이다).

그런데 이 프로젝트에서 반복해서 배우는 게 있다. 검사가 통과한다고 기능이 사는 것은 아니다.

0.6.0 때 드래그 기능이 그랬다. 하네스가 드래그 이벤트를 직접 만들어 던져서 통과시켰는데, 실제로는 Tauri의 네이티브 파일 드롭이 그 배관을 통째로 가져가서 진짜 마우스로는 아무 일도 일어나지 않았다. 이벤트를 만들어 던지는 검사는 배관이 열려 있는지를 증명하지 못한다.

그래서 이번에는 색을 확인할 때 설정값을 보지 않았다. 셸 안에서 echo로 자식이 실제로 받은 환경변수를 되물어, 스위치가 꺼져 있으면 비어 있고 켜져 있으면 3이 나오는지 본다. 스토어가 값을 들고 있다는 것은 프로세스가 그 값을 받았다는 증거가 아니다.

사용량도 같은 식으로 본다. 실시간으로 읽은 값이 캐시보다 15분 앞서 있는 것을 숫자로 찍어 확인한다.


정리하면 이번에 배운 것은 하나다. 증상이 보이는 자리를 고치기 전에, 그 결정을 실제로 누가 내렸는지 먼저 물어야 한다. 색은 우리가 칠하는 게 아니라 CLI가 결정하고, 그 CLI는 우리 설정이 아니라 자기가 물려받은 환경을 본다.

내려받기 → icenovel.com/service/icecmd

IceCmd — 오르카가 무거워서 직접 만든 경량 터미널 매니저 프로젝트로