@yfedberts/huscarl
v1.0.2
Published
Typed Node.js/TypeScript SDK for the OpenViking REST API
Maintainers
Readme
Huscarl - Node.js SDK for OpenViking
The Node.js/TypeScript client for OpenViking. Bring full context database access to your Node.js backend.
What is Huscarl?
Huscarl is a typed Node.js/TypeScript client for OpenViking, an open-source context database for AI agents. OpenViking stores resources, memories, and skills in a virtual filesystem addressed by viking:// URIs, with semantic retrieval and automatic AI-generated summaries at three levels of detail (L0/L1/L2).
OpenViking is Python-first. It ships a Python SDK, a CLI, and an MCP server. Huscarl fills the Node.js gap, giving TypeScript developers full REST API access through an idiomatic, ergonomic interface. Types are bundled; no @types/ package needed.
Why Huscarl?
Huscarl is the right choice when you need programmatic control over OpenViking from a Node.js application:
- Ingestion pipelines: batch ingest files, URLs, and directories
- Admin tooling: manage accounts, users, and roles in a multi-tenant deployment
- Backend services: retrieve context before calling an LLM, implement RAG workflows
- Session tracking: build persistent conversation memory with automatic knowledge extraction
- Full API access: covers the complete OpenViking REST API, not just a subset
Huscarl vs. MCP
OpenViking also exposes an MCP server that integrates directly with Claude, Cursor, and other AI tools. MCP is the right choice when an AI model needs to call OpenViking as a tool inside a chat interface.
Use Huscarl when you are building Node.js services, ingestion pipelines, admin tooling, or anything that needs programmatic access beyond what MCP's six high-level tools expose.
Installation
npm install @yfedberts/huscarlRequires Node.js >= 18.
Quick Start
import { Huscarl } from "@yfedberts/huscarl";
const huscarl = new Huscarl({
url: "http://localhost:1933",
apiKey: "your-api-key",
});
await huscarl.initialize(); // verify server is reachable
// Ingest a document
await huscarl.resources.add("./docs/guide.md", {
target: "docs/",
reason: "Project documentation",
wait: true, // block until embeddings are ready
});
// Semantic search
const results = await huscarl.retrieval.find("how to configure authentication", {
targetUri: "viking://resources/docs/",
limit: 5,
});
// Read the top result
const content = await huscarl.resources.read("docs/guide.md");Workflow Overview
A typical integration follows this pattern:
Ingest: Add files, URLs, or directories via
resources.add(). Setwait: trueto block until semantic processing completes, or callwaitProcessed()at a checkpoint.Retrieve: Use
retrieval.find()for vector similarity search,retrieval.search()for context-aware search that uses conversation history to expand the query, orretrieval.grep()/retrieval.glob()for exact text and filename matching.Track: Create a
session, append messages withaddMessage(), record which contexts were actually used withused(), then callcommit()to archive the conversation and trigger long-term memory extraction.Administer: Use
adminto manage accounts and users in a multi-tenant deployment. Usecontexts.get()to obtain a scoped handle that acts as a specific user, useful for building multi-user backends.
Examples
The examples/ folder contains runnable .ts files for common patterns: quickstart, RAG pipeline, batch ingestion, and multi-tenant setup. Each file is self-contained with inline comments.
Modules
| Module | Description | Docs |
|--------|-------------|------|
| resources | Add, read, move, remove, link resources and directories | docs/resources.md |
| retrieval | Semantic search, grep, and glob | docs/retrieval.md |
| sessions | Conversation sessions and memory extraction | docs/sessions.md |
| skills | Register and search skill definitions | docs/skills.md |
| admin + contexts | Multi-tenant accounts, users, roles, and scoped handles | docs/admin.md |
| observer | Server health and component monitoring | docs/observer.md |
Error Handling
All methods throw HuscarlError on failure. Use HuscarlError.isHuscarlError(err) as a type guard.
import { HuscarlError } from "@yfedberts/huscarl";
try {
await huscarl.resources.read("missing/file.md");
} catch (err) {
if (HuscarlError.isHuscarlError(err)) {
console.error(err.code, err.message);
}
}Development
npm install # install dependencies
npm run typecheck # type-check without emitting
npm test # run tests
npm run build # build CJS + ESM + .d.tsZero runtime dependencies. Contributions welcome - open an issue or PR.
License
Licensed under the Apache License 2.0.
Copyright 2026 Yulius Faustinus Edbert Santoso
