{"slug": "your-claude-skill-is-invisible-to-codex-here-s-how-to-fix-it", "title": "Your Claude Skill Is Invisible to Codex. Here's How to Fix It.", "summary": "A developer proposes a standardized format for agent skill files to solve interoperability issues between AI coding agents like Claude Code and Codex. The current fragmented landscape forces developers to manually rewrite the same skill for each agent, incurring an 'interop tax'. The solution involves splitting capabilities into contracts and implementations, analogous to ERC-20 tokens, enabling any agent to load any skill.", "body_md": "Disclosure up front: I build\n\n[agentproto], whose spec\n\nregistry (the AIPs) is the last third of this piece. The problem in the first\n\nhalf stands on its own, and the walkthrough uses real, checkable commands.\n\nCorrections welcome — file an issue.\n\nYou spent an afternoon writing a good skill. A `SKILL.md`\n\n, a couple of scripts,\n\na crisp description so the model knows when to reach for it. Claude Code picks it\n\nup and uses it perfectly.\n\nNow open Codex in the same repo. Nothing. The skill is invisible — wrong folder,\n\nwrong format, wrong dialect. Point a cheap local model at the task and you get\n\nthe same blank stare. You wrote the capability once, and exactly one agent can\n\nsee it.\n\nThe one idea, if you remember nothing else:\n\nEveryone converged on folders of markdown with zero interop. It's Ethereum\n\nbefore ERC-20 — the primitive is proven, and nothing can hold anyone else's.\n\nOpen any serious agent-driven repo in 2026 and you find the same sediment: a\n\n`CLAUDE.md`\n\n, an `AGENTS.md`\n\n, maybe a `GEMINI.md`\n\nsaying mostly the same thing; a\n\n`.claude/skills/`\n\nfolder full of `SKILL.md`\n\n; Codex agents in TOML; a `.mcp.json`\n\n;\n\nsomebody's `OPERATOR.md`\n\n. Every tool independently discovered the same primitive\n\n— **agent behavior configured as files in the repo** — and every tool speaks its\n\nown dialect of it.\n\nThis is a genuinely good primitive, and the convergence is evidence it's right.\n\nFiles are diffable, reviewable, versionable; they ride along in git; agents can\n\nread *and write* them, which is what lets an agent improve its own tooling.\n\nAnthropic's harness team, describing their long-running app builder (March\n\n2026), put it plainly: **\"communication was handled via files.\"**\n\nRepository as constitution.Here's why this shape won: each new agent\n\nsession arrives like a new contributor with shell access but no knowledge of\n\nyour team's norms, so a short`AGENTS.md`\n\nacts as the repo's constitution for\n\nagents. The pattern is settled. The interop is what's missing.\n\nThe dialects are the whole problem. They don't even agree on names: it's\n\n`skill.title`\n\nin one flavor, `skill.name`\n\nin another, three incompatible spins on\n\n`AGENTS.md`\n\n. A capability you wire into one product's config is invisible to the\n\nother four agents in your fleet — so *you* re-wire it, by hand, every time you add\n\na brand.\n\n**That manual re-wiring, with your name on it, is the interop tax — and it's the\npart of \"orchestration\" nobody sells you a fix for.** Before we build one, do the\n\nWhere are you?0 duplicated declarations— you're single-agent, not\n\nyour problem yet.2–3(a`CLAUDE.md`\n\nhere, an`AGENTS.md`\n\nthere) — you're\n\npaying the tax quietly, once per new brand.4+— youarethe interop\n\nlayer, by hand, and it costs an afternoon per new agent.\n\nWatch where the platform layer is heading, because it validates the whole idea.\n\nAnthropic's Managed Agents (April 2026) virtualizes the *runtime*: the session is\n\nan append-only log, the harness is disposable, the sandbox sits behind one\n\ngeneric `execute`\n\ninterface. Stable contracts between layers, so each layer swaps\n\nfreely.\n\nDesign it like an OS.The Managed Agents write-up is explicit about the\n\nprinciple: to build infrastructure that accommodates \"programs as yet unthought\n\nof,\" you\"decouple the brain from the hands via a uniform tool interface\"and\n\nput stable interfaces over swappable implementations.\n\nThat's exactly the right instinct — and it's hosted, and it's Claude-only. The\n\nsame layering, done in the open, is just as valuable one floor *below* the\n\nruntime: stable contracts for the **files**. What a tool promises, how a driver\n\nimplements it, what a skill declares. Make those contracts public and versioned,\n\nand any host can load any capability — the way any wallet holds any ERC-20.\n\nSo let's actually build one and watch it reach three different agents.\n\nThe trick is to split what most formats fuse. A capability is two things: a\n\n**contract** (its name, its inputs and outputs, whether it's allowed to mutate\n\nanything) and an **implementation** (the code that runs). Fuse them and the\n\ncapability is welded to one runtime. Separate them and the contract is the part\n\nthat ports.\n\nHere's a docs-search tool as a pure contract — agentproto's `defineTool`\n\n(the AIP-14 `TOOL.md`\n\nspec). Note what's *not* here: no execute body.\n\n``` js\n// tools/docs-search/TOOL.ts — the contract, and nothing else\nimport { defineTool } from \"@agentproto/tool\"\nimport { z } from \"zod\"\n\nexport const docsSearch = defineTool({\n  id: \"docs.search\",\n  description: \"Search the team's internal docs. Returns titles + URLs.\",\n  inputSchema: z.object({ query: z.string(), limit: z.number().default(5) }),\n  outputSchema: z.object({\n    hits: z.array(z.object({ title: z.string(), url: z.string() })),\n  }),\n  mutates: [],        // read-only → no approval gate needed\n  approval: \"auto\",\n})\n```\n\nThe contract carries identity, schemas, and a *side-effect profile* — `mutates`\n\nand `approval`\n\nare how a supervisor later decides whether this call needs a human\n\n(read-only tools sail through; a tool that writes files gets gated). One file,\n\none declared promise, zero opinion about how it's fulfilled.\n\n**This is the piece that makes a capability portable: a promise any runtime can\nread without running anyone's code.**\n\nNow the code. A **DRIVER** (AIP-30's `defineDriver`\n\n) bundles one or more\n\nimplementations, each bound to a tool contract by `implementTool`\n\n. The binding is\n\ntype-checked against the contract's schemas.\n\n``` js\n// drivers/docs-meili.ts — one implementation of the contract above\nimport { defineDriver, implementTool } from \"@agentproto/driver\"\nimport { docsSearch } from \"../tools/docs-search/TOOL.js\"\n\nexport default defineDriver({\n  id: \"docs.search.meili\",\n  name: \"Docs search via Meilisearch\",\n  kind: \"http\",\n  implementations: [\n    implementTool(docsSearch, async ({ input }) => {\n      const res = await fetch(`${process.env.MEILI_URL}/indexes/docs/search`, {\n        method: \"POST\",\n        body: JSON.stringify({ q: input.query, limit: input.limit }),\n      })\n      const { hits } = await res.json()\n      return { hits: hits.map((h) => ({ title: h.title, url: h.url })) }\n    }),\n  ],\n  network: { egress: [\"MEILI_URL\"] }, // declared reach, not ambient\n})\n```\n\nThe codebase makes the analogy for you. The `implementTool`\n\ndoc comment calls it\n\n*\"equivalent to Solidity's MyToken is IERC20 pattern\"* — the compiler enforces\n\n`docs.search`\n\nkeeps working.\n\nWhy the split earns its keep.A driver declares its own`network.egress`\n\n,\n\nits auth, its install steps — so the same`docs.search`\n\ncontract can have a\n\nlocal implementation, a hosted one, and a mock for tests, and the resolver\n\npicks one per call. That's \"stable interfaces over swappable implementations,\"\n\nbut foryourtools, inyourrepo, not behind a vendor's API.\n\nTwo files. Now the payoff.\n\nStart the daemon in your repo. It reads your `tools/`\n\nand `drivers/`\n\nand exposes\n\nthem over MCP:\n\n```\nnpm i -g @agentproto/cli\nagentproto install claude-code          # also installs the adapter package\nagentproto serve                        # long-lived daemon, serves the /mcp gateway\n```\n\nNow spawn agents. Each adapter is pointed at the daemon's `/mcp`\n\ngateway as it\n\nstarts, so all of them see the same served tools — including your `docs.search`\n\n:\n\n```\n# a frontier agent…\nagentproto sessions start claude-code --cwd . \\\n  --prompt \"Use docs.search to find our retry-policy page, then summarize it.\"\n\n# …the exact same tool, a different vendor…\nagentproto sessions start codex --cwd . \\\n  --prompt \"Use docs.search to check whether we document the queue timeout.\"\n\n# …and a cheap local model, no MCP config of its own\nagentproto sessions start hermes --cwd . \\\n  --prompt \"Use docs.search for 'deploy rollback' and list the top 3 hits.\"\n```\n\n**One contract, one driver, three vendors — Claude Code, Codex, and a local\nmodel via Hermes all call docs.search with no per-agent wiring.** The daemon is\n\nThis is the answer to the question [the hub piece](https://dev.to/agentiknet/you-can-parallelize-the-typing-you-cant-parallelize-the-trust-2fkd)\n\nleft open — *when you give one agent a new capability, how many of the others get\nit?* Here the answer is \"all of them, for free,\" and that's the difference between\n\nThe same \"one place, every agent\" trick works for tools you *didn't* write. MCP\n\nservers are the industry's one real interop win — but each agent brand configures\n\nthem separately, so a server wired into Claude Code is still invisible to Codex.\n\nagentproto imports an MCP server once into the daemon's curated set, and then\n\nevery session can reach it. The flow is three real tool calls:\n\n```\nmcp_discovered_list      → find MCPs already configured in claude/cursor/etc.\nmcp_import               → snapshot one into the daemon (survives the source\n                           config being deleted later)\nmcp_imported_tool_list   → search-then-call: list the imported server's tools…\nmcp_imported_call        → …and invoke one\n```\n\nThe import captures a *snapshot* at import time, so the tool stays usable even if\n\nyou later remove the original config. **You wire an MCP server up once, in one\ndaemon, and Claude Code, Codex, and your local model all inherit it** — instead of\n\n`.mcp.json`\n\nblock into four different agent configs and keepingThat's the whole interop tax, refunded: author-once for tools you write, import-\n\nonce for tools you borrow.\n\nHere's the honest edge, because that's what makes the rest trust me. You could do\n\nall of this with a bespoke framework. The bet agentproto makes is *not* a\n\nframework — it's a registry of numbered specs, modeled deliberately on ERCs, BIPs,\n\nand PEPs. `TOOL.md`\n\nis AIP-14. `DRIVER.md`\n\nis AIP-30. Skills, operators,\n\nworkflows, policies, sandbox definitions each get a number.\n\nThe reason to prefer numbers over a framework is projection. A contract that's a\n\npublic spec, not a class in someone's SDK, can be adapted to any host:\n\n`toMastraTool(impl)`\n\nfor a Mastra agent, or\n`toAiSdkTool(impl)`\n\nfor the Vercel AI SDK,`TOOL.md`\n\n(AIP-16 declares the IO as JSON Schema, no compiled module required).\n\nAligned-with, not forked-from.A Claude Code skill is already most of an\n\nAIP skill; the specs are meant to standardize the format people converged on,\n\nnot replace it. And they'reours, plural: Apache-2.0, open to amendment by\n\nissue — the entire point of a numbered public registry is that no single vendor\n\nowns the meaning of`docs.search`\n\n.\n\nThe honest caveats, stated plainly: agentproto is **0.5.0-alpha**. The daemon, the\n\nMCP surface, the driver doctype, and MCP import are live and hands-on today; the\n\nin-process Mastra / AI-SDK adapters and the wider ~52-spec family are earlier-stage\n\n— the repo publishes a live-vs-roadmap split precisely so you can check. Betting on\n\na young registry is a real cost. So is re-wiring the same tool by hand forever.\n\nPick your poison with open eyes.\n\nOnce a capability is *files with a contract*, the loop closes in a way no config\n\nformat allows. An agent can **write** a new `TOOL.md`\n\n, bind a driver, or scaffold\n\na skill — and because those are file writes, they're diffs you can gate exactly\n\nlike any other code.\n\nThis is where this piece hands off to [the supervision ladder](https://dev.to/agentiknet/your-agent-says-the-tests-passed-it-didnt-run-them-15j):\n\nstage the agent-authored tool behind a check and a human ack, and your fleet's\n\ncapabilities grow the way your codebase grows — incrementally, reviewed, in git —\n\ninstead of the way config sprawl grows. The daemon even exposes the doctype verbs\n\n(`create_tool`\n\n, `create_driver`\n\n, `list_driver`\n\n, `self_inspect`\n\n) *as MCP tools*, so\n\nan agent authors its own next capability through the same interface it uses to\n\ncall the last one.\n\n**That's the actual endgame of files-with-contracts: not tidier config, but agents\nthat safely extend themselves, under the same review discipline as a human PR.**\n\nYou don't need my daemon to start paying down the tax:\n\nCount your capability re-declarations one more time. Every number above one is a\n\nplace a dialect can drift, an agent that's blind to a tool it should have, and an\n\nafternoon of your life spent being human glue. The pattern is settled; the\n\nplumbing is the only thing left to build — and it's a couple of files, not a\n\nplatform migration.\n\nWe had folders of markdown and called it interoperability. It never was. The fix\n\nisn't another framework that everyone reinvents next quarter — it's a contract\n\nanyone can read and no one owns.\n\nIf I've mis-described how your agent stack handles this, or you've solved the\n\ninterop tax a cleaner way, tell me where — I'll fix the piece.\n\nTen pieces, one argument. Start anywhere; each one cross-links the rest.\n\n| Piece | The one idea | |\n|---|---|---|\n| 1 |\n|\n\n*Written by the maintainer of agentproto (Apache-2.0, source). Same contract as our /compare page — dated facts, named strengths, corrections by issue. Got something wrong? File an issue.*\n\n*Building agentproto in the open — follow @theagentproto and @agentik_ai on X.*", "url": "https://wpnews.pro/news/your-claude-skill-is-invisible-to-codex-here-s-how-to-fix-it", "canonical_source": "https://dev.to/agentiknet/your-claude-skill-is-invisible-to-codex-heres-how-to-fix-it-3l74", "published_at": "2026-07-14 01:36:24+00:00", "updated_at": "2026-07-14 01:57:42.034439+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["Claude Code", "Codex", "Anthropic", "agentproto", "ERC-20"], "alternates": {"html": "https://wpnews.pro/news/your-claude-skill-is-invisible-to-codex-here-s-how-to-fix-it", "markdown": "https://wpnews.pro/news/your-claude-skill-is-invisible-to-codex-here-s-how-to-fix-it.md", "text": "https://wpnews.pro/news/your-claude-skill-is-invisible-to-codex-here-s-how-to-fix-it.txt", "jsonld": "https://wpnews.pro/news/your-claude-skill-is-invisible-to-codex-here-s-how-to-fix-it.jsonld"}}