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

moaca-ai

v0.0.1

Published

Moaca is a wrapping coding agent, making different agent harnesses accessible through a single unified API, session format, and SDK interface. It is _not_ an orchestrator in the sense of managing multi-agent workflows in sandboxes and sits a layer below o

Readme

M.O.A.C.A. – Mother Of All Coding Agents

Moaca is a wrapping coding agent, making different agent harnesses accessible through a single unified API, session format, and SDK interface. It is not an orchestrator in the sense of managing multi-agent workflows in sandboxes and sits a layer below orchestrators like Fabrik.

[!WARNING] This project is currently in private alpha and not available for public use yet (which is why its currently only re-exporting a private package). The full implementation and source will be available here soon. If you're interested in early access or contributing, please reach out!

Table of Contents


Overview

Modern AI coding agents all store session history differently. GRIPS unifies them under one schema and one API:

  • One schema for nodes (messages, tool calls, compactions, checkpoints, config changes, and custom events)
  • One tree model for branching, forking, and navigating session history
  • One streaming format for real-time output (text, reasoning, tool calls, tool execution stdout/stderr)
  • One SDK to list, read, create, fork, send messages to, and listen to sessions across every supported harness
  • One CLI to inspect and manage sessions from the terminal
  • One React library to render session trees, tables, paths, and streaming UIs

Packages

Package Dependency Graph

cli ──> sdk ──> harness ──> format
                 react ───> format

| Package | Purpose | Tech | |---------|---------|------| | @grips/format | Pure types and schemas — zero I/O | Effect-TS Schema | | @grips/harness | Per-agent adapters (Pi, OpenCode, Claude Code, Codex, Cursor) | Effect-TS | | @grips/sdk | Unified consumer API via Effect Layer and Service | Effect-TS | | @grips/cli | Terminal interface and TUI | Effect-TS + citty | | @grips/react | React components and hooks for rendering sessions | React + Tailwind | | website | Marketing and documentation site | Vite + React |


@grips/format

Pure types and schemas. No I/O, no Effect runtime.

Defines the canonical data model used by every other package.

Core types:

  • Node — Discriminated union of all node types:
    • message — User / assistant / system messages with usage metadata
    • tool_execution — Tool call with arguments, output, and exit code
    • compaction — Session compaction / summarization event
    • branch_summary — Summary of a branched conversation path
    • checkpoint — Code snapshot checkpoint
    • config_change — Agent configuration change
    • custom — Extensible custom event type
  • Session — Session metadata (id, title, cwd, source harness, timestamps)
  • SessionListItem — Lightweight session list entry
  • Tree — Built from an array of nodes; provides getPath, getChildren, findLeaves, validate
  • StreamEvent — Real-time streaming events (text.start, text, tool_call.delta, tool_execution.stdout, done, error, etc.)

Validation:

import { buildTree } from "@grips/format";

const tree = buildTree(nodes);
const result = tree.validate(); // { valid, brokenReferences, orphanedNodes, cycles }

@grips/harness

Per-harness adapters that bridge native agent storage and runtime APIs into the GRIPS format.

Each supported agent has two implementations:

  • SessionSDK — Read/write session storage (list, get, create, append, delete, fork)
  • RuntimeSDK — Drive a live agent (send, listen, stop)

Supported harnesses:

| Harness | SessionSDK | RuntimeSDK | |---------|------------|------------| | Pi (pi) | PiSessionSDK | PiRuntimeSDK | | OpenCode (opencode) | OpenCodeSessionSDK | OpenCodeRuntimeSDK | | Claude Code (claude-code) | ClaudeCodeSessionSDK | ClaudeCodeRuntimeSDK | | Codex (codex) | CodexSessionSDK | CodexRuntimeSDK | | Cursor (cursor) | CursorSessionSDK | CursorRuntimeSDK |

ACP Harness base class:

Agents that expose a JSON-RPC stdio interface can subclass AcpHarness in runtime-sdk/acp.ts to inherit standardized process handling.

Error types:

  • SessionSDKError / RuntimeSDKError — Tagged errors from adapter operations
  • AdapterError — Harness not found or misconfigured

@grips/sdk

Unified consumer API. All harnesses, one interface.

The GripsClient is an Effect Service that aggregates every registered harness and routes calls to the right adapter automatically.

