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

bareclaw

v0.1.1

Published

Bare library exposing picoclaw AI agent via RPC

Downloads

214

Readme


What is this?

bareclaw takes picoclaw (a capable, multi-provider AI agent written in Go) and exposes it as a clean, embeddable Bare module.

The trick: the Go agent is compiled to a small binary, spawned as a subprocess, and driven purely over bare-rpc across stdio using compact-encoding frames. From JavaScript you get a tidy async/streaming API; under the hood it's a Go agent loop.

Sessions and conversation history are persisted into a Hyperbee on the Bare side. The Go process is the stateless engine; the bee is the source of truth. Pass it a Corestore and it does the rest.

┌────────────────────────┐        bare-rpc over stdio         ┌──────────────────────┐
│  Bareclaw (JS / Bare)  │  ─── compact-encoding frames ───▶  │  picoclaw (Go binary)│
│  • Hyperbee state      │  ◀── tool calls / chat stream ───  │  • agent loop        │
│  • tool handlers (JS)  │                                    │  • LLM providers     │
└────────────────────────┘                                    └──────────────────────┘

Install

npm install

Prebuilt Go binaries for darwin/linux/win32 × x64/arm64 ship in prebuilds/ (resolved via the #bareclaw import map). To rebuild them yourself:

make build            # cross-compile all targets into prebuilds/
# or a single host build:
go -C go build -o ../prebuilds/darwin-arm64/bareclaw ./cmd

You'll also need an LLM the agent can reach — e.g. a local Ollama (ollama run llama3.2) or an API key for Anthropic/OpenAI/etc.

Quick start

const Corestore = require('corestore')
const { Bareclaw } = require('bareclaw')

const store = new Corestore('./store')
await store.ready()

// All Go options are passed via `opts`.
const bc = new Bareclaw(store, { provider: 'ollama', model: 'llama3.2' })
await bc.ready()

// Sessions are keyed deterministically from their scope.
const key = await bc.session({ agentId: 'assistant', channel: 'general' })

// chat() yields structured, string-typed chunks.
for await (const chunk of bc.chat(key, 'Say hello in one word.')) {
  if (chunk.type === 'content') process.stdout.write(chunk.content)
  if (chunk.done) break // 'done' (or 'error') is a pure terminator
}

await bc.close() // flushes state to the bee, stops Go cleanly

Run the included demo with bare example.js.

API

new Bareclaw(store, opts = {})

store is a Corestore (the library opens its own Hyperbee on it). Everything Go needs comes through opts:

| option | type | notes | | -------------- | ---------------- | ------------------------------------------------------------------------------ | | provider | string | e.g. ollama, anthropic, openai | | model | string | e.g. llama3.2, claude-... (sets picoclaw model_name + model) | | apiKey | string | for hosted providers | | apiBase | string | custom endpoint | | config | object | string | inline picoclaw config (merged over defaults) — or a path to a config file | | builtinTools | boolean | keep picoclaw's built-in OS tools (default off — see below) |

Tools. By default a bareclaw agent has no built-in tools — its tools come from registerTool. picoclaw's built-in OS tools (file/exec/skills) act on the Go process, not your app, and make small models emit tool-call noise, so they're off unless you pass builtinTools: true.

await bc.session(scope = {})

Returns a deterministic string key for a scope ({ agentId, channel, account, peer }). Same scope → same key. Records the session in the bee so it's listed and survives restarts.

await bc.sessions()

Lists known session keys — read straight from the bee.

bc.chat(sessionId, message, opts = {}) → async iterable

Yields chunks shaped like:

{ type: 'content',  content: '…', done: false }   // streamed / final text
{ type: 'thinking', content: '…', done: false }   // reasoning (when available)
{ type: 'done',  done: true }                      // terminator, no body
{ type: 'error', content: '…', done: true }        // terminator with message

opts.model overrides the model for a single turn. After each turn the session's history is persisted into the bee automatically.

await bc.exportSession(key)Buffer

Opaque blob of a session's history + summary.

await bc.importSession(key, blob)

Restores a session (into both Go and the bee). Round-trips with exportSession.

await bc.registerTool(name, description, schema, handler)

Registers a JavaScript tool the Go agent can call. schema is JSON Schema; handler(input) returns the result. The agent invokes it via an RPC callback:

await bc.registerTool(
  'reverse',
  'Reverse a string',
  { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
  async ({ text }) => ({ result: [...text].reverse().join('') })
)

await bc.close()

Flushes each session's final state to the bee, then shuts the Go process down gracefully (closes its stdin so it reaches EOF and exits).

What's possible

  • Embed a full agent loop in any Bare app — desktop, mobile, P2P — with no Node, no servers, no terminal noise.
  • P2P-native state. Because sessions live in a Corestore/Hyperbee, they replicate, sync, and persist like any other Holepunch data structure.
  • JS-defined tools executed by a Go agent — bridge the agent to anything in your Bare runtime.
  • Bring your own model — local (Ollama) or hosted — selected entirely through opts.

Examples

Runnable P2P demos live in examples/ (each is bare examples/<file>):

| demo | what it shows | | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | swarm-collab.js | two agents discover each other on a Hyperswarm topic and collaborate by relaying turns | | peer-scan-tool.js | a registerTool P2P tool — the agent joins a swarm, counts peers, and leaves | | dht-shared.js | a HyperDHT server as a one-to-many hub: agents post ideas, the merged board fans back to all | | swarm-code-review.js | a multi-agent code-review panel with consensus — 2 agents per lens (to see agreement), a correlator weighs findings over the DHT, verdict written to review.md |

See examples/README.md for details.

Testing

npm test          # brittle-bare test/all.mjs

Session/state tests run without an LLM. Chat and tool tests need a reachable model (the helpers default to ollama + llama3.2).

Known limitations / what's missing

This is an experiment — here's what's rough or unfinished, honestly:

  • Streaming isn't token-by-token (yet). picoclaw's streaming path isn't engaged for the Ollama provider in this RPC setup, so a reply usually arrives as a single content frame rather than incrementally. The thinking chunk type is wired but rarely emitted.
  • Small local models are noisy. Built-in tools are off by default (which removes most tool-call-JSON noise), but tiny models like llama3.2 can still spontaneously emit function-call-shaped JSON or ramble. Use a capable model/provider for sharp, reliable output and real tool use.
  • Go still writes its own session JSONL to disk. The bee is the bare-side source of truth, but picoclaw's internal store also persists to ~/.picoclaw (or the configured dir). Fully routing that through the bee is future work.
  • Live state-change events aren't fired. The CMD_STATE_CHANGED push path exists but Go doesn't emit it yet; persistence happens after each chat turn and on close() instead.
  • Whole-session blobs. Each persist rewrites a session's full blob rather than appending deltas — fine for chats, wasteful for very long histories.
  • No auth/sandboxing of JS tools. Registered tools run with full Bare privileges.

Credits

  • picoclaw — the Go AI agent doing the real work.
  • Bare + bare-rpc + Hyperbee — the Holepunch runtime and primitives.
  • 🤖 Wired together by Claude as an experiment in bridging a Go agent into the Bare world.