Create a Tessl plugin: wrap your existing skills into a versioned, shareable bundle, decide what else it needs (rules, commands, MCP servers), validate, and publish.
91
88%
Does it follow best practices?
Impact
95%
1.25xAverage score across 5 eval scenarios
Advisory
Suggest reviewing before use
Turn the confirmed plan into real files, in the right place. Do not re-litigate the plan here, build it.
Create the plugin skeleton with the CLI. Inspect tessl plugin new --help first, and note two things it requires:
Pass --skill (with --skill-name and --skill-description) or --rules to seed initial content; it errors with neither.
Pass --workspace <name> explicitly. The workspace in --name workspace/plugin is not parsed from the name.
A single standalone skill → tessl skill new (creates the SKILL.md and its plugin.json).
A plugin → tessl plugin new --skill --skill-name <first> --skill-description "..." --workspace <ws>.
Wrapping an existing loose SKILL.md into a plugin → tessl skill import.
See references/plugin-anatomy.md.
tessl skill newTo add more skills to an existing plugin, create the file directly:
skills/<skill-name>/SKILL.md # plus a references/ folder as neededThe manifest's skills: ./skills/ discovers them automatically.
Do not run tessl skill new again inside a plugin to add a skill. That command always scaffolds a standalone skill-as-plugin, which nests a second plugin inside yours (skills/<name>/.tessl-plugin/...). tessl plugin lint may still call the result "valid", but tessl plugin pack silently drops the mis-nested skill, so the plugin ships incomplete. Only the plugin's own plugin.json should be CLI-scaffolded; individual SKILL.md files are authored directly.
description (what + when, it drives discovery) and lean, ordered steps, with depth pushed into references/. See references/shaping-and-decomposition.md.decompose-into-skills.Only add what the plan specified, do not pad.
.md under rules/ for an always-on convention. If the plan identified a convention the agent should always follow (see plan-composition), it belongs here, not in a skill..mcp.json when the plan calls for a capability. Point the manifest at it ("mcpServers": ".mcp.json"). Two transports: http (a URL) and stdio (a command plus args). Do not hard-code secrets..md under commands/ for a user-invoked action.Lint checks structure; pack confirms what actually ships. Because lint can pass on a mis-nested skill, always do both:
tessl plugin lint <plugin-dir>
tessl plugin pack <plugin-dir> --output /tmp/check.tgz
tar tzf /tmp/check.tgz | grep SKILL.md # every intended skill must appear
tar tzf /tmp/check.tgz | grep -E '(^|/)rules/[^/]+\.md$' || true # any rules the plan called for
tar tzf /tmp/check.tgz | grep -E '(^|/)commands/[^/]+\.md$' || true # any commands the plan called forOptionally install into a throwaway project (a file: dependency) and confirm the skills, rules, and any MCP servers materialise.
If the plugin ships an MCP server, scripts, or otherwise touches secrets, auth, file or network access, or CI, also run a security review (tessl review run security <plugin-dir>; inspect tessl review --help for the current form). Expect findings and triage each, a flagged item is not automatically a blocker but should be reviewed with the user.
The composition now exists. Point the user at the next steps: eval via tessl/skill-optimizer (a separate flow), and publish-plugin if they want to share it. Do not run evals here.
Stop when the composition is built, lints clean, packs with every intended skill, and the user knows the next steps.