App Concept
An Ohtools app is the composition root. It collects tool definitions, groups, plugins, metadata, and adapters, then builds an immutable registry that agents and local commands can inspect.
When to use this: read it before deciding where tool code, service wiring, and adapter startup should live in a new project.
import { Ohtools } from "@bosun-sh/ohtools";
export const app = new Ohtools({ name: "ops-tools" }).tool("status.read", {
description: "Read deployment status.",
run: () => ({ status: "ready" })
});
Composition Root
The app is where reusable pieces become one public surface. Small projects can
define tools inline. Larger projects usually import defineTool, defineGroup,
or plugin contributions from domain modules and compose them at the boundary.
The app is not the place to hide side effects. Side effects belong in handlers or services that handlers call. The registry itself should remain inspectable without touching external systems.
Registry And Runtime
app.build() returns the registry: stable IDs, descriptions, schemas, graph
edges, metadata, and adapter definitions. app.runtime() returns a runtime that
can validate input, run a handler, validate output, and return next steps.
import { Effect } from "effect";
import { app } from "./ohtools";
const registry = app.build();
const result = await Effect.runPromise(app.runtime().run("status.read", {}));
registry.tools.size;
result.output;
Adapter Boundary
Adapters expose the same registry in different environments. In 0.1, the supported adapter surfaces are the Bun-backed CLI and MCP stdio. HTTP, SSE, streamable HTTP, Node, Deno, and browser runtimes are outside the release.
Next, read Tools Concept for handler anatomy or Complex Apps for a larger project layout.