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

@lakitu/sdk

v0.1.62

Published

Self-hosted AI agent framework for Convex + E2B with code execution

Readme

@lakitu/sdk

Self-hosted AI agent runtime for Convex + E2B

Lakitu is a framework for AI agents that execute code instead of making tool calls. The agent writes TypeScript, imports capabilities from KSA modules, and runs in an isolated E2B sandbox with its own filesystem, terminal, and database.

npx @lakitu/sdk init

Table of Contents


Why Lakitu?

The core problem: AI coding agents forget their plan halfway through complex tasks, corrupt the host environment, and hallucinate progress they haven't made.

Lakitu's solution: Give the agent an isolated computer (E2B sandbox), structured capabilities (KSA files), persistent memory (Beads task graph), and verifiable state (Convex database).

| Component | What it solves | |-----------|----------------| | E2B Sandbox | Agent gets its own VM—can't break your machine. Boots in 150ms. | | KSA Files | Agent capabilities defined in code, not buried in prompts. Testable, version-controlled. | | Beads | Git-backed task graph. Agent always knows what's done, what's blocked, what's next. | | Convex | Real-time database in the sandbox. Agent can verify actual state, not just claim progress. |

Code Execution vs Tool Calls

Most agent frameworks use JSON tool calls:

{ "tool": "readFile", "args": { "path": "app.ts" } }

Lakitu agents write code:

import { file, shell } from './ksa';

const code = await file.read('app.ts');
await file.write('app.ts', fixedCode);
const result = await shell.exec('bun test');

Why this is better:

  • No tool schemas sent every request (saves 40-60% tokens)
  • Natural composition—chain operations like normal code
  • See exactly what ran, not just "tool was called"
  • Works with any LLM that generates code

Quick Start

1. Initialize

npx @lakitu/sdk init

Creates convex/lakitu/config.ts and an example KSA.

2. Build sandbox template

npx @lakitu/sdk build

Pre-deploys Convex functions into an E2B template. Sandboxes boot instantly with everything ready.

3. Configure Convex

// convex/convex.config.ts
import { defineApp } from "convex/server";
import lakitu from "@lakitu/sdk/convex.config";

const app = defineApp();
app.use(lakitu);

export default app;

Import Reference

Lakitu provides clean, tree-shakeable imports:

// Main entry - everything in one import
import { 
  defineKSA, fn, service, primitive,  // KSA builders
  callGateway, fireAndForget,          // Cloud gateway
  localDb, getSessionId,               // Local database
  THREAD_ID, CARD_ID, WORKSPACE_ID,    // Context identifiers
} from '@lakitu/sdk';

// Tree-shakeable imports for smaller bundles
import { callGateway, THREAD_ID } from '@lakitu/sdk/gateway';
import { localDb, getSessionId } from '@lakitu/sdk/db';
import { defineKSA, fn, service } from '@lakitu/sdk/builders';
import { file, shell, browser } from '@lakitu/sdk/primitives';

Export Summary

| Export | Description | |--------|-------------| | @lakitu/sdk | Everything - builders, gateway, db, primitives | | @lakitu/sdk/gateway | Cloud Convex access (callGateway, fireAndForget) | | @lakitu/sdk/db | Local sandbox Convex (localDb) | | @lakitu/sdk/builders | KSA definition (defineKSA, fn, service) | | @lakitu/sdk/primitives | Sandbox operations (file, shell, browser) | | @lakitu/sdk/types | TypeScript types only | | @lakitu/sdk/loro | CRDT utilities (LoroFS, LoroBeads) | | @lakitu/sdk/convex.config | Convex component config |


Configuration

Lakitu Configuration

// convex/lakitu/config.ts
import { Lakitu } from "@lakitu/sdk";

export default Lakitu.configure({
  // E2B template name (default: "lakitu")
  template: "lakitu",
  
  // Model presets: "fast", "balanced", "capable", "vision"
  model: "balanced",
  
  // Or specify model directly
  // model: "anthropic/claude-sonnet-4",
  
  // KSAs to enable
  ksas: ["file", "shell", "browser", "beads", "web"],
  
  // Gateway configuration
  gateway: {
    // Additional allowed paths beyond defaults
    allowedPaths: [
      "features.myFeature.internal.*",
      "services.MyService.action",
    ],
  },
});

Environment Variables

| Variable | Description | Required | |----------|-------------|----------| | E2B_API_KEY | E2B API key | Yes | | CONVEX_DEPLOYMENT | Convex deployment URL | Yes | | SANDBOX_JWT_SECRET | JWT secret for sandbox auth | Yes | | OPENROUTER_API_KEY | OpenRouter API key for LLM | Yes |


Defining KSAs

KSAs (Knowledge, Skills, Abilities) are capability modules. Define what the agent can do in TypeScript:

import { defineKSA, fn, service, primitive } from "@lakitu/sdk";

export const dbKSA = defineKSA("database")
  .description("Database operations")
  .category("skills")
  
  .fn("migrate", fn()
    .description("Run database migration")
    .param("version", { type: "string", required: true })
    .impl(service("services.Database.internal.migrate"))
  )
  
  .fn("backup", fn()
    .description("Create database backup")
    .impl(primitive("shell.exec"))
  )
  
  .build();

