이 글이 마지막으로 손본 때는이에요. 일부 내용이 더 이상 맞지 않을 수 있으니, 궁금한 점은 글쓴이에게 여쭤 주세요.
AI 번역简体中文한국어
GitHub를 둘러보다가 Innei의 SKILL 저장소를 발견했는데, 그 안에 session-to-skill-and-blog 스킬이 있었어요. 핵심 아이디어가 정말 기발합니다. 한 번의 삽질 엔지니어링 세션을 두 가지 결과물—재사용 가능한 AI 스킬 하나와 링크가 포함된 블로그 글 하나—로 정리하는 거예요. 철칙은 스킬을 먼저 쓰고 블로그를 나중에 쓰는 겁니다. 블로그는 스킬의 URL이 필요하고, SKILL.md 형식이 절차적인 내용을 먼저 정리하게 강제하기 때문이죠.
아이디어는 좋았지만, Innei 자신의 인프라에 맞게 커스터마이즈되어 있었어요—스킬은 그의 GitHub 저장소에 저장하고, 블로그는 mxs CLI를 통해 그의 mx-space 블로그로 발행하는 방식이었죠. 저도 mx-space(pinw.ca)를 운영하고 있기 때문에, 제 환경에 맞게 개조하기로 결정했습니다. 이 글은 그 과정에서 겪은 삽질과 배운 점을 기록한 것입니다.
첫 번째 함정: 서버가 로컬에 없음
스킬을 설치한 후 가장 먼저 한 일은 mxs auth login을(를) 실행하는 것이었습니다. 결과는?
또 localhost에 연결하고 있었어요. 분명 config.json 안에 api_url이(가) 이미 https://api.pinw.ca(이)고, current 포인터도 default을(를) 가리키고 있었는데 말이죠. 하지만 pnpm mxs이(가) monorepo 컨텍스트에서 프로필을 제대로 읽지 못한 겁니다.
프로필을 명시적으로 지정하니 해결되었습니다:
BASH
pnpm mxs ----profile default category list --output llm
# ✅ 9개 카테고리 반환
그래서 resolve-mxs.sh에 --profile default을(를) 추가해서, 모든 스크립트가 mxs를 호출할 때 자동으로 포함되도록 했습니다.
Note
교훈: monorepo 안에서 pnpm mxs을(를) 통해 호출할 때, 프로필 해석 경로가 전역 설치와 다를 수 있습니다. 명시적인 --profile이(가) current 포인터에 의존하는 것보다 더 신뢰할 수 있습니다.
하지만 제 mxs 버전(0.13.2)의 snippet 서브커맨드는 완전히 달랐어요—VFS 스타일이었습니다:
BASH
mxs snippet put --type skill --file SKILL.md "skills/name/SKILL.md"
게다가 경로는 반드시 /SKILL.md(으)로 끝나야 했습니다:
TEXT
✘ skill snippet path must end with /SKILL.md
이 제약은 문서에 전혀 언급되어 있지 않아서, 오류 메시지를 보고 거꾸로 유추할 수밖에 없었습니다. 개조 후의 push-skill.sh은(는) 60줄에서 30줄로 줄었습니다. VFS API 자체가 멱등적이어서—같은 경로에 반복해서 put을(를) 하면 그냥 업데이트가 되기 때문입니다.
네 번째 함정: 성급한 추상화
첫 번째 개조판에서 제가 저지른 전형적인 실수입니다. 사용자의 블로그 디렉토리에 hugo.pinw.ca/이(가) 있는 걸 보고 블로그가 Hugo라고 단정해 버린 거예요. 그래서 스킬 전체를 Hugo 워크플로우(hugo new(와)과 git push → Netlify)로 개조해버렸습니다. 사용자가 '지금 제 사이트도 mx-space예요'라고 정정해주더군요—알고 보니 pinw.ca/core/과(와) pinw.ca/Yohaku/이(가) 메인 사이트였습니다.
이 실수의 근본 원인은: 현재 아키텍처를 확인하지 않은 채 디렉토리 이름만 보고 추론한 데 있었습니다.hugo.pinw.ca은(는) 예전 블로그의 방치된 디렉토리였고, 실제로 돌아가고 있는 mx-space 백엔드는 바로 옆에 있는 pinw.ca/core/에 있었어요.
Warning
교훈: 디렉토리 이름만 보고 기술 스택을 추론하지 말 것. 먼저 사용자에게 묻거나, 실제로 돌아가고 있는 서비스를 확인하세요. hugo.xxx 같은 디렉토리가 있다고 해서 Hugo가 메인 사이트라는 뜻은 아닙니다.
최종 개조方案
다음은 개조 전후의 비교입니다:
구성 요소
Innei 원본
pinw.ca 버전
Skill 저장소
~/git/innei-repo/skill/
~/.pi/agent/skills/
mxs 호출
전역 mxs
pnpm mxs --profile default
스캐폴딩
README/symlink/git stage 포함
디렉토리 + stub만 생성
Snippet API
create --type skill
put --type skill(VFS)
설정
~/.config/innei-skills/config.json
설정 파일 불필요
총 7개 스크립트 중 5개를 다시 작성해야 했습니다(resolve-skill-repo.sh·scaffold-skill.sh·push-skill.sh·publish-post.sh·get-post.sh·update-post.sh). 1개는 새로 추가했고(resolve-mxs.sh), 1개는 그대로 유지했습니다(load-litexml.sh).
가져갈 판단 기준
이번 개조를 통해 세 가지 일반 원칙이 드러났습니다. mx-space에만 해당되는 얘기가 아닙니다:
실행 상태를 확인하라, 추론하지 마라. 디렉토리 이름이 hugo.xxx라고 해서 메인 사이트가 Hugo라는 뜻은 아닙니다. 먼저 ps(와)과 docker ps(와)과 curl을(를) 확인하고 나서 작업을 시작하세요.
CLI 도구의 global flag가 신뢰할 수 없을 때는 환경 변수를 사용하세요.--api-url의 서브커맨드 전달 동작은 버전에 따라 다르지만, MXS_API_URL은(는) 소스 코드에서 최우선 순위를 가집니다.
Monorepo 안에서의 CLI 호출에는 명시적인 프로필이 필요합니다.pnpm mxs의 컨텍스트 해석은 전역 mxs과(와) 다를 수 있습니다. --profile이(가) 유일하게 신뢰할 수 있는 위치 지정 방식입니다.
개조가 완료된 스킬은 이미 ~/.pi/agent/skills/session-to-skill-and-blog/에 자리 잡고 있으며, 이 글도 바로 그 스킬을 사용해 발행했습니다—개밥을 직접 먹는 셈이죠.
GitHub를 둘러보다가 Innei의 SKILL 저장소를 발견했는데, 그 안에 session-to-skill-and-blog 스킬이 있었어요. 핵심 아이디어가 정말 기발합니다. 한 번의 삽질 엔지니어링 세션을 두 가지 결과물—재사용 가능한 AI 스킬 하나와 링크가 포함된 블로그 글 하나—로 정리하는 거예요. 철칙은 스킬을 먼저 쓰고 블로그를 나중에 쓰는 겁니다. 블로그는 스킬의 URL이 필요하고, SKILL.md 형식이 절차적인 내용을 먼저 정리하게 강제하기 때문이죠.
아이디어는 좋았지만, Innei 자신의 인프라에 맞게 커스터마이즈되어 있었어요—스킬은 그의 GitHub 저장소에 저장하고, 블로그는 mxs CLI를 통해 그의 mx-space 블로그로 발행하는 방식이었죠. 저도 mx-space(pinw.ca)를 운영하고 있기 때문에, 제 환경에 맞게 개조하기로 결정했습니다. 이 글은 그 과정에서 겪은 삽질과 배운 점을 기록한 것입니다.
첫 번째 함정: 서버가 로컬에 없음
스킬을 설치한 후 가장 먼저 한 일은 mxs auth login을(를) 실행하는 것이었습니다. 결과는?
제 mx-space는 원격 서버에서 돌아가고 있고, API 주소는 https://api.pinw.ca인데, 로컬호스트가 아니었죠. --api-url 옵션을 추가해봤습니다:
소용없었어요. 계속 localhost를 찾더군요. 소스 코드를 뒤져보니 mxs auth login의 --api-url 전달 체인에 문제가 있었습니다—global flag가 auth 서브커맨드에서 제대로 연결되지 않은 거예요. 환경 변수로 바꿔서 시도했습니다:
이번에는 성공했습니다. 인증 후 설정이 ~/.config/mxs/profiles/default/config.json에 기록되었습니다.
교훈: mx-space CLI의 global flag와 서브커맨드 간 override 우선순위는 버전에 따라 일관되지 않습니다. 환경 변수 MXS_API_URL이(가) 가장 신뢰할 수 있는 크로스-버전 설정 방식입니다.
두 번째 함정: 프로필이 자동으로 활성화되지 않음
인증에 성공하고 나니 모든 게 해결된 줄 알았습니다. 바로 실행했죠:
그런데 auth status은(는) 정상이었습니다:
다음으로 mxs category list을(를) 확인해봤습니다:
또 localhost에 연결하고 있었어요. 분명 config.json 안에 api_url이(가) 이미 https://api.pinw.ca(이)고, current 포인터도 default을(를) 가리키고 있었는데 말이죠. 하지만 pnpm mxs이(가) monorepo 컨텍스트에서 프로필을 제대로 읽지 못한 겁니다.
프로필을 명시적으로 지정하니 해결되었습니다:
그래서 resolve-mxs.sh에 --profile default을(를) 추가해서, 모든 스크립트가 mxs를 호출할 때 자동으로 포함되도록 했습니다.
교훈: monorepo 안에서 pnpm mxs을(를) 통해 호출할 때, 프로필 해석 경로가 전역 설치와 다를 수 있습니다. 명시적인 --profile이(가) current 포인터에 의존하는 것보다 더 신뢰할 수 있습니다.
세 번째 함정: snippet API 버전 차이
원본 스킬의 push-skill.sh에서는 이렇게 사용했습니다:
하지만 제 mxs 버전(0.13.2)의 snippet 서브커맨드는 완전히 달랐어요—VFS 스타일이었습니다:
게다가 경로는 반드시 /SKILL.md(으)로 끝나야 했습니다:
이 제약은 문서에 전혀 언급되어 있지 않아서, 오류 메시지를 보고 거꾸로 유추할 수밖에 없었습니다. 개조 후의 push-skill.sh은(는) 60줄에서 30줄로 줄었습니다. VFS API 자체가 멱등적이어서—같은 경로에 반복해서 put을(를) 하면 그냥 업데이트가 되기 때문입니다.
네 번째 함정: 성급한 추상화
첫 번째 개조판에서 제가 저지른 전형적인 실수입니다. 사용자의 블로그 디렉토리에 hugo.pinw.ca/이(가) 있는 걸 보고 블로그가 Hugo라고 단정해 버린 거예요. 그래서 스킬 전체를 Hugo 워크플로우(hugo new(와)과 git push → Netlify)로 개조해버렸습니다. 사용자가 '지금 제 사이트도 mx-space예요'라고 정정해주더군요—알고 보니 pinw.ca/core/과(와) pinw.ca/Yohaku/이(가) 메인 사이트였습니다.
이 실수의 근본 원인은: 현재 아키텍처를 확인하지 않은 채 디렉토리 이름만 보고 추론한 데 있었습니다. hugo.pinw.ca은(는) 예전 블로그의 방치된 디렉토리였고, 실제로 돌아가고 있는 mx-space 백엔드는 바로 옆에 있는 pinw.ca/core/에 있었어요.
교훈: 디렉토리 이름만 보고 기술 스택을 추론하지 말 것. 먼저 사용자에게 묻거나, 실제로 돌아가고 있는 서비스를 확인하세요. hugo.xxx 같은 디렉토리가 있다고 해서 Hugo가 메인 사이트라는 뜻은 아닙니다.
최종 개조方案
다음은 개조 전후의 비교입니다:
총 7개 스크립트 중 5개를 다시 작성해야 했습니다(resolve-skill-repo.sh·scaffold-skill.sh·push-skill.sh·publish-post.sh·get-post.sh·update-post.sh). 1개는 새로 추가했고(resolve-mxs.sh), 1개는 그대로 유지했습니다(load-litexml.sh).
가져갈 판단 기준
이번 개조를 통해 세 가지 일반 원칙이 드러났습니다. mx-space에만 해당되는 얘기가 아닙니다:
개조가 완료된 스킬은 이미 ~/.pi/agent/skills/session-to-skill-and-blog/에 자리 잡고 있으며, 이 글도 바로 그 스킬을 사용해 발행했습니다—개밥을 직접 먹는 셈이죠.
Skill 주소: Innei/SKILL — session-to-skill-and-blog(원본, 이 글의 영감을 준 저장소)