changelog
제품 릴리즈 노트를 수집(결정론) → 요약(판단) → 렌더 → Orca 탭으로 잇는다.
제품을 먼저 정한다 — 사용자가 말한 대상을 그대로 옮긴다:
| 사용자가 말한 것 | --product |
릴리즈 소스 | 기본 창 |
|---|---|---|---|
| Orca, 오르카 | orca |
stablyai/orca | 최근 3일 (하루 1~2회 릴리즈) |
| Claude Code, 클로드 코드 | claude |
anthropics/claude-code | 최근 3일 (하루 1~3회 릴리즈) |
| Codex, 코덱스 | codex |
openai/codex | 최근 14일 (정식 릴리즈 주 1회쯤) |
| herdr, 허더 | herdr |
herdrdev/herdr | 최근 21일 (안정판 1~2주 간격, preview 는 제외) |
대상이 불명하면 묻지 말고 orca 로 간다(이 스킬의 원형). 여러 제품을 함께 요청하면 (“셋 다”, “요즘 도구들 업데이트”) 제품별로 아래 전 단계를 반복한다 — 제품마다 탭이 따로 열린다.
전제
ghCLI 인증 필요 (gh auth status). 비대화형에서도 keyring 으로 동작한다.- Orca 앱이 실행 중이어야 탭이 열린다.
orcaCLI 가 없는 환경이면 열기 단계는 명시 에러로 끝난다 — 그 경우 렌더된 HTML 경로를 보고하는 데서 멈춘다(조용한 대체 열기 금지).
먼저 스킬을 불러올 때 받은 base directory(이 SKILL.md 가 있는 절대경로)를 SKILL_DIR 에 넣고 아래 블록을 실행한다 — 블록은 그 값을 검증해 쓰고, 넣지 못했을 때만 설치 위치를 찾는다(후보가 여럿이면 멈춘다).
# SKILL_DIR 확정(skill-dir-resolution) — 스킬을 불러올 때 받은 base directory 를 먼저 SKILL_DIR="그 경로" 로 넣는다(항상)
# 블록은 그 값을 검증해 쓰고, 넣지 못했을 때만 설치 위치를 찾는다 — SKILL.md 가 있는 후보가 하나일 때만 받고 아니면 멈춘다
SKILL_DIR=$(sh -c '
S=$1 P=$2 H=${5:-$HOME/.claude}
ok() { d=${1%/}; [ "${d##*/}" = "$S" ] && [ -f "$d/SKILL.md" ] && (cd "$d" && pwd -P); }
[ -n "$3" ] && { ok "$3" && exit; d=${3%/}; [ "${d##*/}" = "$S" ] && echo "SKILL_DIR 무시: $3 에 SKILL.md 가 없다" >&2; }
[ -n "$4" ] && { ok "$4/skills/$S" && exit; echo "CLAUDE_PLUGIN_ROOT 무시: $4/skills/$S 에 SKILL.md 가 없다" >&2; }
c=$(for d in "$H"/plugins/synced/*/"$P"/skills/"$S" "$H"/plugins/synced/*/"$P"~*/skills/"$S" "$H"/plugins/cache/*/"$P"/*/skills/"$S" \
/root/.claude/plugins/synced/*/"$P"/skills/"$S" /root/.claude/plugins/synced/*/"$P"~*/skills/"$S" \
/sessions/*/mnt/.remote-plugins/*/skills/"$S" /sessions/*/mnt/.claude/skills/"$S"; do ok "$d"; done | sort -u)
[ "$(printf "%s\n" "$c" | grep -c .)" -gt 1 ] && { printf "SKILL_DIR 후보가 여럿이다 — 어느 설치본이 쓰이는지 모른다:\n%s\n" "$c" >&2; exit 1; }
printf "%s\n" "$c"' _ changelog itda-dev "${SKILL_DIR:-}" "${CLAUDE_PLUGIN_ROOT:-}" "${CLAUDE_CONFIG_DIR:-}")
: "${SKILL_DIR:?정하지 못했다 — 스킬을 불러올 때 받은 base directory(이 SKILL.md 가 있는 절대경로)를 SKILL_DIR 에 넣고 이 블록을 다시 실행하라}"
WORK="${TMPDIR:-/tmp}/changelog"
mkdir -p "$WORK"
P=orca # 또는 claude | codex | herdr
1단계 — 수집
python3 "$SKILL_DIR/scripts/collect.py" --product "$P" --out "$WORK/$P-collect.json"
사용자가 범위를 말하면 그대로 옮긴다: --since 7d · --since 2w · --since v1.4.170
· --since 2026-08-01 · --new(마지막으로 본 이후) · --all · --full(제외 표면 포함).
산출 JSON 의 각 항목은 {section, kind, scope, title, pr, prs, breaking, revert} 다.
window_widened(기간 내 릴리즈 0 → 최근 1개로 확장)와 range_truncated(수집 범위 끝에
닿음)가 true 면 렌더가 알아서 표기하니 따로 손대지 않는다.
no_new: true 면 여기서 멈춘다. --new·--since <태그> 구간에 새 릴리즈가 없다는
뜻이다. 요약·렌더·탭 열기를 모두 건너뛰고 “마지막으로 확인한 <태그> 이후 새 릴리즈가
없습니다” 한 줄만 보고한다. 같은 내용을 다시 렌더해 탭을 여는 것은 소음이다.
2단계 — 요약 (네가 판단하는 유일한 단계)
$P-collect.json 을 읽고 $WORK/$P-summary.json 을 쓴다.
{
"behavior_changes": [{"text": "...", "refs": [12884], "tag": "v1.4.177"}],
"versions": {"v1.4.177": {"highlights": [{"text": "...", "refs": [13076]}]}}
}
behavior_changes — 전 버전 통합, 최상단에 뜬다. 여기 넣을 것만 넣는다:
revert:true항목 (되돌림은 “어제 되던 게 오늘 안 되는” 변화다)breaking:true항목- 기본 동작·기본값·설정 항목이 바뀐 것 — 제거된 토글, fail-open→fail-closed, 기본 경로 변경,
UA·인증처럼 외부에 보이는 동작 변경, 플래그 폐지(“
--full-auto제거” 류) - 단순 버그 수정은 넣지 않는다. “고쳐졌다”는 동작 변경이 아니다.
highlights — 버전당 3~7건. 사용자가 오늘 쓰다가 알아차릴 만한 것만 고른다.
같은 표면의 자잘한 수정이 여러 건이면 한 줄로 묶어라(“터미널 안정화 6건 — …”).
내부 리팩터·CI·테스트·의존성은 고르지 않는다(전체 목록에는 남아 있다).
제품별 유의
claude— 항목에 PR 참조가 거의 없다.refs: []가 정상이며 번호를 지어내지 않는다.codex— 항목의prs는 복수일 수 있다.refs에는 그중 대표 1~2개면 충분하다.dump_items(말미 PR 전량 덤프)는 highlight 후보가 아니다 — 큐레이션 섹션(items)에서만 고른다. 덤프는 렌더가 별도 접힘 목록으로 전량 보존한다.- 정식 릴리즈 간격이 긴 제품(codex)은 한 릴리즈가 크다 — highlights 상한(7건)은 유지하되 묶음 서술을 적극 쓴다.
작성 규칙
- 한국어로, 사용자가 보는 화면 말로 쓴다. 영문 원제를 그대로 옮기지 않는다.
refs는 반드시collect.json의pr/prs값에서 가져온다. 번호를 지어내지 않는다. 확실한 PR 이 없으면refs: []로 둔다.- 원문에 없는 사실을 추론해 넣지 않는다. 제목만으로 효과가 불분명하면 제목을 옮기고 만다.
- 항목이 0건인 릴리즈(
empty:true)는 요약하지 않는다 — 렌더가 “항목 없음”으로 표기한다.
3단계 — 렌더 · 열기
python3 "$SKILL_DIR/scripts/render.py" \
--data "$WORK/$P-collect.json" --summary "$WORK/$P-summary.json" \
--out "$WORK/$P-changelog.html"
python3 "$SKILL_DIR/scripts/open_in_orca.py" \
--product "$P" --file "$WORK/$P-changelog.html" --tag <가장 최신 태그>
open_in_orca.py 는 제품별 이전 탭이 살아 있으면 재사용하고, 성공했을 때만 state
(~/.local/state/itda-changelog/<product>.json — 스킬 디렉토리 밖, 머신 로컬)를 갱신한다.
실패하면 다음 실행에서 같은 구간이 다시 잡힌다 — 정상 동작이다.
4단계 — 대화 보고
요약 전문을 대화에 반복하지 않는다. 그것 때문에 탭을 여는 것이다. 3~5줄로:
📅 Claude Code · 최근 3일 · 릴리즈 5개 · 47건 → Orca 탭에 열었습니다.
⚠️ 동작 변경 2건 — 게이트웨이 지출 한도 경고 도입, 미신뢰 디렉토리 trust 프롬프트 확대
가장 큰 릴리즈는 v2.1.224(21건, Remote Control·VSCode 집중).
⚠️ 동작 변경 이 있으면 그중 사용자에게 가장 영향이 큰 1~3건만 대화에도 적는다.
출력 구조 (참고)
버전이 1차 축, 각 버전은 3층이다 — 눈에 띄는 변화(네가 고른 것) / 표면별 집계(칩:
orca 는 scope, claude·codex·herdr 는 변경 종류) / 전체 N건 펼치기(<details>, 원문 전량;
codex 는 PR 덤프 접힘 목록 추가). 무엇도 버려지지 않는다.
제품 추가
profiles/<product>.json 을 넣으면 그 이름으로 바로 쓸 수 있다 — 스크립트는 그 디렉터리를
읽어 제품 목록을 만든다(별칭이 필요할 때만 PRODUCT_ALIASES 에 한 줄 추가). 파서는 세
가지다: conventional(feat(scope): …) · sections(### Added 류 keep-a-changelog) ·
prose. 릴리즈 본문을 먼저 몇 개 열어 보고 고른다.
필터에 대해
profiles/<product>.json 의 excluded_scopes(orca: e2e·ci·test·i18n 등)는 조연이다.
실측(2026-08-09, 최근 3일 179건)에서 이 필터가 걸러낸 건 1건뿐이었다. 이 스킬의 가치는
거르기가 아니라 압축에 있다 — 178건을 20줄 첫 화면으로 만드는 것.
새 표면을 제외하고 싶다는 요청이 오면 해당 프로파일의 excluded_scopes 에 scope 를
추가한다. 표면 한국어 이름은 같은 파일 scope_labels 에 있다.