Registry services:

  • SessionSDKRegistry — Holds SessionSDK instances
  • RuntimeSDKRegistry — Holds RuntimeSDK instances

Client API:

import { GripsClient } from "@grips/sdk";

// List sessions across all harnesses
yield* GripsClient.list({ cwd: "/project", harness: "opencode", limit: 10 });

// Get a session and its tree
const { session, tree } = yield* GripsClient.get("opencode:session-123");

// Create a new session
yield* GripsClient.create({ harness: "claude-code", title: "Fix login bug" });

// Send a message and receive a stream of events
const stream = yield* GripsClient.send("pi:session-456", { content: "Refactor auth.ts" });

// Listen to an already-running session
const liveStream = yield* GripsClient.listen("codex:session-789");

// Fork a session from a specific node
yield* GripsClient.fork("cursor:session-abc", "node-xyz", { title: "Exploration branch" });

// Stop a running session
yield* GripsClient.stop("opencode:session-123");

Session IDs are namespaced: {harness}:{nativeId}. The client parses the harness prefix and routes to the correct adapter.


@grips/cli

Terminal interface and interactive TUI for managing sessions.

Commands:

# Interactive TUI (default when no args provided)
grips

# List sessions
grips sessions list [--cwd DIR] [--harness NAME] [--json]

# Show a session
grips sessions get <id> [--json | --tree | --nodes] [--thinking]

# Create a session
grips sessions create [--harness NAME] [--cwd DIR] [--title TITLE] [--json]

# Delete a session
grips sessions delete <id>

# Fork a session from a node
grips sessions fork <id> <nodeId> [--title TITLE] [--json]

# Send a message to a running session
grips send <id> --content "MESSAGE"

# Listen to a running session
grips listen <id>

# Stop a running session
grips stop <id>

Auto-detection: The CLI automatically detects installed agents by checking for their executables (opencode, claude, codex, cursor-agent) or home-directory markers (~/.pi) and wires only the available harnesses into the Effect dependency layer.


@grips/react

React components, hooks, and headless primitives for rendering GRIPS sessions.

Exports:

  • / — Components + hooks + mock data
  • /components — Styled UI components
  • /headless — Unstyled, stateful primitives
  • /hooks — Reusable state and stream logic

Components:

| Component | Description | |-----------|-------------| | SessionTree | Static hierarchical tree of nodes with type legend | | InteractiveSessionTree | Expandable / collapsible interactive tree | | SessionTable | Tabular session list with sorting and filtering | | SessionHeader | Session metadata header (title, harness, timestamps) | | SessionPath | Breadcrumb path from root to selected node | | NodeDetail | Detail view for any node type with type-specific rendering | | SessionView | Composite view combining tree, path, and detail |

Hooks:

| Hook | Purpose | |------|---------| | useTree | Tree state (expand/collapse, select, paths, visibility) | | useStreamEvents | Collect stream events into state | | useStreamContent | Accumulate streaming text / reasoning content | | useStreamingNodes | Merge committed nodes with live draft nodes from a stream | | useSelection | Single / multi selection state | | usePath | Compute ancestor path for a node ID |

Headless primitives:

| Primitive | Purpose | |-----------|---------| | Tree | Render-agnostic tree component (pass your own node renderer) | | SessionList | Render-agnostic list component |

Peer dependencies: react >=19, react-dom >=19, tailwindcss >=4


website

Vite + React marketing and documentation site.

Uses TanStack Router and Tailwind CSS. Built with vite build and previewed with vite preview.


Installation

This repository uses Bun workspaces.

# Install dependencies
bun install

# Type-check all packages
bun run typecheck

# Run tests
bun test

Using packages in your own project

# Install the SDK
bun add @grips/sdk

# Install React components
bun add @grips/react

Quick Start

CLI

# Start the interactive TUI
cd /your/project && grips

# List all sessions across all agents
grips sessions list

# View a session transcript
grips sessions get opencode:abc123

# View the branching tree
grips sessions get opencode:abc123 --tree

# Create a session
grips sessions create --harness claude-code --title "Bugfix"

# Send a message
grips send claude-code:xyz789 --content "Fix the race condition in queue.ts"

SDK

import { Effect } from "effect";
import { GripsClient, SessionSDKRegistry, RuntimeSDKRegistry } from "@grips/sdk";
import { OpenCodeSessionSDK, OpenCodeRuntimeSDK } from "@grips/sdk";

