{"id":104,"date":"2026-10-31T08:00:00","date_gmt":"2026-10-31T07:00:00","guid":{"rendered":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/"},"modified":"2026-10-16T14:00:12","modified_gmt":"2026-10-16T12:00:12","slug":"packaging-skills-agents-and-hooks-as-a-claude-code-plugin","status":"publish","type":"post","link":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/","title":{"rendered":"Packaging skills, agents and hooks as a Claude Code plugin"},"content":{"rendered":"<p>When I started using Claude Code seriously for TYPO3 upgrades, my setup lived in the <code>.claude\/<\/code> folder of each project: a few skills, two or three subagents, a hook script. Then I copied that folder into the next project. And the next. After a month I had five slightly different versions of the same guard hook, and the best fix was in a project I had already closed.<\/p>\n<p>Claude Code plugins solve exactly this. A plugin is a directory with a fixed layout that bundles skills, agents, hooks, MCP servers and more. You install it from a marketplace, it has a version, and every project uses the same copy. This post shows how I packaged my <code>typo3-project-migration<\/code> plugin, the one that did the legwork for the hoja.in move from TYPO3 7.6 to 14.3.<\/p>\n<h2>The layout<\/h2>\n<p>The most common mistake first: only the manifest goes into <code>.claude-plugin\/<\/code>. Everything else sits at the plugin root. This is the real tree of my plugin, without <code>node_modules<\/code> and CI files:<\/p>\n<pre><code class=\"language-text\">typo3-project-migration\/\n\u251c\u2500\u2500 .claude-plugin\/\n\u2502   \u251c\u2500\u2500 plugin.json\n\u2502   \u2514\u2500\u2500 marketplace.json\n\u251c\u2500\u2500 skills\/\n\u2502   \u251c\u2500\u2500 typo3-project-migration\/\n\u2502   \u2502   \u251c\u2500\u2500 SKILL.md\n\u2502   \u2502   \u251c\u2500\u2500 references\/   (hop cards v10 \u2192 v14, troubleshooting, ...)\n\u2502   \u2502   \u2514\u2500\u2500 scripts\/      (inventory.sh, project-gate.sh, t3.sh, ...)\n\u2502   \u251c\u2500\u2500 assess\/SKILL.md\n\u2502   \u251c\u2500\u2500 verify\/SKILL.md\n\u2502   \u2514\u2500\u2500 dev-companion\/SKILL.md\n\u251c\u2500\u2500 agents\/\n\u2502   \u251c\u2500\u2500 project-scout.md\n\u2502   \u251c\u2500\u2500 extension-auditor.md\n\u2502   \u251c\u2500\u2500 upgrade-strategist.md\n\u2502   \u2514\u2500\u2500 upgrade-reviewer.md\n\u251c\u2500\u2500 hooks\/\n\u2502   \u251c\u2500\u2500 hooks.json\n\u2502   \u2514\u2500\u2500 scripts\/guard-bash.sh\n\u251c\u2500\u2500 scripts\/selftest.sh\n\u2514\u2500\u2500 CHANGELOG.md<\/code><\/pre>\n<p>Skills are folders with a <code>SKILL.md<\/code>; scripts and reference files the skill needs live next to it. Agents are single Markdown files with frontmatter. Hooks are configured in <code>hooks\/hooks.json<\/code>. Each of these is a default location, so Claude Code finds them without any configuration. Every component is namespaced with the plugin name, so the skill <code>verify<\/code> appears as <code>typo3-project-migration:verify<\/code> and cannot clash with a <code>verify<\/code> skill from another plugin.<\/p>\n<h2>Step 1: the manifest<\/h2>\n<p><code>.claude-plugin\/plugin.json<\/code> is optional; only <code>name<\/code> is required when you write one. I write one anyway, because the version and the description matter once other people install the plugin:<\/p>\n<pre><code class=\"language-json\">{\n  \"name\": \"typo3-project-migration\",\n  \"displayName\": \"TYPO3 Project Migration\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Upgrade whole TYPO3 projects from v10 to v14, one LTS at a time.\",\n  \"author\": {\n    \"name\": \"Hoja Mustaffa Abdul Latheef\",\n    \"url\": \"https:\/\/jweiland.net\"\n  },\n  \"license\": \"MIT\",\n  \"keywords\": [\"typo3\", \"migration\", \"upgrade\", \"composer\", \"ddev\"]\n}<\/code><\/pre>\n<p>Use kebab-case for <code>name<\/code>. The validator also refuses names that look like Anthropic&#8217;s own plugins (for example anything starting with <code>claude-<\/code>), so do not call yours <code>claude-typo3<\/code>.<\/p>\n<h2>Step 2: agents with a model per job<\/h2>\n<p>Agents are where a plugin pays off most for me, because each one can have its own tools and model. A read-only scout that greps through templates does not need the biggest model; the reviewer that has to find what the green test run misses does. The frontmatter of the reviewer:<\/p>\n<pre><code class=\"language-markdown\">---\nname: upgrade-reviewer\ndescription: Adversarial reviewer for one finished hop of a TYPO3 project upgrade. Reads the hop's commits, the gate output, the ledger and the plan, and hunts for what the gate misses. Read-only.\ntools: Read, Grep, Glob, Bash\nmodel: opus\n---\n\nYou review one hop of a TYPO3 project upgrade, and you don't trust the green gate. You change nothing.<\/code><\/pre>\n<p>In my plugin the scout runs on Haiku, the extension auditor on Sonnet, the strategist and the reviewer on Opus. The description is not decoration: it is what the main session reads to decide when to delegate, so write it like a job ad, with the trigger words people actually use.<\/p>\n<h2>Step 3: hooks that travel with the plugin<\/h2>\n<p>A rule in a prompt is a wish. A hook is enforced by Claude Code, outside the model. My plugin ships one <code>PreToolUse<\/code> hook for the Bash tool:<\/p>\n<pre><code class=\"language-json\">{\n  \"hooks\": {\n    \"PreToolUse\": [\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"\"${CLAUDE_PLUGIN_ROOT}\/hooks\/scripts\/guard-bash.sh\"\"\n          }\n        ]\n      }\n    ]\n  }\n}<\/code><\/pre>\n<p><code>${CLAUDE_PLUGIN_ROOT}<\/code> resolves to the installed plugin directory, which changes with every version, so never hard-code a path and never write state there. The script reads the tool call as JSON on stdin and answers with a decision. The core of it:<\/p>\n<pre><code class=\"language-bash\">if has '(typo3|t3.sh)[[:space:]]+[^|;&amp;]*(extension:setup|upgrade:run|upgrade:mark:undone)'; then\n  recent=\"$(find .project-migration\/backups .ddev\/db_snapshots -maxdepth 1 -mmin -1440 \n    ( -name '*.sql' -o -name '*.sql.gz' -o -name '*.gz' ) 2&gt;\/dev\/null | head -1 || true)\"\n  if [[ -z \"$recent\" ]]; then\n    decide deny \"No database dump from the last 24 h. Take one first, then run it again.\"\n  fi\nfi<\/code><\/pre>\n<p><code>decide<\/code> prints a small JSON object with <code>hookSpecificOutput.permissionDecision<\/code> set to <code>deny<\/code> or <code>ask<\/code> and a reason that Claude sees. So the agent gets told why, takes the dump with <code>ddev snapshot<\/code>, and tries again. On hoja.in this is the hook that blocked database writes until a fresh dump existed. It also asks before <code>ddev import-db<\/code> and denies <code>--ignore-platform-reqs<\/code> and <code>git commit --no-verify<\/code>.<\/p>\n<h2>Step 4: a marketplace for the team<\/h2>\n<p>A marketplace is just a <code>.claude-plugin\/marketplace.json<\/code> that lists plugins and where to get them. My plugin repository is its own marketplace, with the plugin at the root:<\/p>\n<pre><code class=\"language-json\">{\n  \"name\": \"typo3-project-migration\",\n  \"owner\": { \"name\": \"Hoja Mustaffa Abdul Latheef\" },\n  \"plugins\": [\n    {\n      \"name\": \"typo3-project-migration\",\n      \"source\": \".\/\",\n      \"description\": \"Upgrade whole TYPO3 projects from v10 to v14, one LTS at a time.\"\n    }\n  ]\n}<\/code><\/pre>\n<p>For a team with several plugins, one repository with a <code>plugins\/<\/code> folder and one entry per plugin works better. Keep the entry <code>name<\/code> and the <code>name<\/code> in <code>plugin.json<\/code> identical; a mismatch gives confusing &#8220;not found&#8221; errors at install time.<\/p>\n<p>Then, in the shell:<\/p>\n<pre><code class=\"language-bash\">claude plugin validate .\/typo3-project-migration\nclaude plugin marketplace add .\/typo3-project-migration\nclaude plugin install typo3-project-migration@typo3-project-migration\n\n# while developing: load the plugin directly, no install\nclaude --plugin-dir .\/typo3-project-migration<\/code><\/pre>\n<p>To make a project suggest the marketplace and plugin to everybody who opens it, commit this to the project&#8217;s <code>.claude\/settings.json<\/code> (the repository name is a placeholder for your own):<\/p>\n<pre><code class=\"language-json\">{\n  \"extraKnownMarketplaces\": {\n    \"typo3-tools\": {\n      \"source\": { \"source\": \"github\", \"repo\": \"your-org\/claude-typo3-plugins\" }\n    }\n  },\n  \"enabledPlugins\": {\n    \"typo3-project-migration@typo3-tools\": true\n  }\n}<\/code><\/pre>\n<h2>Step 5: versions and a self-test<\/h2>\n<p>The <code>version<\/code> in <code>plugin.json<\/code> pins users to that version until you change it. So a fix only reaches your colleagues when you bump the version. I keep a <code>CHANGELOG.md<\/code> in Keep a Changelog format, and a <code>scripts\/selftest.sh<\/code> that runs in CI and checks the boring things: all manifests are valid JSON, the changelog has an entry for the current version, every skill and agent has frontmatter with a real description, and every agent declares a model. Plus <code>claude plugin validate --strict<\/code>, which turns warnings into failures.<\/p>\n<p>One more thing to know: when you add a marketplace from a local path, Claude Code reads the plugin files in place. Your edits are live at the next session start or after <code>\/reload-plugins<\/code>, without a version bump. Great for development, but remember that your colleagues who installed from git do not have your local edits.<\/p>\n<h2>Was it worth it?<\/h2>\n<p>Yes. The guard hook exists once, with a self-test. When I improve an agent or a hook, every project gets the better version with the next update instead of the next copy-paste. If you have a <code>.claude\/<\/code> folder that you copied more than twice, package it.<\/p>\n<h2>Further reading<\/h2>\n<ul>\n<li><a href=\"https:\/\/code.claude.com\/docs\/en\/plugins-reference\">Claude Code plugin manifest reference<\/a><\/li>\n<li><a href=\"https:\/\/code.claude.com\/docs\/en\/plugin-marketplaces\">Create a plugin marketplace<\/a><\/li>\n<li><a href=\"https:\/\/code.claude.com\/docs\/en\/hooks\">Claude Code hooks reference<\/a><\/li>\n<li><a href=\"https:\/\/code.claude.com\/docs\/en\/sub-agents\">Claude Code subagents<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Copied .claude folders drift fast. How I package skills, agents and a guard hook as a Claude Code plugin with a marketplace, versions and a self-test.<\/p>\n","protected":false},"author":1,"featured_media":105,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18],"tags":[34,37,35],"class_list":["post-104","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-engineering","tag-ai-agents","tag-automation","tag-claude-code"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Packaging skills, agents and hooks as a Claude Code plugin<\/title>\n<meta name=\"description\" content=\"Package Claude Code skills, subagents and hooks as a plugin: plugin.json, directory layout, a local marketplace for the team, versioning and validation.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Packaging skills, agents and hooks as a Claude Code plugin\" \/>\n<meta property=\"og:description\" content=\"Package Claude Code skills, subagents and hooks as a plugin: plugin.json, directory layout, a local marketplace for the team, versioning and validation.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/\" \/>\n<meta property=\"og:site_name\" content=\"Hoja Mustaffa Abdul Latheef \u2013 Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-31T07:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Hoja Mustaffa Abdul Latheef\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@hojaonline\" \/>\n<meta name=\"twitter:site\" content=\"@hojaonline\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Hoja Mustaffa Abdul Latheef\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/\"},\"author\":{\"name\":\"Hoja Mustaffa Abdul Latheef\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"headline\":\"Packaging skills, agents and hooks as a Claude Code plugin\",\"datePublished\":\"2026-10-31T07:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/\"},\"wordCount\":828,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"image\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin.jpg\",\"keywords\":[\"AI agents\",\"Automation\",\"Claude Code\"],\"articleSection\":[\"AI engineering\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/\",\"name\":\"Packaging skills, agents and hooks as a Claude Code plugin\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin.jpg\",\"datePublished\":\"2026-10-31T07:00:00+00:00\",\"description\":\"Package Claude Code skills, subagents and hooks as a plugin: plugin.json, directory layout, a local marketplace for the team, versioning and validation.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/#primaryimage\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin.jpg\",\"contentUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin.jpg\",\"width\":1200,\"height\":630,\"caption\":\"One plugin instead of ten copies\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/hoja.in\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Packaging skills, agents and hooks as a Claude Code plugin\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/\",\"name\":\"Hoja Mustaffa Abdul Latheef \u2013 Blog\",\"description\":\"Notes from daily work with TYPO3, PHP and AI-assisted engineering\",\"publisher\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/hoja.in\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\",\"name\":\"Hoja Mustaffa Abdul Latheef\",\"logo\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/image\\\/\"},\"description\":\"Senior TYPO3 Developer at jweiland.net, TYPO3 CMS Certified Developer. I write about TYPO3 upgrades, extension development, PHP and AI-assisted engineering with Claude Code.\",\"sameAs\":[\"https:\\\/\\\/hoja.in\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Packaging skills, agents and hooks as a Claude Code plugin","description":"Package Claude Code skills, subagents and hooks as a plugin: plugin.json, directory layout, a local marketplace for the team, versioning and validation.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/","og_locale":"en_US","og_type":"article","og_title":"Packaging skills, agents and hooks as a Claude Code plugin","og_description":"Package Claude Code skills, subagents and hooks as a plugin: plugin.json, directory layout, a local marketplace for the team, versioning and validation.","og_url":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/","og_site_name":"Hoja Mustaffa Abdul Latheef \u2013 Blog","article_published_time":"2026-10-31T07:00:00+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin.jpg","type":"image\/jpeg"}],"author":"Hoja Mustaffa Abdul Latheef","twitter_card":"summary_large_image","twitter_creator":"@hojaonline","twitter_site":"@hojaonline","twitter_misc":{"Written by":"Hoja Mustaffa Abdul Latheef","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/#article","isPartOf":{"@id":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/"},"author":{"name":"Hoja Mustaffa Abdul Latheef","@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"headline":"Packaging skills, agents and hooks as a Claude Code plugin","datePublished":"2026-10-31T07:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/"},"wordCount":828,"commentCount":0,"publisher":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"image":{"@id":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/#primaryimage"},"thumbnailUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin.jpg","keywords":["AI agents","Automation","Claude Code"],"articleSection":["AI engineering"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/","url":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/","name":"Packaging skills, agents and hooks as a Claude Code plugin","isPartOf":{"@id":"https:\/\/hoja.in\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/#primaryimage"},"image":{"@id":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/#primaryimage"},"thumbnailUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin.jpg","datePublished":"2026-10-31T07:00:00+00:00","description":"Package Claude Code skills, subagents and hooks as a plugin: plugin.json, directory layout, a local marketplace for the team, versioning and validation.","breadcrumb":{"@id":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/#primaryimage","url":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin.jpg","contentUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin.jpg","width":1200,"height":630,"caption":"One plugin instead of ten copies"},{"@type":"BreadcrumbList","@id":"https:\/\/hoja.in\/blog\/packaging-skills-agents-and-hooks-as-a-claude-code-plugin\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/hoja.in\/blog\/"},{"@type":"ListItem","position":2,"name":"Packaging skills, agents and hooks as a Claude Code plugin"}]},{"@type":"WebSite","@id":"https:\/\/hoja.in\/blog\/#website","url":"https:\/\/hoja.in\/blog\/","name":"Hoja Mustaffa Abdul Latheef \u2013 Blog","description":"Notes from daily work with TYPO3, PHP and AI-assisted engineering","publisher":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hoja.in\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b","name":"Hoja Mustaffa Abdul Latheef","logo":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/image\/"},"description":"Senior TYPO3 Developer at jweiland.net, TYPO3 CMS Certified Developer. I write about TYPO3 upgrades, extension development, PHP and AI-assisted engineering with Claude Code.","sameAs":["https:\/\/hoja.in\/"]}]}},"_links":{"self":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/104","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/comments?post=104"}],"version-history":[{"count":1,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/104\/revisions"}],"predecessor-version":[{"id":175,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/104\/revisions\/175"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/media\/105"}],"wp:attachment":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/media?parent=104"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/categories?post=104"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/tags?post=104"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}