Claude Code skills are easy to write. The hard part nobody documents: how does the skill know where your app's files live on someone else's machine?
I hit this building a skill for my Mac screenshot app. The skill needs to read the latest capture. On my machine that folder is one path. On yours it's wherever you set it in preferences. Hardcode it and the skill breaks for everyone but me.
Here is the pattern that fixed it, in three parts.
A skill is a small markdown file in ~/.claude/skills/
. It tells Claude how to handle a class of requests. When your prompt matches, Claude reads the instructions and follows them, so you stop re-explaining the rules every session. Mine is a single SKILL.md, about 80 lines. You can read the whole thing in a minute: bickov/slimsnap-skill.
Integrations between a desktop app and a terminal agent usually fail one of two ways. You hardcode a path, and it breaks the moment the user moves the folder. Or you push config into the agent side, and every install becomes a manual setup step.
The fix is a config file at a known location that the app owns:
~/.slimsnap/config.json
The app writes its save folder there on every launch. The skill reads it on every invocation. Change the folder in the app's preferences and the skill picks it up on the next capture. Nothing to update on the agent side.
Cursor does the same shape with workspace settings. Raycast extensions do it with preferences. It's rare in the app-plus-agent space mostly because apps don't think about agent integration yet.
Three steps on every invocation:
~/.slimsnap/config.json
to find the captures folderThe capture format is open, MIT licensed: bickov/slimsnap-schema. If you want a skill for Aider or Codex CLI that consumes the same files, nothing is in your way.
[Alex writes this section: 3 or 4 sentences on what description phrasing failed to trigger the skill and what finally worked]
If you're building any tool that an agent should act on: pick a config path under the user's home folder, have the app own it and write it on launch, have the skill read it fresh every time. That's the whole trick.
The working example end to end: SlimSnap (free Mac app) plus the skill:
git clone https://github.com/bickov/slimsnap-skill ~/.claude/skills/slimsnap
Capture something broken, drag an arrow at it, type what you want changed, then in Claude Code: fix this from my screenshot
.
Longer write-up of why the handoff is JSON and what's in the format: on my blog.