diff-page-opener
VS Code 확장. Claude Code의 diff 렌더 스킬이 만드는 승인 페이지를 돕는다. 하는 일은 둘이다.
- 다른 프로그램이 남긴 요청 쪽지를 보고, 로컬 HTML 페이지를 그 작업 폴더를 연 VS Code 창의 내장 브라우저(Integrated Browser)로 연다.
바깥 프로그램은 VS Code 명령을 직접 부를 수 없어서 이 확장이 대신 부른다.
- "Diff 디자인 설정" 화면에서 DESIGN.md를 올리면
claude 명령이 그 문서를 페이지의 색과 글꼴로 해석한다.
미리보기를 본 뒤 저장하고, 고른 디자인(테마)을 테마 파일로 써 둔다. 페이지를 만드는 쪽이 그 파일을 읽어 기본 디자인 위에 덮는다.
쪽지 규칙
쪽지와 답장은 임시 폴더(Node os.tmpdir(), Windows에서는 환경 변수 TEMP) 아래 diff-page-opener/에 둔다.
request.json — 여는 쪽이 쓴다. {"workspace": 작업 폴더 경로, "file": HTML 파일 경로, "time": 밀리초 시각}.
다 쓴 파일로 이름을 바꿔 넣는다(반쯤 쓴 파일을 읽지 않게).
- 확장은
workspace가 자기 창의 작업 폴더(또는 그 아래)이고, file이 .html/.htm이며, time이 15초 안일 때만 연다.
ack.json — 확장이 페이지를 연 뒤 쓴다. {"time": 요청의 time}. 여는 쪽은 이것으로 열렸는지 안다.
Diff 디자인 설정 화면
명령 팔레트(Ctrl+Shift+P)에서 Diff 디자인 설정을 부른다.
- 왼쪽 칸: 테마 콤보 박스, 고른 테마의 정보(원본 문서, 추가한 날, 지금 쓰는 테마), "적용", "+ DESIGN.md 추가", "목록에서 빼기".
- 오른쪽: diff 견본 두 장을 위아래로. 위는 지금 쓰는 테마, 아래는 콤보 박스에서 고른 테마다.
콤보 박스만 바꾸면 아래 견본만 바뀌고, "적용"을 눌러야 저장된다.
- "+ DESIGN.md 추가": 파일을 고르면
claude가 해석한다(문서 세 개가 9~15초에 끝났다, 2026-11-12). 해석 중에는 "버리기"로 멈출 수 있다.
새 테마의 이름은 문서에 적힌 디자인 이름이다.
찾는 차례는 앞머리 YAML의 name: → 첫 # 제목(제목 안에 따옴표로 감싼 이름이 있으면 그것) → 파일 이름(확장자 뺌)이다.
기본 디자인을 포함해 이미 있는 이름과 겹치면 이름 뒤에 날짜를 붙인다.
끝나면 아래에 후보 견본이, 왼쪽 칸에 "문서에 없어 Claude가 정한 값" 목록이 나온다. "목록에 저장"을 눌러야 목록에 들어간다.
- 예전 테마는 "목록에서 빼기"를 누르지 않는 한 남는다. 기본 디자인(이름 "Estilo de Litografia de Precisão")은 뺄 수 없다.
같은 이름을 다시 올리면 이름 뒤에 날짜를 붙여 따로 남긴다.
- 적용한 테마는 다음에 만드는 승인 페이지부터 쓰인다. 이미 열린 페이지는 그대로다.
- 손으로 고쳐 깨졌거나 판이 다른 항목은 콤보 박스에 "(쓸 수 없음)"이 붙고, 까닭이 왼쪽 칸에 나온다.
그런 항목을 적용하면 페이지가 기본 디자인으로 나오므로, 견본도 기본 디자인으로 그린다.
- 목록과 고른 테마는 VS Code 사용자 설정
diffPageOpener.themes, diffPageOpener.activeTheme(범위 application)에 둔다.
설정 동기화를 켜면 계정을 따라 다른 PC로 간다.
- 해석할 때 문서 전문이 이 PC의
claude 명령으로 넘어가고, 사용자의 Claude 요금제를 쓴다.
claude는 CLAUDE.md, 훅, 플러그인을 끈 채(--safe-mode) 도구 없이(--tools "") 임시 폴더에서 돈다.
모델은 sonnet, 생각 깊이는 low로 부른다. 모델을 정하지 않았을 때는 한 문서에 1~2분, 한 번은 4분을 넘겼다.
테마 파일 규칙 (판 1)
테마 파일은 쪽지와 같은 폴더의 theme.json이다. 확장은 깨어날 때와 diffPageOpener 설정이 바뀔 때 쓴다.
고른 것이 기본 디자인이거나, 고른 항목이 목록에 없거나, 판이 다르거나 값 모양 검사에 걸리면 쓰지 않고 지운다.
확장을 지우면 VS Code를 다시 시작할 때 vscode:uninstall 훅(lib/uninstall.js)이 이 파일을 지운다.
{"contract": 1, "id": "…", "name": "WattVision", "vars": {"--bg": "#121212", "…": "변수 30개"}}
읽는 쪽은 아래를 모두 지킬 때만 테마를 쓴다. 하나라도 어긋나면 테마 전체를 버리고 기본 디자인으로 낸다.
통과한 변수만 섞으면 어두운 바탕에 기본 글자색이 들어가 글이 안 보일 수 있기 때문이다.
contract가 읽는 쪽이 아는 판과 같다.
vars에 아래 30개가 모두 있고, 모르는 이름이 없다.
- 모든 값이 글이고, 소문자로 바꾼 값에 금지 글자
; { } < > 역슬래시 @ /* url( expression( var( 줄바꿈(LF, CR)이 없다.
| 변수 |
역할 |
값 모양 |
--bg |
페이지 바탕 |
색 |
--bgimg |
바탕 무늬 |
none 또는 linear-gradient(…)를 쉼표로 이은 것 |
--bgsize |
바탕 무늬 한 칸 크기 |
길이 1~2개 |
--card |
사이드 메뉴와 파일 상자 바탕 |
색 |
--fg |
본문 글자 |
색 |
--mut |
흐린 글자(행 번호, 보조 설명, 열 제목) |
색 |
--line |
테두리와 구분선 |
색 |
--acc |
강조(메뉴 번호, 지금 파일 표시, 접기 글자) |
색 |
--hover |
메뉴 올림, 지금 파일 칸, 접기 줄 바탕 |
색 |
--fh |
파일 머리 바탕, 종류 표시 글자 |
색 |
--fhfg |
파일 머리 글자 |
색 |
--fhbar |
파일 머리와 구간 머리의 왼쪽 띠, 종류 표시 바탕 |
색 |
--fhok |
파일 머리의 더한 줄 수 |
색 |
--fhbad |
파일 머리의 뺀 줄 수 |
색 |
--sh |
구간 머리 바탕 |
색 |
--shfg |
구간 머리 글자 |
색 |
--shbar |
구간 머리 왼쪽 띠 |
색 |
--ctx |
문맥 줄 바탕 |
색 |
--del |
삭제 줄 바탕 |
색 |
--delmk |
삭제 줄 안에서 바뀐 낱말 |
색 |
--ins |
추가 줄 바탕 |
색 |
--insmk |
추가 줄 안에서 바뀐 낱말 |
색 |
--ok |
메뉴와 본문의 더한 줄 수 |
색 |
--bad |
메뉴와 본문의 뺀 줄 수 |
색 |
--emp |
반대편에 줄이 없는 빈 칸 바탕 |
색 |
--stripe |
빈 칸의 빗금 선 |
색 |
--rad |
모서리 반지름 |
0~32px 사이의 px 길이 하나 |
--shadow |
파일 상자 그림자 |
none 또는 길이 2~4개와 색 하나 이하 |
--fontui |
화면 글꼴 |
글꼴 이름 목록. 끝은 sans-serif |
--fontcode |
코드 글꼴 |
글꼴 이름 목록. 끝은 monospace |
- 색은
#rgb, #rrggbb, #rrggbbaa, 숫자만 든 rgb()·rgba() 가운데 하나다.
- 글꼴 이름은 따옴표로 감싸거나 영문자, 숫자, 공백, 하이픈으로만 쓴다.
- 확장은 저장하기 전에 값 모양까지 검사한다(
lib/theme.js). 읽는 쪽은 이름과 금지 글자만 다시 본다.
- 변수를 더하거나 빼거나 이름·역할을 바꾸면 판을 올린다.
lib/theme.js의 CONTRACT·VARS와 읽는 쪽의 판 번호를 함께 바꾼다.
판이 다른 테마는 다시 해석하기 전까지 기본 디자인으로 나온다.
설정의 테마 항목에는 위 넷 말고도 source(올린 파일), addedAt(추가한 날), design(문서 전문), invented가 있다.
invented는 문서에서 오지 않은 변수 이름이다. Claude가 "문서에서 그대로 가져왔다"고 한 값이라도 문서 글에서 찾지 못하면 여기에 든다.
글꼴은 목록의 첫 이름, 나머지는 값 전체를 문서 글에서 낱말로 찾는다.
견본 다시 만들기
미리보기 견본 media/sample.html은 페이지를 만드는 쪽(diff 렌더 스킬의 render_html.py)이 만든 진짜 페이지다.
그 스크립트의 페이지 규칙이 바뀌면 다시 만든다. 기본 디자인의 값과 이름도 이 견본에서 읽는다(첫 :root, 사이드 메뉴의 "디자인:" 줄).
python <diff 렌더 스킬 폴더>/scripts/render_html.py --no-theme --title "견본" --out media/sample.html sample/before.py sample/after.py sample.py
아이콘 다시 만들기
마켓플레이스 아이콘 assets/marketplace-icon.png(512x512)는 assets/icon.svg에서 만든다. 마켓플레이스가 SVG 아이콘을 받지 않아서다.
그림을 바꿀 때는 SVG를 고치고 아래 명령으로 PNG를 다시 만든다. PNG를 손으로 고치지 않는다.
python make_icon.py
Chrome이나 Edge를 화면 없이 띄워 SVG를 찍는다. 알려진 설치 경로에 없으면 --browser <실행 파일>로 준다.
색은 기본 디자인의 값이다(남색 바탕, 전기 파랑 띠, 지운 줄 주황, 더한 줄 초록).
시험
node --test "test/*.test.js"
vscode 모듈을 부르지 않는 lib/theme.js, lib/interpret.js, lib/themeFile.js만 시험한다. 화면은 설치한 뒤 손으로 본다.
설치
- 마켓플레이스: 게시자
YSTools의 diff-page-opener.
- 게시 전 시험 설치:
python install.py. 묶기만 하려면 python install.py --no-install --out <경로>.
설치하면 옛 시험판 local.diff-page-opener를 지운다. 두 확장이 함께 깨어 있으면 같은 쪽지로 페이지가 두 번 열린다.
- 설치 전부터 열려 있던 VS Code 창은 한 번 다시 불러와야(Developer: Reload Window) 확장이 깨어난다.
- 설치 확인:
code --list-extensions에 ystools.diff-page-opener가 있는지 본다.
- 창이 확장을 깨웠는지(Windows):
%APPDATA%\Code\logs\<세션>\window*\exthost\exthost.log에서 _doActivateExtension YSTools.diff-page-opener 줄을 찾는다.
로그는 게시자 이름의 대문자를 살려 찍으므로 대소문자를 가리지 않고 찾는다.
그 창이 어느 작업 폴더인지는 같은 로그에 나오는 workspaceStorage\<id> 폴더의 workspace.json이 알려 준다.
게시
마켓플레이스 게시는 GitHub Actions 워크플로 .github/workflows/publish-marketplace.yml이 한다.
Marketplace Trusted Publishing으로 인증하므로 접근 토큰(PAT)을 만들거나 저장하지 않는다.
처음 한 번, Marketplace 게시자 관리에서 YSTools 게시자의 Trusted Publishing 탭에 정책을 만든다.
| 입력 칸 |
값 |
| Policy name |
Diff Page Opener GitHub |
| Repository owner |
100Mile |
| Repository |
diff-page-opener |
| Workflow |
publish-marketplace.yml |
| Environment |
비워 둔다 |
Workflow 칸에는 .github/workflows/를 붙이지 않는다. 비공개 저장소면 정책을 만든 뒤 48시간 안에 워크플로가 한 번 성공해야 정책이 살아난다.
게시하는 방법은 셋이다.
- package.json의
version과 같은 v<버전> 태그(예: v0.2.0)를 main에 들어간 커밋에 달아 올린다.
- 같은 판을 다시 올려야 하면 그 태그를 옮기지 않고
publish-retry/v<버전>/<번호> 태그를 올린다. 번호는 1부터다.
- GitHub의 Actions 화면에서 이 워크플로를 main으로 손수 실행하고 버전을 적는다.
워크플로는 Windows에서 문법 검사와 시험을 돌리고 묶음을 만든다. 다음 작업이 그 묶음만 받아 vsce publish --oidc로 올린다.
main에 커밋을 올리기만 해서는 게시되지 않는다. Actions가 성공해도 Marketplace 안의 검사가 남을 수 있으니, 마켓 화면에 그 판이 보일 때까지 본다.
필요한 것
- 내장 브라우저 명령
workbench.action.browser.openFile이 있는 VS Code. 1.146.0에서 확인했다.
- 테마 해석에는 PATH에서 찾을 수 있는
claude 명령(Claude Code CLI).
Windows에서는 네이티브 설치의 claude.exe와 npm 설치의 claude.cmd를 모두 찾는다(PATHEXT 차례).
- 설치 스크립트에는 Python 3과 PATH의
code 명령.