Implementation Types

Service — calls your Convex backend:

.impl(service("services.MyApi.internal.doThing"))

Primitive — local sandbox operation:

.impl(primitive("file.read"))
.impl(primitive("shell.exec"))
.impl(primitive("browser.screenshot"))

Writing Project KSAs

Project KSAs live in convex/lakitu/ksa/ and use the gateway to call your Convex backend:

// convex/lakitu/ksa/myFeature.ts
import { callGateway } from "@lakitu/sdk/gateway";

export interface Item { id: string; name: string; }

/** List all items */
export const list = () => 
  callGateway<Item[]>("features.myFeature.list", {});

/** Get item by ID */
export const get = (id: string) => 
  callGateway<Item>("features.myFeature.get", { id });

/** Create new item */
export const create = (name: string) => 
  callGateway<{ id: string }>("internal.features.myFeature.create", { name }, "mutation");

Built-in KSAs

| KSA | What it does | |-----|--------------| | file | Filesystem operations | | shell | Terminal commands | | browser | Web automation via Playwright | | beads | Task tracking (bd ready, bd close, etc.) | | web | Search and scrape | | pdf | Generate PDFs from markdown | | email | Send emails |

Built-in Primitives

| Category | Functions | |----------|-----------| | file | read, write, edit, glob, grep, ls, exists, stat | | shell | exec | | browser | open, screenshot, click, type, getHtml, getText, close |


Gateway API

The gateway enables sandbox code to call your cloud Convex backend securely.

callGateway

import { callGateway } from "@lakitu/sdk/gateway";

// Basic usage
const data = await callGateway("features.users.list", { limit: 10 });

// With type annotation
const user = await callGateway<User>("features.users.get", { id: "123" });

// Specify operation type (query/mutation/action)
const result = await callGateway(
  "internal.features.users.create",
  { name: "John" },
  "mutation"
);

callGatewayBatch

Execute multiple calls in a single HTTP request:

import { callGatewayBatch } from "@lakitu/sdk/gateway";

const [users, posts] = await callGatewayBatch([
  { path: "features.users.list", args: { limit: 10 } },
  { path: "features.posts.recent", args: {} },
]);

if (users.ok) console.log(users.data);

fireAndForget

Non-blocking calls for logging/analytics:

import { fireAndForget } from "@lakitu/sdk/gateway";

// Won't block execution
fireAndForget("services.Analytics.track", { event: "page_view" });

Local Database

The sandbox has its own Convex instance for fast local operations.

import { localDb, getSessionId } from "@lakitu/sdk/db";

// Query
const files = await localDb.query("state/files.getByPath", { path: "/workspace" });

// Mutation
const id = await localDb.mutate("planning/beads.create", { title: "Task" });

// Fire-and-forget (non-blocking)
localDb.fire("state/files.trackAccess", { path: "/workspace" });

// Get session context
const sessionId = getSessionId();

Template Customization

Customize the sandbox environment with a template config:

// convex/lakitu/template.config.ts
import { defineTemplate } from "@lakitu/sdk/template";

export default defineTemplate({
  packages: {
    apt: ["ffmpeg", "imagemagick", "poppler-utils"],
    pip: ["pandas", "numpy", "pillow"],
    npm: ["sharp", "canvas"],
  },
  services: ["redis"],
  setup: [
    "pip install -r requirements.txt",
  ],
});

Build with custom packages:

npx @lakitu/sdk build --custom

CLI Commands

npx @lakitu/sdk init              # Setup in Convex project
npx @lakitu/sdk init --dir ./convex  # Custom directory
npx @lakitu/sdk build             # Build E2B template
npx @lakitu/sdk build --base      # Base template only
npx @lakitu/sdk build --custom    # Custom template only  
npx @lakitu/sdk publish           # Template management

How It Works

  1. Agent receives task → loads relevant KSAs
  2. Queries Beadsbd ready returns unblocked work
  3. Executes in sandbox → writes code using KSA functions
  4. Verifies via Convex → checks actual state matches expected
  5. Updates Beads → marks tasks done, creates follow-ups
  6. Session endsbd sync persists everything to git

The agent can pick up exactly where it left off, even across sessions or handoffs to other agents.


Benchmarks

Real-world agent task benchmarks across different models. All tests run in isolated E2B sandboxes with full code execution.

Code Generation

| Model | Pass Rate | Avg Latency | |-------|-----------|-------------| | Claude Sonnet 4.5 | 100% (5/5) | 27.9s | | Claude Haiku 4.5 | 80% (4/5) | 12.7s | | Gemini 3 Flash Preview | 80% (4/5) | 16.0s |

Summary

| Category | Best Model | Notes | |----------|------------|-------| | Code Generation | Claude Sonnet 4.5 | Most reliable (100%) | | Research Tasks | Gemini 3 Flash | Better at multi-step reasoning | | Page Creation | Gemini 3 Flash | Better output verbosity | | Speed | Claude Haiku 4.5 | 2-3x faster than others |


Contributing

See CONTRIBUTING.md for development setup and guidelines.


Links

License

MIT