{"slug": "build-a-devtool-once-mount-it-anywhere", "title": "Build a devtool once. Mount it anywhere", "summary": "Devframe released a framework that lets developers define a devtool once with `defineDevframe()` and mount it in any host framework through a single Web Standard `Request → Response` handler created by `initDevframe()`. The package ships adapters for frameworks including Hono and the `cac` CLI library, plus an MCP adapter that exposes opted-in RPC functions, resources, and shared state to AI agents, and the `@devframes/hub` headless composition layer for running multiple devtools through one entry point.", "body_md": "# Build a devtool once. Mount it anywhere.\n\n``` js\nimport { defineDevframe } from 'devframe'\nimport { initDevframe } from 'devframe/initiate'\n\nconst myDevframe = defineDevframe({\n  id: 'my-tool',\n  name: 'My Tool',\n  rpc: [getModules],\n  view: { type: 'spa', distDir: './dist/client' },\n})\n\n// one Request → Response handler, any host framework\nconst { handler } = initDevframe(myDevframe, {\n  base: '/__my-tool/',\n})\n```\n\n// Foundation //\n\n## One definition, every entry point\n\n`defineDevframe()` describes a tool once. `initDevframe()` turns it into a Web Standard `Request → Response` handler, and adapters reshape that same definition into whatever your package ships.\n\n```\nOne Standard Handler\nAdapters as Conveniences\nType-safe RPC & Shared State\nVisual and Agentic\n```\n\n// Portability //\n\n## The same handler, mounted natively\n\nA devframe's boundary is simply the Web Standard `Request` and `Response`. Any framework that speaks that (or connect-style middleware) mounts the same tool and inherits the whole ecosystem. Only the host-framework-facing glue changes. [See all adapters](https://devfra.me/adapters/initiate).\n\n``` js\nimport { Hono } from 'hono'\nimport { devtools } from './devtools'\n\nconst app = new Hono()\n\napp.all(`${devtools.base}*`, c => devtools.handler(c.req.raw))\n```\n\n// Adapters //\n\n## Package it the way your tool ships\n\nThe handler is the smallest common denominator. Higher-level adapters package that same definition into familiar forms; pick the entry points your package needs. [Browse the adapters](https://devfra.me/adapters).\n\n``` python\nimport { createCac } from 'devframe/adapters/cac'\nimport myDevframe from './my-tool'\n\ncreateCac(myDevframe).parse()\n```\n\n// Interfaces //\n\n## One capability, two interfaces\n\nRPC functions stay private by default and opt into agent exposure explicitly. The [MCP adapter](https://devfra.me/adapters/mcp) translates those functions, resources, and selected shared state into an agent-consumable interface: the presentation changes, the source of truth stays the same.\n\n``` js\nimport { defineRpcFunction } from 'devframe'\n\nexport const inspectBuild = defineRpcFunction({\n  name: 'inspect-build',\n  type: 'query',\n  handler: () => readBuildGraph(),\n})\n```\n\n// Hub //\n\n## From one devframe to a devtools hub\n\nWhen several devtools run at once, discovery becomes the problem. `@devframes/hub` is a headless composition layer: many devframes register docks, commands, terminals, and shared state, and appear through one consistent entry. [Learn about the hub](https://devfra.me/guide/hub).\n\n``` js\nimport { initHub } from '@devframes/hub/initiate'\nimport { createTerminalsDevframe } from '@devframes/plugin-terminals'\n\nconst hub = initHub({\n  base: '/__devframes/',\n  devframes: [\n    createTerminalsDevframe(),\n    // ...more devframes\n  ],\n  ui: await import('@devframes/hub-ui').then(m => m.createUi()),\n})\n```\n\n## Ship your devtool everywhere\n\n`DevframeDefinition` and pick the entry points your package ships: hosted, standalone, embedded, or agentic.", "url": "https://wpnews.pro/news/build-a-devtool-once-mount-it-anywhere", "canonical_source": "https://devfra.me", "published_at": "2026-09-23 15:47:20+00:00", "updated_at": "2026-09-23 16:01:07.350000+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "agent-protocols", "ai-tools"], "entities": ["Devframe", "defineDevframe", "initDevframe", "Hono", "cac", "@devframes/hub", "MCP"], "alternates": {"html": "https://wpnews.pro/news/build-a-devtool-once-mount-it-anywhere", "markdown": "https://wpnews.pro/news/build-a-devtool-once-mount-it-anywhere.md", "text": "https://wpnews.pro/news/build-a-devtool-once-mount-it-anywhere.txt", "jsonld": "https://wpnews.pro/news/build-a-devtool-once-mount-it-anywhere.jsonld"}}