npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@onetool/one-tool

v0.1.0

Published

Stateful CLI environment for LLM agents — no sandbox required

Readme

one-tool

Constrained agent workspace that avoids Python and shell sandboxes.

one-tool gives a model exactly one tool:

run(command: string)

Behind that one entrypoint, the runtime provides:

  • shell-like composition with |, &&, ||, and ;
  • a rooted virtual file system
  • adapter-backed retrieval and fetch commands
  • model-friendly output formatting
  • command discovery through help, usage text, and guided errors

It is built for the common agent problem:

You want the power of CLI-style composition without exposing a real shell.

At a glance:

  • one model-facing tool: run(command)
  • 26 built-in commands for files, text, data, memory, and adapters
  • rooted storage through NodeVFS, MemoryVFS, or BrowserVFS
  • structured execution via runDetailed(...)
  • extension helpers for custom commands
  • testing helpers for command and scenario coverage
  • MCP server support for Claude Code and other MCP clients

Try the interactive demo →


Documentation map


Why this library exists

Many agent systems expose a large set of narrow tools:

  • one tool for file reads
  • one tool for file writes
  • one tool for search
  • one tool for HTTP
  • one tool for JSON inspection
  • one tool for memory

That often creates three problems:

  1. The model has to discover and plan across too many tool boundaries.
  2. Multi-step work becomes verbose and brittle.
  3. CLI-style reasoning patterns get lost.

one-tool takes the opposite approach:

  • expose one tool
  • make it feel like a small CLI
  • keep execution safe and rooted
  • make outputs compact, navigable, and recoverable

The result is a model-facing interface that is simpler, but still expressive.

It is a practical alternative to code-interpreter style sandboxes when you need:

  • lower infrastructure cost
  • a smaller execution surface
  • easier multi-tenant control
  • browser or middleware deployment without arbitrary code execution

When this fits

Use one-tool when:

  • you want one stable tool surface instead of many narrow tools
  • your agent needs to compose file, text, JSON, memory, and retrieval work in one step
  • you want a safer rooted workspace instead of a real shell
  • you need deterministic command behavior that is easy to test
  • you want a browser-, middleware-, or server-friendly alternative to code-interpreter or shell sandboxes

Look elsewhere when:

  • you need arbitrary process execution
  • you need full shell compatibility, redirection, or job control
  • you need a streaming terminal or interactive TTY applications

Quick start

Requirements

  • Node >= 20.11
  • npm

Run the repo locally

npm install
npm run build
npm run demo

npm run demo runs the smallest self-contained example: examples/01-hello-world.ts.

For the rest of the walkthrough, open examples/README.md.

Start with:

npm run build
npm run demo
npm run example:custom-command
npm run example:readonly-agent

Then continue with:

  • npm run example:detailed-execution for traces and structured output
  • npm run example:adapters for search and fetch
  • npm run example:mcp-server for Claude Code / MCP integration

For the provider-backed agent example or live integration tests:

cp .env.example .env

Then fill in the Groq, OpenAI, or Anthropic section described in docs/providers.md.

For the example walkthrough, see examples/README.md.


Five-minute integration

Minimal Node example

import {
  buildToolDefinition,
  createAgentCLI,
  NodeVFS,
  SimpleMemory,
  type FetchAdapter,
  type FetchResponse,
  type SearchAdapter,
  type SearchHit,
} from 'one-tool';

class MySearch implements SearchAdapter {
  async search(query: string, limit = 10): Promise<SearchHit[]> {
    const rows = await mySearchBackend.search(query, { limit });
    return rows.map((row) => ({
      title: row.title,
      snippet: row.snippet,
      source: row.url,
    }));
  }
}

class MyFetch implements FetchAdapter {
  async fetch(resource: string): Promise<FetchResponse> {
    const payload = await myApi.lookup(resource);
    return {
      contentType: 'application/json',
      payload,
    };
  }
}

const runtime = await createAgentCLI({
  vfs: new NodeVFS('./agent_state'),
  adapters: {
    search: new MySearch(),
    fetch: new MyFetch(),
  },
  memory: new SimpleMemory(),
});

export async function run(command: string): Promise<string> {
  return runtime.run(command);
}

const tool = buildToolDefinition(runtime);

mySearchBackend and myApi are placeholders for your own services. The runtime surface stays the same whether those are local libraries, HTTP clients, databases, or SDK calls.

Example result

For:

cat /logs/app.log | grep -c ERROR

The model sees something like:

3

[exit:0 | 2ms]

For a missing file:

[error] cat: file not found: /notes/missing.txt. Use: ls /notes

[exit:1 | 0ms]

For complete API details, see docs/api.md.

Why this shape works well for agents