const layer = Layer.mergeAll(
  Layer.succeed(SessionSDKRegistry, { sdks: [new OpenCodeSessionSDK()] }),
  Layer.succeed(RuntimeSDKRegistry, { sdks: [new OpenCodeRuntimeSDK()] })
).pipe(Layer.provide(GripsClient.Default));

const program = Effect.gen(function* () {
  const sessions = yield* GripsClient.list({ limit: 5 });
  const { session, tree } = yield* GripsClient.get(sessions[0].id);
  const stream = yield* GripsClient.send(session.id, { content: "Hello" });

  yield* Stream.runForEach(stream, (event) =>
    Effect.sync(() => console.log(event.type))
  );
});

Effect.runPromise(Effect.provide(program, layer));

React Components

import { SessionTree, SessionView, useStreamingNodes } from "@grips/react";
import { mockNodes } from "@grips/react/data/mock";

// Static tree
<SessionTree nodes={mockNodes} />

// Full interactive view with streaming
function MyApp({ nodes, streamEvents }) {
  const { nodes: liveNodes, draftNodeIds } = useStreamingNodes(nodes, streamEvents);
  return <SessionView nodes={liveNodes} autoExpandIds={draftNodeIds} />;
}

Architecture

The Streaming Draft Node Lifecycle

When driving a running agent through RuntimeSDK, the event stream merges live output into the tree:

  1. Stream IntakeuseStreamingNodes merges committed nodes with incoming StreamEvents.
  2. Draft Node Initialization — When an active event starts (e.g., text.start), a transient "draft node" is created with _draft: true.
  3. Delta Merging — Incremental events continuously merge into the draft node's payload.
  4. Live Auto-Expansion — Draft node IDs are returned as draftNodeIds and mapped to autoExpandIds in the Tree component, keeping the active streaming turn visible.
  5. Commitment — On completion events (text.done, tool_execution.end, done), the draft node closes. If the runtime appends it to storage, it becomes a permanent committed node.

Node Format

Every node shares a common shape:

interface Node {
  id: string;
  parentId: string | null;
  timestamp: number;
  type: "message" | "tool_execution" | "compaction" | "branch_summary" | "checkpoint" | "config_change" | "custom";
  version?: number;
  payload: /* type-specific */;
  metadata: Record<string, unknown>;
}

The parentId enables a full directed acyclic graph of session history, supporting branching, forking, and non-linear exploration.


Development

Scripts

| Script | Description | |--------|-------------| | bun run dev | Start dev servers (Turbo) | | bun run typecheck | TypeScript check all packages | | bun test | Run all tests | | bun run fmt | Format with oxfmt | | bun run lint | Lint with oxlint | | bun run grips | Run the CLI locally |

Testing Conventions

  • Colocation required — Test files (*.test.ts, *.test.tsx) and Storybook stories (*.stories.tsx) must live in the same directory as the source file they cover. No __tests__/ or stories/ directories.
  • Unit tests: vitest run in packages/react/ and packages/website/; bun test elsewhere.
  • Storybook play() tests are real tests and must pass.

Adding a New Harness Adapter

See AGENTS.md for the full workflow. The short version:

  1. Implement SessionSDK in packages/harness/src/session-sdk/my-agent.ts
  2. Implement RuntimeSDK in packages/harness/src/runtime-sdk/my-agent.ts (or subclass AcpHarness)
  3. Export both from packages/harness/src/index.ts
  4. Register in packages/sdk/src/registry.ts
  5. Add auto-detection in packages/cli/src/layer.ts
  6. Add colocated tests

Adding a New Node Type

See AGENTS.md for the full workflow. The short version:

  1. Define the payload schema in packages/format/src/node.ts
  2. Add streaming events to packages/format/src/stream.ts if applicable
  3. Add colors, background, and symbol in packages/react/src/lib/node-rendering.tsx
  4. Create a detail component in packages/react/src/components/NodeDetail/details/
  5. Wire it into NodeDetail.tsx
  6. Add tests and stories

Contributing

  1. Follow the existing code style (oxfmt, oxlint).
  2. Keep tests and stories colocated with source files.
  3. Ensure all tests pass before submitting changes.
  4. Make minimal changes — prefer small, focused PRs.

License

MIT