{
  "markdown": "# toolfactory\n\nBuild an agent tool once; ship it as an Agent Skill, an Agent Plugins bundle, a Claude Code,\nCodex or Cursor plugin, an MCP server, a CLI, an npm or PyPI package, an MCP Registry entry, an\nOpenClaw or Hermes native plugin, and a web page, from one operation module and one config file.\n\ntoolfactory is a scaffolder and a keeper-in-sync, not a runtime. It writes each surface in the\nshape that surface's own tooling would have written, proves it with that surface's own validator,\nand records every generated file in a lock so drift fails CI. Delete toolfactory from a repo it\ngenerated and every surface still installs, builds and publishes.\n\n<!-- tf:install -->\n## Install\n\n[![Agent Skill](https://img.shields.io/badge/Agent_Skill-available-5B5BD6)](https://github.com/GoatInAHat/toolfactory)\n\n- **Agent Skill** — `npx skills add GoatInAHat/toolfactory`\n- **MCP server** — `npx -y toolfactory mcp` [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=toolfactory&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22toolfactory%22%2C%22mcp%22%5D%7D) [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=toolfactory&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInRvb2xmYWN0b3J5IiwibWNwIl19)\n- **Claude Desktop extension** — download `toolfactory.mcpb` from the GitHub Release and double-click to install\n- **Claude Code plugin** — `claude plugin marketplace add GoatInAHat/toolfactory`, then `claude plugin install toolfactory@toolfactory`\n- **Codex plugin** — `codex plugin marketplace add GoatInAHat/toolfactory`, then `codex plugin add toolfactory@toolfactory`\n- **Gemini CLI extension** — `gemini extensions install https://github.com/GoatInAHat/toolfactory`\n- **OpenClaw plugin** — `openclaw plugins install --link hosts/openclaw` from a checkout\n- **Hermes plugin** — `hermes plugins install https://github.com/GoatInAHat/toolfactory#hosts/hermes/toolfactory_hermes`\n- **DSH plugin** (experimental) — `dsh plugin --profile <profile> add ./hosts/dsh` from a checkout, or the release tarball `toolfactory-dsh-0.1.2.tgz`\n- **Web app** — `npx -y toolfactory mcp --http --open` serves the operations page beside the\n  MCP endpoint on one port and opens it; over MCP or a skill, the `web` operation does the same and\n  returns the URL.\n- **npm package** — `npm install toolfactory`\n\n<!-- /tf:install -->\n\n## Quickstart\n\n```sh\nmkdir hello && cd hello\nnpx toolfactory init --name hello --binding typescript --surfaces skill,agent-plugins,claude,mcp,cli,npm\n```\n\n`init` writes `plugin.json` (identity), `dev.toolfactory/tool.json` (surfaces, binding, config),\nthe kernel scaffold, the `.agents/` agent-config canon (skills, MCP servers, `sync.py`, `setup`\nand the per-harness hook carriers, so the tool is developable in any harness), and the first\nbuild. It also does what a human would do next: `git init` and a first commit, then\n`bash .agents/setup`, which renders the harness adapters, installs the git hooks that keep them\nin sync, and installs the dependencies. Its `nextSteps` end with the one reload line of the\nharness it is running inside, because reload is the one part a repository cannot automate.\n\nAdd `--repo <owner>/<name>` and it creates that GitHub repository through `gh` and pushes to it —\n**private unless you pass `--public`** — with one topic per selected surface, and prepares the\nlive-tests environment when a `.env` is there. `--dryRun` prints the `gh` invocations instead.\nNone of it is required: with no GitHub, plain git or no git at all, everything below still works.\n\n### Instruction-only Codex plugin\n\nUse `--runtime none --surfaces skill,codex` when a plugin is only SKILL.md instructions for\nCodex. ToolFactory then emits no MCP server, operation snapshot, language scaffold, or consumer\nruntime dependency. `binding` remains required for config compatibility but is unused in this\nmode. This is available in the published npm package starting with ToolFactory 0.1.1.\n\n1. Write operations in `src/ops.ts` (TypeScript) or `src/<pkg>/ops.py` (Python). Each one is a\n   name, a description, an input schema, an optional output schema, an optional `requires`\n   list, and a handler.\n2. `npx toolfactory introspect` spawns the kernel MCP server and snapshots `tools/list` into\n   `dev.toolfactory/ops.json`.\n3. `npx toolfactory build` regenerates every selected surface in-tree.\n4. `npx toolfactory gate` runs what CI runs, here: build, the drift check, every surface's\n   upstream validator, your own checks and tests, and the credential-free host end-to-end.\n5. Commit everything. `npx toolfactory package` builds the release assets into `dist/release/`;\n   CI runs the same gate and, on a `v*` tag, the same package job before publishing.\n\nA TypeScript operation:\n\n```ts\noperation({\n  name: \"echo\",\n  description: \"Echo text back.\",\n  input: z.object({ text: z.string() }),\n  output: z.object({ text: z.string() }),\n  annotations: { readOnlyHint: true },\n  handler: async ({ text }) => ({ text }),\n})\n```\n\n## Commands\n\nEvery command exists as a CLI subcommand and as an MCP tool (`toolfactory mcp`), because\ntoolfactory is built with toolfactory.\n\n| Command | Does |\n|---|---|\n| `init` | new tool: identity file (`keywords` defaults to `[name]`, the Kiro Powers/Agent Plugins activation trigger; `--keywords` overrides), `tool.json`, kernel scaffold, first build, `git init` + first commit, `.agents/setup`; `--repo <owner>/<name>` creates the GitHub repository (private; `--public` opts out) and pushes it |\n| `introspect` | snapshot the kernel's `tools/list` into `ops.json` |\n| `build` | regenerate every selected surface; delete orphans; write the lock |\n| `check` | fail if the operation snapshot or any generated file drifted from the code (the CI gate) |\n| `validate [--surface]` | run each surface's upstream validator |\n| `coverage` | the operation × surface verdict matrix |\n| `gate` | run what CI runs, here: build, drift check, validators, your checks and tests, host e2e — stopping at the first failure |\n| `package` | build every release asset into `dist/release/` (npm tarball, distributions, plugin tarball and bundle zip, web build, coverage) |\n| `adopt` / `unadopt` / `eject` | take a file (or a whole surface) over from toolfactory, or give it back |\n| `doctor` | which upstream CLIs this machine can delegate to |\n| `secrets` | every credential the project needs — its own sensitive config keys and the release registries' tokens — with where to mint each, whether it is present locally and on GitHub, and (`--action check`) whether the registry accepts it; never a value |\n| `bootstrap-repo` | push `.env` to GitHub through `gh` (config keys to the `live-tests` environment, release tokens to the repository), enable Pages, configure npm trusted publishing once the package exists, and print the one-time steps that are left |\n| `unpublish` | retract every registry a surface dropped since the previous tag published to; the release runs it, `--dryRun` shows it |\n\n## Surfaces\n\nSkills first. `init` selects the minimum that already serves every harness — `skill`,\n`agent-plugins`, `mcp`, `cli` and the binding's package registry — because everywhere that\ntakes a plugin also takes a skill plus an MCP server, and a skill is one file with no upstream to\ntrack. Every host-specific plugin below is opt-in: add it only when that host needs what a skill\nand an MCP server cannot give it (a gateway tab, browser capability, a store listing).\n\n| Surface | Emits | Validated by |\n|---|---|---|\n| `skill` | `skills/<name>/SKILL.md` (frontmatter + operations block; body is yours), plus `.agents/skills/<name>`, a symlink to it, so Copilot, Codex, Hermes, DSH and `.agents/sync.py` see the same one skill | `agentskills validate` |\n| `agent-plugins` | root `plugin.json` + `mcp.json` (consumed by OpenClaw, Hermes, Copilot, Cursor, Codex) | Ajv against the 1.0.0 schemas |\n| `claude` | `.claude-plugin/plugin.json` | `claude plugin validate` |\n| `codex` | `.codex-plugin/plugin.json` + `.agents/plugins/marketplace.json` (`codex plugin marketplace add <owner>/<repo>`) | real Codex CLI: marketplace add, plugin add, plugin list |\n| `cursor` | `.cursor-plugin/` manifest | schema-shaped |\n| `gemini` | root `gemini-extension.json` — a Gemini CLI extension installable straight from the repo, reading your `AGENTS.md` and `skills/` | `gemini extensions validate` |\n| `mcp`, `cli` | the kernel MCP server (stdio, or `--http`) and a CLI over your operations; each lists only the operations it can run | MCP Inspector, `--help` |\n| `npm`, `pypi` | package metadata merged into `package.json` / `pyproject.toml` | `npm pack`, `uv build` |\n| `mcp-registry` | `server.json` | `mcp-publisher` |\n| `mcpb` | `hosts/mcpb/manifest.json` and a `.mcpb` release asset packed from the npm tarball — the one-click install Claude Desktop takes | `mcpb validate` |\n| `openclaw-native` | `hosts/openclaw/`, mirroring `openclaw plugins init --type tool` | `openclaw plugins build --check`, `validate`, plugin-inspector |\n| `hermes-native` | `hosts/hermes/`, a manifest v2 plugin | `hermes plugins doctor --ci` |\n| `web` | `web/`, a shadcn/ui (Vite, React, Tailwind) app with a form per operation; your own pages sit beside it in `App.tsx` | `vite build`, Playwright |\n| `browser-extension` | `hosts/browser/`, one WXT extension built for Chromium, Firefox and Safari: the worker calls your kernel over loopback MCP, the popup is the `web` app, and the operations that need a page are yours to write in `entrypoints/` | `wxt build`, `web-ext lint`, Playwright against a real Chromium |\n| `dsh` (experimental) | `hosts/dsh/`, a zero-code DSH (DeepSeek Harness) bundle: one Cordis patch row attaching your MCP server through `@deepseek-ai/dsh-mcp-client` | a keyless `dsh --profile headless` boot |\n| workflows (always) | `ci.yml`, `release.yml` (gate → package → publish legs → GitHub Release, plus Pages), `compose.toolfactory.yaml`, `.env.example`, `renovate.json`; every step is one `toolfactory gate` / `toolfactory package` runs without GitHub | the workflow itself |\n| readme (always) | the Install section of `README.md` (a marked region): one install line per selected surface, plus a static Agent Skill badge | — |\n\n## Driving toolfactory from an agent\n\nEvery command is an MCP tool, so a host can drive the whole loop without a shell — and nothing is\nregistered by hand. Every generated project carries the `.agents/` canon, so `toolfactory` and the\ntool's own kernel are already entries in `.agents/mcp/servers.json`, which `bash .agents/setup`\nrenders into whichever harnesses are on the machine (`.mcp.json`, `.cursor/mcp.json`,\n`.codex/config.toml`, …) and keeps in sync from every one of them. `root` is an argument of every\ntool, so one registration serves every repository on the machine; from inside a host worktree,\npass it explicitly.\n\nReload is the one part a repository cannot automate, so `init` prints the line that matches the\nharness it is running inside, and the generated `AGENTS.md` carries the table it comes from.\nInside OpenClaw, install the tool you are building with\n`openclaw plugins install --link <repo>/hosts/openclaw --force`; inside Hermes, commit and run\n`hermes plugins install file://<repo>#hosts/hermes/<pkg>` — every `hermes` run is a fresh process,\nand `hermes gateway restart` is only for the messaging gateway.\n\nGSD uses the same skills, CLI and MCP server; no GSD-specific surface is needed. From a generated\nproject, run `bash .agents/setup --all` so `.mcp.json` is rendered even on a GSD-only machine,\nthen discover its server in an interactive GSD session before unattended use. GSD launched by\nOpenClaw or Hermes loads the child project's configuration separately from the outer agent.\nSee [GSD compatibility](docs/gsd.md) for setup, runtime boundaries and the repeatable smoke test.\n\n## The boundary\n\nCore logic is a pure function of JSON arguments, environment/config and the filesystem. An\noperation declares what it needs from a closed vocabulary: `net`, `fs`, `shell`, `secret` are\nportable; `browser`, `model`, `user-input`, `channel` are not. Every surface gets a per-operation\nverdict (`native`, `bridged`, `degraded`, `excluded`, with a reason) in `COVERAGE.md`, and an\nexcluded operation is left off that surface's tool list rather than stubbed. A tool that needs a\nbrowser is written as two operations: one that takes the page content as an argument and runs\neverywhere, and one that declares `browser` and runs only where a browser exists.\n\nSee [docs/spec.md](docs/spec.md) for the normative design.\n\n## Repository\n\ntoolfactory's own repo is generated by `toolfactory build` from its `dev.toolfactory/tool.json`.\n`pnpm check`, `pnpm test`, `pnpm toolfactory check` and `pnpm toolfactory validate` are the gates.\n",
  "bytes": 12918,
  "sha": "072c2b61ee4798d98655ed51deaa2a312e89f41e34de8023deadaa62218a6dcf",
  "repo_slug": "goatinahat/toolfactory",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_goatinahat_toolfactory_36386bed/readme"
}