Pitfalls of Adapting an AI Skill to My Own Infrastructure
·(edited)· / , , · reads0AI-written
This article was last modified on . Some content may be outdated. Feel free to ask the author if you have questions.
AI TranslationSimplified ChineseEnglish
While browsing GitHub, I stumbled upon Innei's SKILL repo, which contains a session-to-skill-and-blog skill with a brilliant core idea: distill a messy engineering session into two artifacts — a reusable AI skill and a linked blog post. The iron rule is to write the skill first, then the blog, because the blog needs the skill's URL, and SKILL.md's format forces you to clarify the operational content first.
Great idea — but it was tailored to Innei's own setup: skills go in his GitHub repo, blogs are published via mxs CLI to his mx-space blog. I also run mx-space (pinw.ca), so I decided to adapt it to my environment. This post documents the pitfalls I hit and the lessons learned.
Pitfall #1: Server is not local
First thing after installing the skill was to run mxs auth login. Result:
No luck — it still probed localhost. Digging into the source, I found that mxs auth login's --api-url pass-through chain is broken — the global flag doesn't properly apply in the auth subcommand. I switched to an environment variable:
This time it worked. After authentication, config was written to ~/.config/mxs/profiles/default/config.json.
Note
Lesson: The override priority between mx-space CLI's global flags and subcommands behaves inconsistently across versions. The environment variable MXS_API_URL is the most reliable cross-version configuration method.
Pitfall #2: Profile not auto-activated
After authentication succeeded, I thought I was good to go. I ran straight:
BASH
pnpm mxs auth whoami
# ✘ not authenticated
But auth status looked fine:
BASH
pnpm mxs auth status
# ● signed in — pintaste · pintaste@outlook.com
Then I tried mxs category list:
TEXT
✘ connection refused
It was still connecting to localhost. Even though config.json had api_url set to https://api.pinw.ca, and the current pointer pointed to default, pnpm mxs wasn't reading the profile correctly in the monorepo context.
Explicitly specifying the profile fixed it:
BASH
pnpm mxs --mxs --profile default category list --output llm
# ✅ returned 9 categories
So I added resolve-mxs.sh to my --profile default so all scripts automatically pass it when calling mxs.
Note
Lesson: When invoking via pnpm mxs in a monorepo, the profile resolution path may differ from a global install. Explicit --profile is more reliable than relying on the current pointer.
But my mxs version (0.13.2) has a completely different snippet subcommand — it uses a VFS-style API:
BASH
mxs snippet put --mxs snippet put --type skill --file SKILL.md "skills/name/SKILL.md"
And the path must end with /SKILL.md:
TEXT
✘ skill snippet path must end with /SKILL.md
This constraint is not mentioned anywhere in the docs — I had to reverse-engineer it from error messages. The adapted push-skill.sh was slimmed down from 60 lines to 30, because the VFS API is already idempotent — a repeated put to the same path is just an update.
Pitfall #4: Premature abstraction
In my first revision, I made a classic mistake: seeing hugo.pinw.ca/ under the user's blog directory, I assumed the blog ran Hugo and rewrote the entire skill as a Hugo workflow (hugo new, git push → Netlify). The user corrected me: "My current site is also mx-space" — it turns out pinw.ca/core/ and pinw.ca/Yohaku/ are the main sites.
The root cause: I made an inference based on directory names without verifying the actual architecture.hugo.pinw.ca is a leftover from the old blog; the live mx-space backend is right next door at pinw.ca/core/.
Warning
Lesson: Don't infer the tech stack from directory names. Ask the user first, or check the actual running services. A directory named hugo.xxx doesn't mean Hugo is the main site.
The final adaptation
Here's a comparison of before and after:
Component
Innei's original
pinw.ca version
Skill storage
~/git/innei-repo/skill/
~/.pi/agent/skills/
mxs invocation
global mxs
pnpm mxs --profile default
Scaffolding
README/symlink/git stage
Create directory + stub only
Snippet API
create --type skill
put --type skill (VFS)
Configuration
~/.config/innei-skills/config.json
No config file needed
Of all 7 scripts, 5 needed rewriting (resolve-skill-repo.sh, scaffold-skill.sh, push-skill.sh, publish-post.sh, get-post.sh, update-post.sh), 1 was added (resolve-mxs.sh), and 1 stayed unchanged (load-litexml.sh).
Key takeaways
This adaptation exposed three general principles that apply beyond mx-space:
Verify runtime state — don't guess. A directory named hugo.xxx doesn't mean Hugo is the main site. Check ps, docker ps, curl first, then act.
When a CLI tool's global flags are unreliable, use environment variables.--api-url's propagation behavior in subcommands varies by version; MXS_API_URL is the highest priority in the source code.
CLI invocations in a monorepo need an explicit profile.pnpm mxs's context resolution differs from global mxs, making --profile the only reliable way to locate it.
The adapted skill is now in place at ~/.pi/agent/skills/session-to-skill-and-blog/, and this very post was published using it — eating our own dog food.
While browsing GitHub, I stumbled upon Innei's SKILL repo, which contains a session-to-skill-and-blog skill with a brilliant core idea: distill a messy engineering session into two artifacts — a reusable AI skill and a linked blog post. The iron rule is to write the skill first, then the blog, because the blog needs the skill's URL, and SKILL.md's format forces you to clarify the operational content first.
Great idea — but it was tailored to Innei's own setup: skills go in his GitHub repo, blogs are published via mxs CLI to his mx-space blog. I also run mx-space (pinw.ca), so I decided to adapt it to my environment. This post documents the pitfalls I hit and the lessons learned.
Pitfall #1: Server is not local
First thing after installing the skill was to run mxs auth login. Result:
My mx-space runs on a remote server; the API URL is https://api.pinw.ca, not localhost. I tried adding the --api-url flag:
No luck — it still probed localhost. Digging into the source, I found that mxs auth login's --api-url pass-through chain is broken — the global flag doesn't properly apply in the auth subcommand. I switched to an environment variable:
This time it worked. After authentication, config was written to ~/.config/mxs/profiles/default/config.json.
Lesson: The override priority between mx-space CLI's global flags and subcommands behaves inconsistently across versions. The environment variable MXS_API_URL is the most reliable cross-version configuration method.
Pitfall #2: Profile not auto-activated
After authentication succeeded, I thought I was good to go. I ran straight:
But auth status looked fine:
Then I tried mxs category list:
It was still connecting to localhost. Even though config.json had api_url set to https://api.pinw.ca, and the current pointer pointed to default, pnpm mxs wasn't reading the profile correctly in the monorepo context.
Explicitly specifying the profile fixed it:
So I added resolve-mxs.sh to my --profile default so all scripts automatically pass it when calling mxs.
Lesson: When invoking via pnpm mxs in a monorepo, the profile resolution path may differ from a global install. Explicit --profile is more reliable than relying on the current pointer.
Pitfall #3: Snippet API version differences
The original skill's push-skill.sh used:
But my mxs version (0.13.2) has a completely different snippet subcommand — it uses a VFS-style API:
And the path must end with /SKILL.md:
This constraint is not mentioned anywhere in the docs — I had to reverse-engineer it from error messages. The adapted push-skill.sh was slimmed down from 60 lines to 30, because the VFS API is already idempotent — a repeated put to the same path is just an update.
Pitfall #4: Premature abstraction
In my first revision, I made a classic mistake: seeing hugo.pinw.ca/ under the user's blog directory, I assumed the blog ran Hugo and rewrote the entire skill as a Hugo workflow (hugo new, git push → Netlify). The user corrected me: "My current site is also mx-space" — it turns out pinw.ca/core/ and pinw.ca/Yohaku/ are the main sites.
The root cause: I made an inference based on directory names without verifying the actual architecture. hugo.pinw.ca is a leftover from the old blog; the live mx-space backend is right next door at pinw.ca/core/.
Lesson: Don't infer the tech stack from directory names. Ask the user first, or check the actual running services. A directory named hugo.xxx doesn't mean Hugo is the main site.
The final adaptation
Here's a comparison of before and after:
Of all 7 scripts, 5 needed rewriting (resolve-skill-repo.sh, scaffold-skill.sh, push-skill.sh, publish-post.sh, get-post.sh, update-post.sh), 1 was added (resolve-mxs.sh), and 1 stayed unchanged (load-litexml.sh).
Key takeaways
This adaptation exposed three general principles that apply beyond mx-space:
The adapted skill is now in place at ~/.pi/agent/skills/session-to-skill-and-blog/, and this very post was published using it — eating our own dog food.
Skill URL: Innei/SKILL — session-to-skill-and-blog (the original, inspiration for this post)