| Approach | What you get | Main tradeoff | | ---------------- | -------------------------------------------- | -------------------------------------------- | | Code interpreter | arbitrary code execution | expensive, harder to secure, harder to scale | | Real shell | familiar process-level power | large risk surface and inconsistent outputs | | one-tool | constrained, composable workspace for agents | intentionally narrower than Python or shell |

The trade is deliberate: less raw power than arbitrary code execution, but much tighter control and a much simpler operating model.


Common questions

Why one tool instead of many?

Because the model usually reasons better over one composable tool than a large menu of narrow tools.

  • one run(command) tool means one schema to understand
  • command discovery happens inside the runtime through help, usage text, and errors
  • compositions like cat /logs/app.log | grep ERROR | head -n 5 stay in one tool call instead of three
  • fewer round trips usually means less brittle planning and less context churn

How do I choose which commands to enable?

Start with presets:

  • full
  • readOnly
  • filesystem
  • textOnly
  • dataOnly

Then refine with explicit includes, excludes, or a custom registry.

Examples and full registry options are documented in docs/api.md#command-registry.

Which VFS should I use?

| Scenario | Backend | Why | | ---------------------- | ------------ | ---------------------------------------- | | Server-side agent | NodeVFS | Persists to disk and survives restarts | | Unit tests | MemoryVFS | Fast, deterministic, no cleanup required | | Browser agent | BrowserVFS | IndexedDB-backed persistence | | Ephemeral/stateless | MemoryVFS | No persistence overhead | | Long-lived local agent | NodeVFS | Workspace survives process restarts |

Full backend details: docs/vfs.md

Can I add custom commands?

Yes.

How do I inspect execution programmatically?

Use runtime.runDetailed(commandLine).

It returns:

  • raw stdout bytes
  • structured stderr and exit code
  • per-command trace data for pipelines and chained commands
  • presentation metadata for truncation and binary-guard cases

Reference: docs/api.md#structured-execution

Where should I start with the examples?

  • start with examples/README.md
  • read the numbered examples in order
  • use examples/advanced/ when you need a narrower pattern after the basics

Does this work with my model provider?

The runtime itself is provider-agnostic.

  • OpenAI: covered by maintained example and live-test entrypoint
  • Groq: covered by maintained example and live-test entrypoint
  • Anthropic: covered by maintained example and live-test entrypoint through Anthropic's OpenAI-compatible endpoint
  • other OpenAI-compatible providers: often usable if they support tool calling, but not covered by maintained examples or tests in this repo

Provider details: docs/providers.md


How it works

Execution semantics:

  • stdout bytes flow through pipes
  • stderr does not flow through pipes
  • a pipeline stops on the first failed stage
  • &&, ||, and ; control whether the next pipeline runs
  • relative paths resolve under /
  • there is no process environment, cwd mutation, or shell state

Operationally, think of the runtime as:

  1. one parser for CLI-style commands
  2. one registry of allowed commands
  3. one rooted workspace
  4. optional retrieval adapters and memory
  5. one formatter that turns results into model-friendly text or structured execution data

The runtime intentionally makes discovery cheap:

  • help lists commands
  • help <command> gives details and examples
  • calling a command with the wrong shape returns guided usage
  • large output becomes navigable output, not useless output

Command language

Supported operators:

| Operator | Meaning | | ------------------- | -------------------------------------------------------- | | <code>\|</code> | pipe stdout to the next command | | && | run the next pipeline only if the previous one succeeded | | <code>\|\|</code> | run the next pipeline only if the previous one failed | | ; | always run the next pipeline |

The parser also supports:

  • single quotes
  • double quotes
  • backslash escaping

This is intentionally not a real shell. It does not implement:

  • environment expansion
  • globbing
  • command substitution
  • redirection
  • backgrounding

All paths are rooted under /. Relative paths also resolve under /.

Full syntax, unsupported constructs, and examples: docs/command-reference.md#command-language


Built-in command groups

The runtime ships with 26 built-in commands.

| Group | Commands | Reference | | ---------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | | System | help, memory | docs/command-reference.md#system-commands | | Filesystem | ls, stat, cat, write, append, mkdir, cp, diff, mv, rm, find | docs/command-reference.md#filesystem-commands | | Text | grep, head, tail, sort, sed, tr, uniq, wc | docs/command-reference.md#text-commands | | Data | json, calc | docs/command-reference.md#data-commands | | Adapters | search, fetch | docs/command-reference.md#adapter-backed-commands |

Example workflows:

cat /logs/app.log | grep ERROR | tail -n 20
find /config --type file --name "*.json" | sort
sed -n "1,20p" /logs/app.log
diff -u /drafts/qbr.md /reports/qbr.md
search "Acme renewal risk" | head -n 5 | write /notes/acme-risk.txt
fetch order:123 | json get customer.email

