Observed since 20 Oct, 22:38 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
@0x6d61/wn-core
Lightweight AI Agent Core Framework
Lightweight AI Agent Core Framework for Node.js.
Build any AI agent by combining LLM providers, personas, skills, MCP tools, and built-in tools.
npm install @0x6d61/wn-core
Global install (to use as CLI):
npm install -g @0x6d61/wn-core
wn-core serve --provider claude --model claude-sonnet-4-20250514
Listens on stdin/stdout for JSON-RPC 2.0 messages from a TUI or any client.
# Test: pipe a JSON-RPC message
echo '{"jsonrpc":"2.0","id":1,"method":"input","params":{"text":"hello"}}' | wn-core serve
import {
createClaudeProvider,
AgentLoop,
ToolRegistry,
createReadTool,
createWriteTool,
createShellTool,
createGrepTool,
createNoopHandler,
} from '@0x6d61/wn-core'
// 1. Create an LLM provider
const providerResult = createClaudeProvider(
{ apiKey: process.env['ANTHROPIC_API_KEY'] },
'claude-sonnet-4-20250514',
)
if (!providerResult.ok) throw new Error(providerResult.error)
// 2. Register built-in tools
const tools = new ToolRegistry()
tools.register(createReadTool())
tools.register(createWriteTool())
tools.register(createShellTool())
tools.register(createGrepTool())
// 3. Build an AgentLoop
const loop = new AgentLoop({
provider: providerResult.data,
tools,
handler: createNoopHandler(),
systemMessage: 'You are a helpful assistant.',
})
// 4. Run a single conversation turn
const result = await loop.step('Read src/index.ts and summarize it')
if (result.ok) {
console.log(result.data)
}
Configuration is loaded from two levels: ~/.wn/config.json (global) and .wn/config.json (project-local). CLI flags take the highest priority.
{
"defaultProvider": "claude",
"defaultModel": "claude-sonnet-4-20250514",
"defaultPersona": "default",
"providers": {
"claude": { "apiKey": "${ANTHROPIC_API_KEY}" },
"openai": { "apiKey": "${OPENAI_API_KEY}" },
"ollama": { "baseUrl": "http://localhost:11434" },
"gemini": { "apiKey": "${GEMINI_API_KEY}" }
},
"mcp": {
"servers": [
{
"name": "example",
"command": "npx",
"args": ["-y", "example-mcp-server"]
}
]
}
}
API keys can reference environment variables using ${ENV_VAR} syntax.
OAuth Token (authToken): Claude provider also supports OAuth authentication via authToken. Use authToken instead of apiKey when authenticating with a Claude OAuth token:
{
"providers": {
"claude": { "authToken": "${ANTHROPIC_AUTH_TOKEN}" }
}
}
Priority (highest to lowest): CLI flags > project-local .wn/ > global ~/.wn/
wn-core uses a 3-layer resource model. Resources are loaded from ~/.wn/ (global) and .wn/ (project-local). Local resources override global ones with the same name.
A persona is a plain Markdown file that defines the system prompt for the LLM.
Directory: personas/
~/.wn/personas/default.md
.wn/personas/security-expert.md
Example (personas/default.md):
You are a helpful assistant.
Answer concisely and accurately.
No frontmatter required — the entire file content becomes the system prompt. Select a persona by name (filename without .md) via defaultPersona in config or --persona CLI flag.
A skill defines a reusable action with a description, allowed tools, and instructions.
Directory: skills/<skill-name>/SKILL.md
~/.wn/skills/code-review/SKILL.md
.wn/skills/recon/SKILL.md
Example (skills/code-review/SKILL.md):
---
name: code-review
description: Review source code for bugs and security issues
tools: [read, grep, shell]
---
## Instructions
1. Read the target files using the read tool.
2. Check for common vulnerabilities (injection, XSS, etc.).
3. Report findings with severity and remediation advice.
Frontmatter fields:
| Field | Required | Default | Description |
|---|---|---|---|
name | No | directory name | Skill identifier |
description | Yes | — | Short description of the skill |
tools | No | [] | List of tools the skill can use |
The body (after ---) contains the detailed instructions.
An agent definition configures a sub-agent with its own persona, skills, provider, and model.
Directory: agents/
~/.wn/agents/scanner.md
.wn/agents/code-reviewer.md
Example (agents/scanner.md):
---
persona: security-expert
skills: [recon, port-scan]
provider: claude
model: claude-sonnet-4-20250514
---
A sub-agent specialized in network reconnaissance.
Runs port scans and service detection, then reports findings.
Frontmatter fields:
| Field | Required | Default | Description |
|---|---|---|---|
name | No | filename | Agent identifier |
persona | No | "" | Persona name to use as system prompt |
skills | No | [] | List of skills to enable |
provider | No | "" | LLM provider override |
model | No | "" | Model override |
The body becomes the agent's description.
wn-tui (separate process) <-- JSON-RPC 2.0 --> wn-core
|
+-- AgentLoop
+-- LLMProvider (Claude/OpenAI/Ollama/Gemini)
+-- Loader (persona/skill/agent)
+-- Tools (read/write/shell/grep + MCP)
+-- SubAgentRunner (Worker Threads)
+-- RPC Server (JSON-RPC 2.0)
See docs/architecture.md for details.
Core and clients communicate via JSON-RPC 2.0 over stdin/stdout (NDJSON format).
| Method | Params |
|---|---|
response | { content: string } |
toolExec | { event: 'start'|'end', name, args|result } |
stateChange | { state: 'idle'|'thinking'|'tool_running' } |
log | { level: 'info'|'warn'|'error', message } |
| Method | Params | Result |
|---|---|---|
input | { text: string } | { accepted: boolean } |
abort | {} | { aborted: boolean } |
configUpdate | { persona?, provider?, model? } | { applied: boolean } |
npm install
npm test # Run tests (344 tests)
npm run typecheck # TypeScript type check
npm run lint # ESLint
npm run build # Build (tsup)
MIT
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
openaiEnvironment{
"local_name": "openai",
"alias": false,
"peer_metadata": null
} | ^6.25.0 | runtime |
@anthropic-ai/sdkEnvironment{
"local_name": "@anthropic-ai/sdk",
"alias": false,
"peer_metadata": null
} | ^0.78.0 | runtime |
@google/generative-aiEnvironment{
"local_name": "@google/generative-ai",
"alias": false,
"peer_metadata": null
} | ^0.24.1 | runtime |
@modelcontextprotocol/sdkEnvironment{
"local_name": "@modelcontextprotocol/sdk",
"alias": false,
"peer_metadata": null
} | ^1.27.1 | runtime |
tsxEnvironment{
"local_name": "tsx",
"alias": false,
"peer_metadata": null
} | ^4.21.0 | development |
tsupEnvironment{
"local_name": "tsup",
"alias": false,
"peer_metadata": null
} | ^8.5.1 | development |
eslintEnvironment{
"local_name": "eslint",
"alias": false,
"peer_metadata": null
} | ^10.0.2 | development |
vitestEnvironment{
"local_name": "vitest",
"alias": false,
"peer_metadata": null
} | ^4.0.18 | development |
prettierEnvironment{
"local_name": "prettier",
"alias": false,
"peer_metadata": null
} | ^3.8.1 | development |
@eslint/jsEnvironment{
"local_name": "@eslint/js",
"alias": false,
"peer_metadata": null
} | ^10.0.1 | development |
typescriptEnvironment{
"local_name": "typescript",
"alias": false,
"peer_metadata": null
} | ^5.9.3 | development |
@types/nodeEnvironment{
"local_name": "@types/node",
"alias": false,
"peer_metadata": null
} | ^25.3.0 | development |
typescript-eslintEnvironment{
"local_name": "typescript-eslint",
"alias": false,
"peer_metadata": null
} | ^8.56.1 | development |
@vitest/coverage-v8Environment{
"local_name": "@vitest/coverage-v8",
"alias": false,
"peer_metadata": null
} | ^4.0.18 | development |
eslint-config-prettierEnvironment{
"local_name": "eslint-config-prettier",
"alias": false,
"peer_metadata": null
} | ^10.1.8 | development |
Source distribution
{
"shasum": "b5633a784641e8781a0b2050c0abd0b544c4bdc2",
"tarball": "https://registry.npmjs.org/@0x6d61/wn-core/-/wn-core-0.1.2.tgz",
"fileCount": 19,
"integrity": "sha512-IGlwApky2677C2fPelZFBgbj7tkteb54F4BUQRNnlJjnx039Dabw0fRSocjykuFUiKLHYhq+A9KQz3Em70pvGg==",
"signatures": [
{
"sig": "MEYCIQCCE/lGRoPSTDy+SlSY7AVqFnuHe7ktyg7RSUzANJcpZQIhAPQZ/oljywEa/qChmiaJyovk1Fo8//3IqfCj0t1gYMek",
"keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
}
],
"unpackedSize": 307954
}Observed since 20 Oct, 22:38 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:3d8bfbede02487bc3e8f5987bb7bdc83ca0b48bfee4b953828a84149e40b0a2b