New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@cjhyy/code-shell-core

Package Overview
Dependencies
Maintainers
1
Versions
84
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cjhyy/code-shell-core

Core engine for code-shell — agent orchestration, tool execution, hooks, protocol. UI-agnostic.

latest
Source
npmnpm
Version
0.9.46
Version published
Weekly downloads
526
-70.89%
Maintainers
1
Weekly downloads
 
Created
Source

@cjhyy/code-shell-core

UI-agnostic agent orchestration framework. The headless core of code-shell: turn an LLM + a tool registry + a transcript into a multi-turn agent loop, with permissions, hooks, MCP support, and pluggable approval backends.

Compatible with Anthropic and OpenAI-protocol providers (Claude, DeepSeek, GPT, Gemini, Qwen, …). No terminal UI dependencies — embed it in a CLI, a web service, a Slack bot, a desktop app. This is a Node.js runtime package, not a browser SDK.

Install

npm install @cjhyy/code-shell-core
# or
bun add @cjhyy/code-shell-core

Requires Node ≥ 20.10 and an ESM-capable runtime.

Quickstart

import { Engine, HeadlessApprovalBackend } from "@cjhyy/code-shell-core";

const engine = new Engine({
  llm: {
    provider: "anthropic",
    model: "claude-sonnet-4-6",
    apiKey: process.env.ANTHROPIC_API_KEY!,
  },
  cwd: process.cwd(),
  // Headless approval — "approve-all" trusts the model fully and is
  // only appropriate for local/trusted prompts. Use "approve-read-only",
  // explicit permissionMode/tool allowlists, or a custom ApprovalBackend
  // in production.
  approvalBackend: new HeadlessApprovalBackend("approve-all"),
  headless: true,
});

const result = await engine.run("list files in this directory and summarise their purpose");

console.log(result.text);
console.log("turns:", result.turnCount, "reason:", result.reason);

Streaming events:

await engine.run("...", {
  onStream(event) {
    if (event.type === "text_delta") process.stdout.write(event.text);
    if (event.type === "tool_use_start") console.log("→", event.toolCall);
  },
});

Restrict the tool set:

new Engine({
  llm: {
    /* … */
  },
  // Whitelist — only these built-in tools are registered.
  enabledBuiltinTools: ["Read", "Glob", "Grep", "WebFetch"],
  // Or blacklist — registers every built-in except these.
  // disabledBuiltinTools: ["Bash", "Write", "Edit"],
});

What's included

  • Engine — turn loop, transcript management, session persistence, resume.
  • Tool system — registry, executor, permission classifier, schema validation. Built-in tools for filesystem, shell, web fetch, sub-agents, plan mode, tasks.
  • LLM clients — Anthropic, OpenAI (and any OpenAI-protocol endpoint). Provider catalog covers DeepSeek, Qwen, OpenRouter, Gemini.
  • MCP — connect to Model Context Protocol servers (stdio / SSE / streamable-http / in-process).
  • Hooks — pre_tool_use, post_tool_use, on_user_prompt_submit, on_session_start, on_session_end, more.
  • Protocol — AgentServer / AgentClient over JSON-RPC for running the engine out-of-process.
  • Run manager — queue, schedule, and persist multi-engine workflows.

Designing for production

  • Approval backend. HeadlessApprovalBackend("approve-all") is fine only for local/trusted prompts. For untrusted input, explicitly set permissionMode, restrict tools with enabledBuiltinTools / disabledBuiltinTools, or implement ApprovalBackend to gate destructive tools (Write/Edit/Bash) through your own auth.
  • Permission rules. Pass permissionRules to the engine for fine-grained allow/deny per tool + args pattern. Bash commands additionally get a built-in safety classifier (dangerous commands like rm -rf always require explicit approval).
  • Hooks are the right place for audit logging, prompt rewriting, and policy enforcement.
  • Memory. The engine ships with an extract-memories + auto-dream pipeline that persists to ~/.code-shell/memory/. Disable by passing a no-op MemoryOrchestrator, or scope to a project by setting CODE_SHELL_HOME.

The stable, recommended construction path for embedders is the createServer / createClient factory pair over a protocol transport. Direct new Engine(...) still works for advanced cases — but the protocol-mediated path is what we test, document, and avoid breaking.

import { createServer, createClient, createInProcessTransport } from "@cjhyy/code-shell-core";