Full command tables, examples, and workflows: docs/command-reference.md


Public API

Primary entrypoints:

| Surface | Purpose | Reference | | ------------------------------------------------ | ---------------------------------------------------- | ------------------------------------------------------------------------------ | | createAgentCLI(...) | create a runtime | docs/api.md#core-runtime | | runtime.runDetailed(...) | inspect structured execution results and traces | docs/api.md#structured-execution | | buildToolDefinition(...) | expose an OpenAI-compatible tool definition | docs/api.md#tool-definition | | one-tool/mcp | expose the runtime as an MCP stdio tool server | docs/api.md#mcp-server-surface | | CommandRegistry / createCommandRegistry(...) | select, override, and compose commands | docs/api.md#command-registry | | one-tool/extensions | author custom commands with stable helper utilities | docs/api.md#public-extension-helpers | | one-tool/testing | test custom commands and deterministic scenario runs | docs/api.md#command-testing-helpers | | package subpaths | import focused surfaces like one-tool/vfs/browser | docs/api.md#package-exports |

Most integrations only need:

  • runtime.run(commandLine)
  • buildToolDefinition(runtime)

When you need observability, test assertions, or per-step telemetry, use runtime.runDetailed(commandLine) instead of parsing the formatted string from run(...).

Full API reference: docs/api.md


VFS backends

All backends implement the same VFS interface.

| Backend | Best for | Persistence | Notes | | ------------ | ------------------------------ | ----------------------------------- | ------------------------------------------------------------------------ | | NodeVFS | server/runtime agents | host filesystem under a chosen root | rooted host storage; hides symlink entries and rejects symlink traversal | | MemoryVFS | tests, demos, ephemeral agents | none | fast and deterministic | | BrowserVFS | browser agents | IndexedDB | persistent client-side filesystem |

Full interface, backend behavior, and workspace model: docs/vfs.md


Provider-backed agent example

This repo includes a maintained provider-backed example agent in examples/08-llm-agent.ts.

npm run agent

Live integration tests are opt-in:

npm run test:live
npm run test:live:groq
npm run test:live:openai
npm run test:live:anthropic

Environment setup, provider selection, and compatibility notes: docs/providers.md

If you want the smallest maintained end-to-end path:

  • npm run agent for a provider-backed agent loop
  • npm run example:mcp-server for MCP / Claude Code integration
  • npm run example:custom-command for extending the runtime

Security model

The runtime is intentionally safer than exposing a real shell, but it is not a complete sandbox.

What it does:

  • roots all file paths under /
  • blocks path escape through normalization
  • rejects symlink traversal inside NodeVFS
  • rejects shell features such as redirection, subshells, backticks, and environment expansion
  • never spawns host processes
  • routes network access through explicit developer-supplied adapters

What still matters:

  • NodeVFS touches a real host directory under the root you choose
  • storage policies and output truncation do not by themselves cap how much command input may be materialized; use executionPolicy.maxMaterializedBytes when you need that bound
  • fetch and search can reach real systems if your adapters do
  • custom commands can do anything your code does

For production use, treat adapters and custom commands as your trust boundary.


Adding commands

Built-in commands in this repo use metadata-driven conformance coverage, and the same conformance helper is exposed for downstream consumers.

For command authoring:

Register custom commands before calling buildToolDefinition(runtime) if the model should see them in the generated tool description.


Testing

Main entrypoints:

npm test
npm run demo
npm run example:custom-command
npm run agent

npm test includes both deterministic contract tests and deterministic end-to-end scenario tests.

Live provider tests:

npm run test:live
npm run test:live:groq
npm run test:live:openai

Testing helpers and conformance utilities are documented in docs/api.md#command-testing-helpers. Command authoring patterns live in COMMANDS.md.


Project layout

one-tool/
├─ README.md
├─ COMMANDS.md
├─ docs/
│  ├─ api.md
│  ├─ command-reference.md
│  ├─ providers.md
│  ├─ vfs.md
│  └─ diagrams/
├─ examples/
├─ src/
└─ test/

Known limitations

  • run(...) returns a complete formatted string, not a streaming result
  • output formatting is fixed even though the overflow thresholds are configurable
  • built-in adapters are limited to search and fetch; other integrations should be custom commands
  • the library does not manage your outer agent loop, retries, token budgets, or provider cost tracking
  • access control is at command granularity; if you need subcommand-level policy, expose a narrower command

Non-goals

  • full shell compatibility
  • arbitrary process spawning
  • shell redirection semantics
  • globbing and environment expansion
  • hidden mutable runtime state like a working directory