@octostaff/claude-scuba
v0.4.3
Published
Claude scuba integration package for OctoStaff.
Readme
@octostaff/claude-scuba
Run Claude Code as an OctoStaff Bubble bot.
@octostaff/claude-scuba connects the Anthropic Claude Agent SDK to an
OctoStaff Bubble server. Add the configured Bubble bot principal to a thread and
claude-scuba will subscribe to that thread, forward user messages to Claude,
and write Claude text, reasoning, tool activity, approval requests, and tool
results back into Bubble.
When to Use It
Use @octostaff/claude-scuba when Claude Code should participate in Bubble
threads from a local machine, developer workstation, or long-running daemon that
dials into Bubble.
Use @octostaff/reef instead when Bubble needs to call out to a hosted A2A
agent over HTTP.
Install
npm install @octostaff/claude-scubaThe package includes the claude-scuba executable. Install it globally if you
want the command on your shell path:
npm install -g @octostaff/claude-scubaFor local installs, run the executable from an npm script or with npx:
npx claude-scuba --config ./claude-scuba.config.jsonSupported Claude Agent SDK versions
claude-scuba bridges the inner @anthropic-ai/claude-agent-sdk. It declares
a range rather than an exact pin:
@anthropic-ai/claude-agent-sdk: >=0.2.141 <0.4.0Every change runs the full claude-scuba integration suite (live + fake SDK) at
both ends of that range on CI — the 0.2.141 floor and the latest 0.3.x —
so both majors are continuously supported, not tested at a single point in time.
| Inner SDK | Status | Notes |
| ------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 0.2.x (≥ 0.2.141) | Supported | Batch TodoWrite plan tool. |
| 0.3.x | Supported (default) | Granular TaskCreate/TaskUpdate/TaskList plan tools + system:thinking_tokens telemetry — the bridge normalizes both tool shapes to the same neutral plan and drops the telemetry noise. |
| 0.4.x+ | Untested | Outside the declared range; may work but is not exercised. |
Both plan-tool shapes render identically to Bubble clients (a neutral task_list
part), so upgrading the inner SDK across the 0.2→0.3 boundary is transparent.
Pinning a custom inner SDK version
The SDK is resolved by normal Node module resolution at the install location and loaded lazily at runtime, so you can override it from the outside — no fork needed:
- Consumer app: declare your own exact
@anthropic-ai/claude-agent-sdkdependency (any version in range), or force one tree-wide with an npm/yarn/pnpmoverrides/resolutionsentry. - Docker: use a version-pinned image tag —
ghcr.io/octostaff/claude-scuba:<version>-sdk-<sdkversion>(see Docker). - Library embedders: pass the
queryFactoryoption toClaudeBubbleBotto supply your own SDKqueryimplementation entirely.
Prerequisites
- A running OctoStaff Bubble server.
- A Bubble bot principal and bearer token for that principal.
- Claude Agent SDK credentials in the process environment.
- A working directory that Claude may read or modify, depending on your permission mode.
Quick Start
Create claude-scuba.config.json:
{
"bubble": {
"url": "https://bubble.example.com",
"principalId": "claude-bot",
"token": { "env": "BUBBLE_BOT_TOKEN" }
},
"claude": {
"model": "claude-sonnet-4-5",
"cwd": "/path/to/project",
"permissionMode": "default",
"settingSources": ["user", "project"],
"includeProjectMemory": true
},
"logger": {
"level": "info",
"pretty": true
}
}Run the bot:
BUBBLE_BOT_TOKEN=... claude-scuba --config ./claude-scuba.config.jsonOverride the configured Claude working directory at launch time:
claude-scuba --config ./claude-scuba.config.json --cwd /path/to/projectclaude-scuba also loads a .env file from the current working directory when
one is present.
Configuration
bubble
url: Base URL of the Bubble server.principalId: Bubble bot principal ID this process authenticates as.token: Bearer token for the principal. Use a string or{ "env": "NAME" }.consumer: Optional cursor policy for thread consumption.
Default consumer policy:
{
"coldStart": { "mode": "from-head" },
"resume": { "mode": "live-only" }
}Set resume to { "mode": "durable" } when the bot should replay missed
events after downtime.
claude
model: Claude model alias or full model ID. Omit it to use the Claude SDK default.cwd: Working directory for Claude file and shell tools. Defaults to the process working directory.permissionMode: Claude Agent SDK permission mode. Supported values aredefault,plan,acceptEdits,bypassPermissions,dontAsk, andauto.settingSources: Optional Claude Code settings sources:user,project, andlocal.includeProjectMemory: Enables Claude Code project memory and adds theprojectsetting source.forwardSubagentText: Defaults totrue. Set it tofalseto suppress forwarded subagent narration.
logger
Set logger to false to disable logging, true for defaults, or an object:
{
"logger": {
"level": "debug",
"pretty": true,
"runLog": {
"enabled": true,
"dir": "./claude-run-logs"
}
}
}Run logs are NDJSON files containing SDK inputs, SDK outputs, and translated Bubble events for each Claude run.
Library Usage
import { ClaudeBubbleBot, loadClaudeScubaConfig } from '@octostaff/claude-scuba';
const config = loadClaudeScubaConfig({
bubble: {
url: 'https://bubble.example.com',
principalId: 'claude-bot',
token: { env: 'BUBBLE_BOT_TOKEN' },
},
});
const bot = new ClaudeBubbleBot({ config });
await bot.start();
await bot.wait();Docker
Prebuilt images are published to GHCR on each release:
docker pull ghcr.io/octostaff/claude-scuba:latestTags:
| Tag | Inner SDK |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| :latest, :<version> | Latest supported inner SDK (current 0.3.x). |
| :<version>-sdk-<sdkversion> | Coupled to an exact inner SDK — one per supported line, e.g. :0.3.0-sdk-0.2.141 (the 0.2.x floor) and :0.3.0-sdk-0.3.200 (the resolved 0.3.x). Use these to pin the inner SDK for reproducible deployments. |
<version> is the claude-scuba release version; <sdkversion> is the bundled
@anthropic-ai/claude-agent-sdk version (see Supported versions).
The image runs the claude-scuba daemon (ENTRYPOINT) and reads its config from
--config /etc/claude-scuba/config.json (CMD). It needs Claude Agent SDK
credentials and the bot's Bubble token in the environment:
ANTHROPIC_AUTH_TOKEN+ANTHROPIC_BASE_URL(orANTHROPIC_API_KEY)CLAUDE_SCUBA_TOKEN— the bot's Bubble bearer token (referenced by the config)CLAUDE_SCUBA_PROJECT_DIR— the host project mounted as the container working dir
See docker-compose.yml for a complete example that
inlines the config and wires these variables.
Operations
- The bot runs on Bubble threads where its principal has a participant role.
- Adding the bot principal to a thread starts a runtime for that thread.
- Revoking the bot principal's thread grant stops that thread runtime.
- In
defaultpermission mode, Claude tool approvals are routed through Bubble approval events. - Send
SIGINTorSIGTERMfor graceful shutdown.
Package Contents
The npm package ships compiled, minified JavaScript, the claude-scuba
executable, and TypeScript declarations. The runtime bundles the Bubble SDK code
it uses. Public declarations may reference @octostaff/sdk where public APIs
expose shared Bubble protocol types.
