Agent Skills: 상태바 아이콘 관리

|

UncategorizedID: shren207/nixos-config/set-icons

Install this agent skill to your local

pnpm dlx add-skill https://github.com/greenheadHQ/nixos-config/tree/HEAD/modules/shared/programs/claude/files/skills/set-icons

Skill Files

Browse the full folder contents for set-icons.

Download Skill

Loading file tree…

modules/shared/programs/claude/files/skills/set-icons/SKILL.md

Skill Metadata

Name
set-icons
Description
|

상태바 아이콘 관리

세션별 상태바 아이콘 (Jira, Slack, Figma, Memo)의 설정, 수정, 제거를 다룬다. SessionStart hook이 상태 파일을 초기화하고, 이 스킬로 링크를 관리한다. Memory 아이콘(🧠)은 statusline에서 자동 감지하므로 이 스킬과 무관하게 동작한다.

빠른 참조

| 아이콘 | 키 | 색상 | 용도 | |--------|-----|------|------| | ⚡ | jira | yellow | Jira 이슈 링크 | | 💬 | slack | magenta | Slack 채널/스레드 | | 🎨 | figma | red | Figma 디자인 | | 📓 | memo | green | 세션 메모 파일 | | 🧠 | (자동) | blue | Memory 파일 (auto-detect, worktree 공유, orphan 시 ⚠) |

상태 파일 구조

경로: ~/.claude/status-icons/<session-id>.json

{
  "jira": { "url": "https://example.atlassian.net/browse/PROJ-123", "label": "PROJ-123" },
  "slack": { "url": "https://app.slack.com/client/T.../C...", "label": "Slack" },
  "figma": { "url": "https://www.figma.com/design/...", "label": "Figma" },
  "memo": { "path": "$HOME/.claude/memos/<session-id>.md", "label": "Memo" }
}

상태 파일 경로 확인

SessionStart hook의 additionalContext에 상태 파일 경로가 표시된다. 대화 컨텍스트에서 상태 파일: 뒤의 경로를 STATE_FILE로 사용한다.

# additionalContext에서 "상태 파일: /path/to/file.json"을 확인 후:
STATE_FILE="$HOME/.claude/status-icons/<session-id>.json"

핵심 절차

대화형 설정

사용자가 제공한 URL과 요청한 아이콘을 사용한다. 설정 대상이나 필요한 URL이 빠졌을 때만 질문 도구로 해당 정보를 묻는다. 이미 제공된 링크나 요청하지 않은 서비스의 링크를 다시 묻지 않는다.

사용자가 URL을 입력하면 아래 jq 명령어로 상태 파일을 업데이트한다. Memo 아이콘도 스킬 호출 시 자동 등록한다 (메모 설정 섹션 참조).

⚠️ jq -n 사용 금지 — 기존 키가 덮어씌워진다. 반드시 기존 파일을 입력으로 사용: tmp=$(mktemp "$(dirname "$STATE_FILE")/.${STATE_FILE##*/}.XXXXXX") && jq '...' "$STATE_FILE" > "$tmp" && mv "$tmp" "$STATE_FILE"

Jira 설정

URL에서 이슈번호를 자동 추출한다:

# URL에서 이슈번호 추출: /browse/PROJ-123 → PROJ-123
JIRA_URL="https://example.atlassian.net/browse/PROJ-123"
JIRA_LABEL=$(echo "$JIRA_URL" | grep -oE '[A-Z]+-[0-9]+' | tail -1)

tmp=$(mktemp "$(dirname "$STATE_FILE")/.${STATE_FILE##*/}.XXXXXX") && jq --arg url "$JIRA_URL" --arg label "$JIRA_LABEL" \
  '.jira = {"url":$url,"label":$label}' \
  "$STATE_FILE" > "$tmp" && mv "$tmp" "$STATE_FILE"

Slack 설정

tmp=$(mktemp "$(dirname "$STATE_FILE")/.${STATE_FILE##*/}.XXXXXX") && jq --arg url "https://app.slack.com/client/T.../C..." \
  '.slack = {"url":$url,"label":"Slack"}' \
  "$STATE_FILE" > "$tmp" && mv "$tmp" "$STATE_FILE"

Figma 설정

tmp=$(mktemp "$(dirname "$STATE_FILE")/.${STATE_FILE##*/}.XXXXXX") && jq --arg url "https://www.figma.com/design/..." \
  '.figma = {"url":$url,"label":"Figma"}' \
  "$STATE_FILE" > "$tmp" && mv "$tmp" "$STATE_FILE"

아이콘 제거

# 특정 아이콘 제거 (예: figma)
tmp=$(mktemp "$(dirname "$STATE_FILE")/.${STATE_FILE##*/}.XXXXXX") && jq 'del(.figma)' "$STATE_FILE" > "$tmp" && mv "$tmp" "$STATE_FILE"

메모 설정

메모 파일은 SessionStart hook이 자동 생성하지만, 아이콘은 스킬 호출 시 등록한다:

# MEMO_FILE은 additionalContext의 "메모:" 뒤 경로
tmp=$(mktemp "$(dirname "$STATE_FILE")/.${STATE_FILE##*/}.XXXXXX") && jq --arg path "$MEMO_FILE" \
  '.memo = {"path":$path,"label":"Memo"}' \
  "$STATE_FILE" > "$tmp" && mv "$tmp" "$STATE_FILE"
  • 경로: ~/.claude/memos/<session-id>.md
  • 상태바에서 📓 Memo Cmd+Click으로 file:// URL을 통해 열 수 있다

동작 원리

