수동 개발로그 스킬을 만들어 공개하기까지
설치하기
AI 세션의 대화 내용을 근거로 개발로그 Markdown 초안을 만들어 주는 Agent Skill입니다. Codex와 Claude Code 양쪽에서 동작합니다.
전역 설치는 다음 한 줄이면 됩니다.
npx skills add al8bright/manual-devlog --skill manual-devlog -g -a codex -a claude-code --copy -y
상황별로 쓰는 명령은 이렇게 나뉩니다.
| 상황 | 명령 |
|---|---|
| 프로젝트 하나에만 설치 | npx skills add al8bright/manual-devlog --skill manual-devlog |
| 이미 설치했고 최신화 | npx skills update manual-devlog -g -y |
| 설치 목록 확인 | npx skills list -g |
이미 설치했다면 지우고 다시 설치할 필요가 없습니다. 갱신 명령 하나로 끝납니다.
설치 후 Codex나 Claude Code를 새로 시작하고 "개발로그 작성해줘"라고 하면 됩니다. 저장소는 al8bright/manual-devlog입니다.
이 글은 그 스킬을 만들고 다듬어 공개하기까지의 기록을 하나로 합친 것입니다. 아래 내용은 모두 스킬 자신이 작성한 개발로그 세 편에서 왔습니다.
오늘의 목표와 맥락
로컬에서만 쓰던 수동 개발로그 작성 스킬을 다른 사람도 설치해 쓸 수 있는 형태로 공개하는 것이 출발점이었다.
기존 스킬은 Codex와 Claude Code에 각각 복사해 둔 상태였고, 두 사본의 문서 규칙을 동일하게 맞춘 뒤였다. 남은 문제는 배포 경로였다.
파일을 수동으로 복사해 달라고 안내하는 대신 한 줄 명령으로 설치되는 표준 방식을 쓰고 싶었다. 조사 결과 npx skills CLI가 SKILL.md 기반 Agent Skills 표준을 지원했고, 설치 대상 에이전트를 Codex와 Claude Code로 각각 지정할 수 있었다.
작업은 세 단계로 이어졌다.
- 공개 배포
.gitignore정책 추가- 스킬 문서 자체의 규칙 보강
뒤로 갈수록 새 기능을 얹기보다 이미 만든 것의 빈틈을 메우는 쪽으로 성격이 바뀌었다.
구현한 내용
저장소 분리와 스킬 폴더 구성
작업 자체는 기존 서비스 프로젝트 세션 안에서 시작했지만, 그 저장소에 원격을 추가하지 않았다. 이미 다른 서비스 저장소를 가리키고 있어서 공개 스킬용 원격을 붙이면 둘이 뒤섞일 위험이 있었다.
공개용 저장소는 별도 폴더에 두고 그 안에서만 커밋했다. 구조는 저장소 루트 아래 manual-devlog/SKILL.md 하나로 시작했다. 설치할 때 지정하는 스킬 이름과 폴더 이름이 그대로 대응되도록 하기 위해서다.
SKILL.md의 핵심 규칙은 다음과 같다.
- 발행하지 않고 편집 가능한 Markdown 초안만 만든다. 업로드 API 호출, GitHub 수집, 저장된 외부 자격 증명 사용을 모두 금지한다.
- 출력 경로는 프로젝트 루트의
devlogs/이며,docs/에는 절대 쓰지 않는다. - 파일명은
YYYYMMDD_[N]_제목.md이고, 같은 날짜 파일이 있으면 순번을 올린다. - 본문 섹션은 근거가 있을 때만 쓴다. 특히
# 문제와 해결은 실제 문제가 있었던 경우에만 넣는다.
README와 설치 안내
푸시 후 설치 안내 README를 추가했다. 설치 명령, 옵션 의미, 사용법 트리거 예시, 결과물 형식, 수동 설치 경로 순으로 구성했다.
전역 설치 명령에 --copy를 기본으로 넣은 이유는 Windows 환경 때문이다. 심볼릭 링크 생성은 권한 설정에 따라 실패할 수 있어, 실제 파일 복사가 더 안전한 기본값이라고 판단했다.
.gitignore 처리 단계 추가
공개 직후 빠진 규칙이 드러났다. 생성한 devlogs/ 폴더를 버전 관리에 포함할지 말지에 대한 기준이 없었다.
이 결정은 프로젝트마다 갈린다. 팀과 공유하려면 커밋해야 하고, 개인 메모라면 무시 목록에 넣는 편이 낫다. 스킬이 한쪽을 조용히 강제하면 곤란하므로 선택 가능하게 만들되 기본값을 명확히 정하기로 했다.
- 기본값은
.gitignore를 수정하지 않는 것이다. 초안은 프로젝트와 함께 추적된다. - 저장소에서
devlogs/를 처음 만들 때 기본값을 알리고 대안을 한 문장으로 제시한다. - 다만 답변을 기다리며 멈추지 않는다. 선택이 없으면 기본값을 유지한다.
- 사용자가 명시적으로 요청할 때만 항목을 추가한다. 무관한 항목은 지우거나 순서를 바꾸지 않는다.
- 초안을 스스로 커밋하거나 푸시하지 않는다.
마지막 보고 단계에도 적용된 .gitignore 결정을 알린다는 항목을 넣었다. 조용히 처리하면 사용자가 나중에 원치 않는 상태를 발견하게 된다.
스킬 문서 자체의 규칙 보강
마지막으로 방향을 바꿔 스킬 문서를 점검 대상으로 삼았다.
기준은 실사용 경험으로 좁혔다. 이 스킬을 이미 여러 번 돌려봤으니 판단이 흔들렸던 지점이 곧 문서의 빈틈이라고 봤다. 있으면 좋을 규칙이 아니라, 없어서 즉흥적으로 메웠던 부분을 찾는 방식이다.
10개 항목이 나왔고 성격에 따라 세 묶음으로 나뉜다.
| 묶음 | 규칙 | 없을 때 생기는 일 |
|---|---|---|
| 실패 방지 | 날짜는 환경 정보나 셸 명령으로 확인 | 파일명 전체가 날짜 기반이라 결과물이 통째로 잘못됨 |
| 실패 방지 | 출력 루트는 가장 가까운 git 저장소 루트 | 하위 디렉터리나 모노레포에서 폴더가 엉뚱한 곳에 생김 |
| 실패 방지 | 기존 파일 덮어쓰기 금지 | 순번 판단이 어긋나면 기존 초안이 사라짐 |
| 실패 방지 | 근거 부족 시 되묻기 | 빈약한 문서를 지어내게 됨 |
| 품질 편차 | 기본 분량 지정 | 실행할 때마다 길이가 달라짐 |
| 품질 편차 | 같은 날 초안과 중복 회피 | 연속 작성 시 같은 내용이 반복됨 |
| 품질 편차 | 수정 요청은 해당 파일 편집 | 불필요한 새 파일이 쌓임 |
| 공개 배포 | 기본 한국어, 요청 시 타 언어 | 한국어 사용자 외에는 쓰기 어려움 |
| 공개 배포 | 태그: 줄 끝 쉼표 유지 |
모델이 오타로 보고 지움 |
| 공개 배포 | 제목 40자 상한 | 경로 길이 문제에 걸림 |
설계와 판단
기본값을 "아무것도 하지 않음"으로 정한 이유
.gitignore는 프로젝트 전체에 영향을 주는 공유 설정 파일이다. 개발로그를 쓰겠다고 요청했을 뿐인데 스킬이 이 파일을 말없이 고치면, 의도하지 않은 변경이 다음 커밋에 섞여 들어간다.
그래서 기본값의 실제 의미는 "devlogs를 커밋하라"는 강제가 아니라 사용자의 설정 파일을 건드리지 않는다에 가깝다. 파일을 만드는 것보다 남의 설정을 고치는 쪽이 되돌리기 어렵다는 판단이었다.
물어보되 막지는 않기
첫 생성 시 안내는 하되 응답을 기다리지 않도록 명시했다.
개발로그 작성은 보통 작업을 마무리하며 요청하는 일이다. 여기서 부수적인 질문 때문에 흐름이 멈추면 스킬이 성가셔진다. 안내는 하고 결정은 나중에 해도 되게 두는 편이 실제 사용 흐름에 맞다.
"없어서 메운 것"만 골랐다
보강한 10개 항목은 모두 실제로 부딪힌 지점에서 나왔다.
예를 들어 중복 회피 규칙은 두 번째 개발로그를 쓸 때 첫 번째와 겹치지 않게 임의로 조정한 데서 나왔다. 그건 규칙이 아니라 그때그때의 판단이었고, 판단에 의존하는 부분은 실행마다 결과가 달라진다.
다국어를 허용하되 헤더 키는 건드리지 않았다
제목: / 태그: 두 줄은 글쓴이의 발행 흐름과 맞물린 형식 계약이다. 본문 언어를 따라 번역하면 오히려 파이프라인이 깨진다.
번역 대상은 본문과 섹션 제목까지로 한정했다.
"무엇을 하지 않나"를 README 상단에 배치
개발로그를 다루는 도구라, 설치하는 쪽에서는 "내 코드나 커밋을 어디로 보내는 것 아닌가"라는 의심이 자연스럽다.
발행하지 않음, 수집하지 않음, 자격 증명 사용하지 않음을 앞에 못 박아 두는 편이 설치 결정에 도움이 된다고 봤다.
문제와 해결
첫 푸시가 권한 오류로 실패했다
첫 커밋 후 푸시하자 접근이 거부됐다.
Please make sure you have the correct access rights and the repository exists.
처음에는 GitHub CLI에 인증된 계정이 대상 저장소의 소유 계정과 다른 점을 의심했다. 하지만 실제 원인은 원격 URL과 SSH 설정의 불일치였다.
원격 주소가 기본 호스트를 그대로 쓰고 있었는데, SSH 설정에서 그 호스트는 다른 계정용 키에 매핑되어 있었다. 인증 자체는 성공하지만 권한 없는 계정으로 접속하고 있었던 것이다.
해결은 이미 설정되어 있던 계정별 SSH 호스트 별칭을 쓰도록 원격 URL을 교체하는 것이었다. 같은 커밋을 그대로 다시 밀어 성공했고 히스토리를 손댈 필요는 없었다.
계정이 여러 개인 환경에서는 원격 URL의 호스트 부분을 먼저 확인하는 것이 가장 빠른 진단 경로다.
Codex 설치본만 갱신되지 않았다
푸시 후 갱신 명령을 돌렸는데 Codex 쪽에는 새 규칙이 하나도 반영되지 않았다. 구조를 확인해 보니 두 에이전트의 설치 형태가 달랐다.
| 위치 | 형태 | 갱신 방식 |
|---|---|---|
| 공용 원본 | 실제 파일 | 갱신 명령으로 최신화 |
| Claude Code | 공용 원본을 가리키는 심볼릭 링크 | 자동으로 따라옴 |
| Codex | 실제 디렉터리 | 갱신되지 않음 |
여기서 "수동 사본이 자리를 차지해 링크를 걸지 못했다"고 판단했고, 그 판단은 틀렸다.
사본을 지우고 Codex를 대상으로 다시 설치해도 해당 위치에는 아무것도 생기지 않았다. 강제 복사 옵션을 붙여도 결과는 같았다. 설치 도구는 두 경우 모두 공용 원본 디렉터리에만 기록했다.
즉 이 도구는 Codex 디렉터리를 애초에 관리 대상으로 삼지 않는다. 설치 목록에는 Codex가 지원 대상으로 표시되지만 파일이 놓이는 곳은 공용 원본 한 곳뿐이다. 처음에 있던 Codex 사본은 도구가 만든 것이 아니라 이전에 손으로 복사해 둔 것이었다.
Codex가 공용 원본 경로를 직접 읽는지는 문서에서 근거를 찾지 못했다. 그래서 확실한 쪽을 택해 공용 원본에서 Codex 디렉터리로 최신 내용을 다시 복사해 뒀다.
이 경로는 도구가 갱신해 주지 않으므로 앞으로도 수동 관리가 필요하다.
같은 실수를 하루에 두 번 했다
중간에 "갱신 경로를 확인했다"고 기록했지만 그건 잘못된 결론이었다.
당시 세 위치 모두 최신으로 보였던 이유는 갱신이 동작해서가 아니라, 직접 파일을 복사해 뒀기 때문이다. 내가 만들어 둔 상태를 근거로 검증했으니 통과할 수밖에 없었다.
이후 해시를 비교해 어긋남을 찾아냈지만, 그 조치를 실행하는 과정에서 진단이 한 번 더 뒤집혔다. 상태를 만들어 놓고 그 상태를 근거로 확인하면 아무것도 검증되지 않는다는 교훈이 같은 날 두 번 반복된 셈이다.
검증한 내용
- 스킬 정의를 검증 스크립트로 확인해 유효 판정을 받았다. 규칙을 보강한 뒤에도 다시 통과시켰다.
- 커밋을 원격
main에 푸시하고 로컬과 원격이 동기화된 상태를 확인했다. - 갱신 명령을 실제로 실행해 성공 출력을 받았고, 공용 원본과 저장소 내용이 줄바꿈 차이를 제외하고 동일함을 확인했다.
- Codex 사본에 새 규칙 문구가 0건임을 확인해 갱신 누락을 특정했다.
- 사본 제거 후 재설치와 강제 복사 재설치를 각각 실행해, 설치 도구가 Codex 디렉터리에 아무것도 쓰지 않는다는 점을 두 번의 관측으로 확정했다.
- 복구 후 공용 원본과 Codex 사본의 해시 일치를 확인했다.
아직 확인하지 않은 것도 있다. 다른 사람의 환경에서 처음부터 설치하는 경로는 검증하지 않았다. 확인된 것은 이미 설치된 환경의 갱신 경로와 그 한계까지다.
다음 단계
- Codex가 공용 원본 경로를 직접 읽는지 확인한다. 읽는다면 Codex 사본은 불필요한 중복이고, 읽지 않는다면 갱신할 때마다 수동 복사가 계속 필요하다.
- 다른 환경에서 최초 설치를 한 번 통과시켜 본다.
- 라이선스 방침을 정하고 관련 파일과 문서를 함께 추가한다.
확인이 끝나기 전까지 스킬 수정 순서는 다음을 지킨다.
- 저장소에 푸시
- 갱신 명령 실행
- Codex 사본 재복사