CommunityCoding & Developmentgithub.com

anhhung04/tracecat-manage-skills

Use when creating, uploading, updating, publishing, or re-binding a local Agent Skill directory through Tracecat MCP, including pushing a fix to a skill an agent preset already uses.

What is tracecat-manage-skills?

tracecat-manage-skills is a Claude Code agent skill that use when creating, uploading, updating, publishing, or re-binding a local Agent Skill directory through Tracecat MCP, including pushing a fix to a skill an agent preset already uses.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/anhhung04/omp-tracecat/tree/HEAD/skills/tracecat-manage-skills

Installed? Explore more Coding & Development skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Manage Tracecat skills

Tracecat MCP ships six skill tools: list_skills, get_skill, prepare_skill_download, prepare_skill_upload, complete_skill_upload, and publish_skill.

Writes are staged, not inlined. File bytes never travel as tool arguments: prepare_skill_upload takes metadata only — path, SHA-256, size, content type — and returns a short-lived PUT URL per file; the bytes go to those URLs over plain HTTP; complete_skill_upload then attaches the staged blobs and replaces the draft. Do not look for an inline content_base64 argument, and never read file bytes into context to send them.

The bundled helper removes the parts that are error-prone by hand: the safe directory walk, symlink rejection, root SKILL.md enforcement, and SHA-256 digests.

Upload a skill

The same four steps create a skill and replace an existing one. The only difference is which identity arguments prepare_skill_upload takes.

  1. Resolve the target workspace with list_workspaces, then call list_skills. For a new skill, confirm the name is free — omitting skill_id always creates a new row, so a second create yields two skills with the same name and different slugs. For an existing skill, take its skill_id.

  2. Build the metadata array:

    python3 <this-skill-dir>/scripts/upload_skill_files.py metadata <local-skill-dir>
    

    It prints the files array verbatim: one entry per file with path, sha256, size_bytes, and content_type. No file contents.

  3. Call prepare_skill_upload with workspace_id and that files array, plus either:

    • name (and optional description) and no skill_id, to create a skill; or
    • skill_id and no name/description, to replace an existing skill's draft.

    For a create, pass the same name the local frontmatter declares — the server merges name and description into the stored root SKILL.md frontmatter before validating, so a mismatched argument silently rewrites what gets stored.

    The response carries skill_id, base_revision, created, and a per-file upload_id, upload_url, method, headers, and expires_at.

  4. PUT each file's raw bytes to its upload_url with the returned method and headers, straight from disk. The URLs are short-lived; check expires_at and re-prepare rather than retrying a stale one.

  5. Call complete_skill_upload with workspace_id, skill_id, the base_revision from step 3, and a files array of {"path": ..., "upload_id": ...} for every file. This replaces the draft and does not publish.

  6. Call publish_skill with the skill_id when the skill should be attachable to presets. An unpublished draft cannot be bound.

base_revision is a concurrency guard. A draft_revision_conflict means someone else edited the draft since step 3 — call get_skill to see the current draft_revision and what a complete-tree replacement would delete, then re-prepare.

Updating a live skill

A fix that stops after complete_skill_upload changes nothing that any agent runs. Three steps, in order:

  1. prepare_skill_upload with skill_id → PUT the bytes → complete_skill_upload. This replaces the draft. It does not publish.
  2. publish_skill with the same skill_id. Skills are versioned; this mints a new immutable version and moves the skill's current_version_id.
  3. update_agent_preset with the consuming preset's skills list — the same {"skill_id": ...} entries it already had. Each binding is re-pinned to that skill's current published version at write time, so a preset bound before step 2 keeps running the old version until this call rewrites it.

Skipping step 3 is the classic failure: the new version exists, the preset never sees it.

Verify by re-fetching. get_skill without path returns the draft manifest — paths, digests, sizes, draft_revision, is_publishable, validation_errors — and never file contents; get_skill with path reads one file, inline when it is small UTF-8 text. list_skills shows the skill's current_version_id; get_agent_preset shows skills[].skill_version_id and skills[].skill_version. Confirm both moved.

This is routine, reversible work. Every published version is immutable and still bound-able, so a bad push is undone by publishing a corrected tree and re-binding. Do it rather than narrating risk; reserve caution for operations that actually cannot be undone.

Declaring the skill's tools

A skill carries its own tools. Declare them in the root SKILL.md frontmatter under metadata.tools, as registry action names or mcp.<slug> / mcp.<slug>.<tool> entries, up to 64 per skill:

---
name: slack-triage
description: Post and thread triage updates in Slack.
metadata:
  tools:
    - tools.slack.post_message
    - tools.slack.list_replies
---

Every preset the skill is attached to receives those tools on top of its own actions allowlist. They are granted as soon as the preset resolves, whether or not the model opens the skill; only the skill's instructions load on demand.

Prefer this over listing the same tools on each preset's actions when the tools group naturally and several agents reuse them — one edit and a re-publish then updates every consuming preset. Keep a tool on the preset's actions when it is specific to that one agent.

One caveat: a preset's namespaces filter applies to the registry tools in the union and silently blocks the ones outside it. After attaching a skill to a namespace-restricted preset, check tool_policy.blocked_tools on get_agent_preset. MCP tools a skill declares (mcp.<slug> / mcp.<slug>.<tool>) are not filtered by namespaces and do not appear there.

Changing metadata.tools changes what agents can execute, so it follows the same three steps as any other fix: replace the draft, publish_skill, then update_agent_preset to re-pin the binding. A read of the resulting preset shows the granted tools as one flat list in tool_policy.actions, with no per-skill provenance — the union is what you can verify.

Size

Bytes no longer pass through model context, but each file still has a server-side size limit and a whole tree is still easier to review when it is small and text-only.

  • Prefer Markdown, YAML, and scripts. Host a large binary asset elsewhere and reference it.
  • Move long-form detail into references/ files the agent reads on demand rather than into SKILL.md.
  • If a tree is too large to reason about, split the skill itself into two skills. Do not split one tree across several complete_skill_upload calls — each call replaces the entire draft, so a partial call deletes everything it omits.

Hard rules

  • Omitting skill_id creates; passing it replaces. Never create against a name that already exists — the slug retry makes the duplicate succeed instead of failing.
  • Every write replaces the entire draft. Files absent from the local directory are deleted from the skill. Always send the complete tree.
  • Upload every prepared file before calling complete_skill_upload, and pass every path back with its upload_id.
  • Never inline file bytes or base64 into a tool argument, and never read an upload or download URL's bytes into context. Stream to and from disk.
  • Publishing does not move existing preset bindings. Re-write the preset's skills list to pick up a new version.
  • Reject symlinked files and directories, and never send content from outside the selected skill root. The helper enforces this; do not work around it.
  • The root file must be exactly SKILL.md, at the top level, and valid UTF-8. The server rejects a file set without it.
  • If the client cannot execute local scripts, say so and give the user the helper command to run. Do not substitute model-generated digests.

References

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Related Skills