const [serverT, clientT] = createInProcessTransport();
const handle = createServer({
  transport: serverT,
  cwd: process.cwd(),
  llm: { provider: "anthropic", model: "claude-sonnet-4-6", apiKey: KEY },
  permissionMode: "default",
});
const client = createClient({ transport: clientT });

client.onStreamEvent(({ sessionId, event }) => {
  if (event.type === "text_delta") process.stdout.write(event.text);
});

const result = await client.run({ sessionId: "main", task: "Summarize README.md" });
console.log(result.text);

handle.close();
client.close();

For an out-of-process worker, swap createInProcessTransport() for a StdioTransport pair. The factory accepts any Transport, so a future IpcAdapter will compose without changing the call shape.

Browser UI hosts that only need the trusted Panel App lifecycle coordinator should use the audited browser-safe subpath:

import { PanelAppLifecycleRuntime } from "@cjhyy/code-shell-core/browser/panel-app-runtime";

This entry contains no Engine, filesystem, process or Electron dependency. The non-browser alias is @cjhyy/code-shell-core/panel-app-runtime.

StreamEvent includes background_agent_completed (B2.2) so embedders that don't poll notificationQueue still observe sub-agent finish/fail results. client.onBackgroundAgentCompleted((sessionId, event) => …) is the typed entry point; events also flow through the catch-all onStreamEvent.

Stable surface

These exports are covered by the stability promise:

AreaStable exports
FactoriescreateServer, createClient, createInProcessTransport, StdioTransport
Server/clientAgentServer, AgentClient (direct use is supported but createServer/Client preferred)
EngineEngine, EngineConfig, EngineRuntime, ChatSessionManager
Protocol typesMethods, ErrorCodes, RpcMessage, RunResult, StreamEvent, StreamCallback, BackgroundAgentCompletedEvent
LLMLLMConfig, LLMResponse, ModelPool, createLLMClient, registerProvider
Tool authoringToolDefinition, ToolCall, ToolResult, RegisteredTool, BUILTIN_TOOLS, HookContext, HookResult
PermissionsPermissionClassifier, HeadlessApprovalBackend, AutoApprovalBackend, ApprovalBackend, PermissionMode, PermissionRule
ErrorsFrameworkError + subclasses (LLMError, ToolError, PermissionDeniedError, …)

Treat as internal

Anything not in the table above — including root-entry exports for product/runtime helpers and direct imports from ./engine/..., ./tool-system/..., ./session/..., ./hooks/... subpaths — is experimental/internal unless explicitly documented otherwise, and may change between minor versions without notice. Plan to migrate via the protocol surface instead of deep-importing.

In 0.8 the plugin installer / marketplace / onboarding / self-updater exports (installPluginFromPath, installPlugin, addMarketplace, resolveApiKey, checkForUpdate, …) moved off this root entry to @cjhyy/code-shell-core/internal — they are host-assembly surfaces for the in-repo TUI/desktop apps, not part of the embeddable agent SDK.

Stability

Pre-1.0 — APIs may change between minor versions. The "stable surface" table above is the contract; everything else is mobile.

Breaking in 0.8: host-assembly exports (installer/marketplace/onboarding/ updater) left the root entry; import them from @cjhyy/code-shell-core/internal if you must (no stability promise there).

See CHANGELOG.md in the monorepo.

License

MIT © maki maki. See LICENSE.

Core exposes the Link registry and credential/policy machinery, and starts with no provider implementations. Product hosts install reviewed providers before creating an Engine; importing Core alone does not activate HTTP integrations.

import { Engine, registerLocalLinkProviders } from "@cjhyy/code-shell-core";
import { createDefaultLinkProviders } from "@cjhyy/code-shell-server/links";

registerLocalLinkProviders(createDefaultLinkProviders());
const engine = new Engine(config);

A custom SDK host can instead register its own LocalLinkProviderSpec implementations. Registration is process-scoped, validates unique provider/action IDs, and does not connect accounts or grant permissions. Desktop, TUI and serve compose the defaults explicitly; spawned workers load createLinkProviderModule through the existing trusted module-loading seam. Pure provider normalization helpers remain temporarily on the Core extension entry while their existing CLI/remote/verification consumers migrate; HTTP provider implementations live only in Server.

Keywords

ai

FAQs

Package last updated on 22 Oct 2026

Related posts