From meko-agent-skills
Lists the user's Meko datapacks, shows authorization, supports search and pagination, and pins one as the active datapack on Claude Desktop. Triggers when the user says things like "switch datapack", "use the Acme datapack", "list my datapacks", "which datapack am I on", "pin Acme", or any request to change or inspect the active datapack. Persistence is via memory_add (Desktop has no SessionStart hook), so the pin survives across sessions until the user clears it.
How this skill is triggered — by the user, by Claude, or both
Slash command
/meko-agent-skills:meko-select-datapack-desktopThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
<!--
Claude Desktop has no SessionStart hook, so the Claude Code variant's sidecar/hook design doesn't apply here. Instead, the pin is stored as a memory with a structured tag, scoped to agent_id="claude_desktop" (Desktop's project bucket), and you re-read it on every Desktop turn before issuing Meko MCP tool calls. The pin outlives a single Desktop conversation — it sticks until the user explicitly clears it. Same project-scoped semantic as the Claude Code variant; different mechanism.
A single memory under agent_id="claude_desktop" carries the pin:
text: "meko_active_datapack=<uuid> name=<name> selected_at=<iso8601>"
metadata: { "type": "active-datapack-pin" }
You discover it by calling memory_search(query="meko_active_datapack", agent_id="claude_desktop", limit=1) at the start of any turn that's about to make a Meko MCP write. If you find a pin, pass datapack_id="<uuid>" to every Meko call that accepts it. If you don't find one, fall back to the server default (omit the parameter).
Trigger immediately on any of these signals:
memory_search for meko_active_datapack returned no result AND the user has more than one datapack — proactively offer to pin one.Before issuing a Meko MCP write tool call (memory_add, conversation_add_message, artifact_put, etc.), if you don't already know the active pin from this turn's earlier work:
memory_search(
query="meko_active_datapack",
agent_id="claude_desktop",
conversation_id="<this conversation's id>",
limit=1)
Parse the result. If a pin row is present, extract the UUID from the text body (after meko_active_datapack=) and pass it as datapack_id to every Meko MCP call this turn. If not, omit datapack_id and let the server resolve the default.
This is once per turn, not once per call. Cache within the turn.
Use a temporary conversation for browsing only. Call
conversation_create(agent_id="claude_desktop", title="Claude Desktop datapack selection") and use its returned ID for the read-only
datapack_list below and for the pin memory_add/memory_update in step 4.
Do not reuse this conversation for later capture. It lives in whatever datapack was active when it was created (typically the default), and a conversation cannot move between datapacks. Once a datapack is pinned, capture must flow through a new conversation created in the selected datapack — see step 5.
datapack_list(conversation_id="<this conversation's id>")
The response is an array; the fields you'll use are datapack_id,
datapack_name, created_at, account_id, and grant.
grant is the caller's actual authorization on the datapack — one of
"owner", "maintainer", "contributor", "viewer". Display it verbatim in
the Role column. Do not hardcode "Owner", do not invent or normalize the value
(render "maintainer" as maintainer, not Maintainer). The deployed
response is the source of truth — see references/role-display-future.md for
the taxonomy.
If the response has zero entries, tell the user: "You don't have any datapacks yet. Run datapack_create(name='<name>') to make one, or visit the Meko Cloud console." Stop here.
If the response has exactly one entry, auto-select it. Print: "Only one datapack: <name>. Auto-selecting. Run meko-select-datapack-desktop again with clear to unset." Skip the table; jump to step 4 (persist) and step 5 (confirm).
For 2+ datapacks, render a numbered table. Page size 10. Default sort: created_at DESC (newest first).
Your datapacks (showing 1-10 of 14):
# Name Role Created Status Active?
1 meko-local-setup owner 2026-04-30 ready ← (pinned)
2 meko_default_datapack owner 2026-04-30 ready
3 team-onboarding maintainer 2026-04-08 ready
4 q2-roadmap viewer 2026-03-22 ready
…
Reply with: a number (1-10) to pin · a substring to search · `next` / `prev` to page
· `clear` to unset · `cancel` to leave the current pin alone
The Role column shows each datapack's grant value verbatim (owner,
maintainer, contributor, viewer). Never hardcode "Owner" — shared
datapacks legitimately carry other grants, and misreporting them (e.g. showing
a maintainer grant as "Owner") misleads the user about their own access.
Mark the currently-pinned row with ← (pinned) based on the memory_search result (if any).
next / prev → re-render next/previous page.cancel → leave any existing pin in place; print "Cancelled. Active datapack unchanged." Stop.clear / none / unpin → see step 4's clear path.On first pin (no existing pin memory):
memory_add(
text="meko_active_datapack=<uuid> name=<name> selected_at=<iso8601>",
agent_id="claude_desktop",
conversation_id="<this conversation's id>",
metadata='{"type":"active-datapack-pin"}')
Verify the write with memory_search (the standard Meko verify-after-write rule from meko-mcp-tools-desktop). Capture the returned memory id.
On switch (existing pin memory found):
memory_update(
memory_id="<existing pin id>",
text="meko_active_datapack=<new uuid> name=<new name> selected_at=<iso8601>",
agent_id="claude_desktop",
conversation_id="<this conversation's id>")
Always update — never memory_add a second pin. Two pin memories will produce ambiguous reads.
On clear:
memory_delete_by_id(
memory_id="<existing pin id>",
agent_id="claude_desktop",
conversation_id="<this conversation's id>")
If memory_search returned no pin, there's nothing to delete — print "No pin was set; nothing to clear." and stop.
Conversation transition after a clear (same rule as a switch). The pin memory is now gone, but the session's current conversation still physically lives in the datapack that was pinned when it was created — a conversation cannot move to the default. You must pick exactly one of these; do not mix them:
datapack_id on its conversation_add_message calls — do NOT switch it to the default (that would fail). The clear only affects new sessions. Disclose: "Pin cleared. This chat keeps saving to <old datapack name>; new chats will use the default datapack."datapack_id (conversation_create(agent_id="claude_desktop")) and post all subsequent turns there. Stop posting to the old conversation. Disclose: "Pin cleared. Started a new chat context saving to the default datapack."Default to Option A (least disruptive) unless the user wants the switch to take effect right now. Either way, never send datapack_id=default to the pre-existing pinned conversation.
Pinned datapack `<name>` (`<uuid>`) for Claude Desktop.
This is stored as a memory under agent_id="claude_desktop". It will persist
across sessions until you run this skill again with `clear` (or `switch` to
a different datapack).
I'll read this pin via `memory_search` before each Meko MCP write so the
right `datapack_id` flows through automatically.
Then start a fresh conversation for capture in the selected datapack. The
temporary selection conversation from step 1 belongs to the datapack that was
active when it was created and cannot be moved. For subsequent capture this
session, call conversation_create(agent_id="claude_desktop", datapack_id="<the newly pinned uuid>", title="<topic>") and post turns
(conversation_add_message) to that conversation with the same
datapack_id. Do not keep posting to the selection conversation — doing so
would split capture across the old and new datapacks or fail outright.
selected_at); offer to delete the others.clear the stale pin.datapack_id) and tell the user "Couldn't read the active-datapack pin. Using server default for this call." Don't guess a UUID.datapack_id for that one call. Do NOT update the pin memory.Don't write to local files, don't use environment variables, don't ask the user to paste the UUID into every prompt. A single tagged memory is the entire mechanism. Anything else creates drift between what you think is pinned and what memory_search will report.
| File | What it covers |
|---|---|
references/cookbook.md | Sample list / search / select / clear transcripts on Desktop |
references/troubleshooting.md | Pin not recalled, duplicate pins, stale UUID recovery |
Creates, edits, and verifies skills using a test-driven development approach with pressure scenarios and subagents.
npx claudepluginhub yugabyte/meko-skills --plugin meko-agent-skills