| 상황 | 동작 | |------|------| | 새 세션 (cwd 첫 진입 또는 종료 후 재시작) | 빈 sidecar로 시작. 같은 cwd 마커는 startup이 건드리지 않음 (관리 책임은 Stop hook). | | /clear | 같은 cwd 마커의 직전 sid에서 sidecar/memo deep clone 복원 — 같은 cwd에서 며칠 전 세션의 아이콘도 자동 복원된다(아카이빙 우선). | | --resume / --continue | 기존 상태 파일 읽기, 모든 아이콘 유지 | | compact | 동일하게 상태 재주입 | | 자동 정리 | 없음 (아카이빙 우선) — sidecar/memo/마커는 사용자가 명시적으로 정리하기 전까지 보존 |

Lineage 복원 (cwd 격리)

Stop hook(record-last-session.sh)이 매 턴 종료에 ~/.claude/status-icons/.last-session-<sha1(cwd)> 마커 파일에 session_id를 atomic write한다. SessionStart hook은 새 sid에 sidecar가 없을 때 같은 cwd의 마커만 조회하므로, 동시에 진행 중인 다른 워크트리/프로젝트 세션과 아이콘이 섞이지 않는다.

marker 관리는 전적으로 Stop hook의 책임이다 — SessionStart hook은 startup에서 marker를 건드리지 않으므로, 같은 cwd에 두 인스턴스가 동시에 떠 있어도 새 인스턴스의 startup이 다른 인스턴스의 active marker를 덮어쓰지 않는다. 결과적으로 같은 cwd에서 며칠 전 세션 종료 후 다시 방문해 /clear//branch를 하면 직전 세션의 아이콘이 자동 복원된다(아카이빙 우선).

자동 정리 로직은 없다. sidecar/메모/마커는 사용자가 명시적으로 정리하기 전까지 그대로 보존된다. storage 누적이 부담이 되면 별도 도구나 수동 정리로 처리한다.

자주 발생하는 문제

  1. 아이콘 미표시: 상태 파일이 없거나 JSON 파싱 오류 → cat "$STATE_FILE" | jq .로 검증
  2. 상태 파일 경로 불명: SessionStart hook의 additionalContext에서 상태 파일: 뒤의 경로 확인
  3. memo 키 소실: jq -n으로 새 JSON 생성 시 기존 키가 사라짐 → 반드시 기존 파일을 입력으로 사용
  4. 아이콘 순서/라인 변경 불가: 순서와 라인 배치는 statusline.sh에 하드코딩
    • L1 (link icons 그룹): Jira → Slack → Figma → Memo. 조건부 라인 (모두 미설정 시 라인 자체 생략)
    • L2 (context 라인): cwd (📁) + branch (🌿) + branch 동기화 상태(ahead/behind/dirty). 워크트리도 main repo 처럼 같은 줄에 branch 를 인라인 표시한다 (별도 L3 라인 없음).
    • L_M (heavy state 그룹): Plan (📝) → Memory (🧠). Memo는 L1으로 이동.
    • L_SID: session-id (🆔) 전용 줄 — 이 줄에는 session-id 외 어떤 아이콘도 병렬 출력하지 않는다.
    • L_N: 5h/7d Rate Limits (SSH 분기는 vertical bracket ▏…▕ 게이지로 압축)
  5. SessionStart hook 동작 (source별):
    • 지원 source는 startup, clear, resume, compact 네 가지. 그 외 source는 hook이 즉시 exit 0로 skip한다 (sidecar/memo는 생성하지 않음).
    • startup: STATE_FILE이 부재하면 빈 객체 {}로 시작. 동일 sid로 startup이 재발화되면 STATE_FILE을 보존(아이콘 유실 방지). cwd 마커는 startup이 건드리지 않는다 (관리 책임은 Stop hook).
    • clear / resume / compact: STATE_FILE이 부재하면 ① 같은 cwd 마커의 직전 sid sidecar에서 deep clone → ② 실패 시 빈 객체 {}. STATE_FILE이 이미 존재하면 그대로 사용.
    • 마커는 Stop hook이 매 턴 종료에 cwd-sha1로 인코딩된 파일에 sid를 기록해 누적한다. 글로벌 mtime 기반 탐색은 사용하지 않으므로 동시 실행 중인 다른 cwd 세션과 아이콘이 섞이지 않는다.
    • 실제 source 라벨링이 의심되면(예: /clear 후 아이콘이 사라지는 증상이 재현되면) CLAUDE_HOOK_DEBUG=1로 hook을 재기동해 ~/.claude/logs/session-hooks.log를 채집한 뒤 source 매핑을 확인한다.
  6. OSC 8 hyperlink 클릭 UX (macOS Ghostty + Claude Code fullscreen):
    • 일반 Cmd+클릭 — Plan/Memo/Memory 같은 file:// link는 Ghostty plain-text URL fallback detector로 동작 (Jira/Slack/Figma 같은 https://도 동작)
    • Cmd+Shift+클릭 — Claude Code TUI(CLAUDE_CODE_NO_FLICKER fullscreen 모드)가 mouse capture로 일반 Cmd+클릭을 가로채는 영역에서 escape hatch. cwd (vscode://file/<path>/) 처럼 fallback detector가 인식 못 하는 scheme은 Cmd+Shift+클릭으로만 동작
    • 관련 upstream issue: anthropics/claude-code#26356, #37216, #45173 (mouse capture 회귀 미해결)

주의사항

  • $STATE_FILE 변수는 SessionStart hook의 additionalContext에서 확인한다
  • jq로 상태 파일을 수정할 때 항상 임시 파일을 거쳐 atomic write한다
  • 상태 파일이 없거나 JSON이 깨지면 아이콘 미표시 (graceful degradation)
  • statusline.sh나 hook 스크립트 수정은 관련 소스 코드를 직접 참조한다