Everything Caraka does, and what it deliberately doesn't.
Caraka is a bridge, not an agent. It has no reasoning loop, no execution tools, no model provider, and no plugin marketplace — your coding agent already has all of those, in better form.
⏸v0.2 preview. A private Telegram DM to Claude Code is usable now, and so is a group on the chat allowlist. caraka service prints a unit rather than installing one. Memory, attachments, and other agents remain roadmap work.
01
Quickstart
Install from the repository you want Claude to work in. The wizard checks local prerequisites, validates the Telegram bot, then pairs one private operator.
$ claude auth status
$ npx caraka init
✓ Workspace · current directory
✓ Claude login · ready
✓ Telegram · paired
✓ Secrets · mode 0600
$ npx caraka doctor
$ npx caraka start
!The token is entered in the terminal, never in config.yaml or an AI chat. Start keeps the gateway in the foreground until Ctrl-C.
02
Sessions & topics
A Telegram topic or a Discord thread maps to one persisted agent session. Where threads are unavailable — a failed creation, or WhatsApp, which has none — the same task runs in linear mode behind a workspace and session header.
(ordinary message)Creates or resumes the session for this Telegram thread and sends the text to Claude unchanged.
/newCreate a fresh local session and, where topics are available, a new topic for it.
/stopSend session/cancel for the active Claude prompt.
/statusShow idle, running, awaiting_approval, done, failed, or cancelled.
/wsList the configured workspaces and their paths, answering in General.
/switch <preset>Rebind this session to another loaded agent preset from its next task on.
/commandsList the slash commands Claude reported for this session, or say it has reported none yet.
/usageReport the context and cost from the agent’s last usage update, or say none has arrived.
/ingat <note>Save a note to memory for this workspace, or say memory is off.
/lupakan <id>Delete one memory item by its id.
/memoriList what memory currently holds for this workspace.
/yolo <duration>Offer a trust window for this workspace. The duration is mandatory, sixty minutes is the ceiling, and a signed button opens it.
/lockClose the trust window now.
/helpShow the command list.
restartLoad the stored ACP session before the next prompt, and close any trust window the last process left open. A CLI-route session starts a fresh agent thread instead: its id lives in process memory.
!One run at a time per workspace and the rest queued FIFO; past 20 messages a minute the sender waits, and a run is cancelled at 30 minutes. A group or guild channel is served once its id reaches the chat allowlist. More than one workspace is supported, and @slug in front of a message picks which.
03
Claude over ACP
Caraka starts the official Claude ACP adapter as a subprocess. Claude owns the model, tools, sandbox, authentication, and repository context.
SHIPPED · ACP v1Official adapter@agentclientprotocol/sdk 1.3.0 and claude-agent-acp 0.63.0 are pinned runtime dependencies.
SESSIONNew and loadEach chat route stores the ACP session id. A missing old session is replaced without breaking the route.
CLI FALLBACKSeven presets, one YAML eachAn agent without ACP is spawned from a preset in presets/agents/ and answers in one text update. The MCP inbox is still roadmap work.
!No model abstraction or agent loop exists in Caraka. ACP transports prompts, updates, permission requests, and cancellation.
04
Signed approvals
ACP permission requests become a button on whichever channel has buttons, and a one-time code on the card where none exist. An ordinary word is never interpreted as approval.
allowOnly an ACP allow_once option is offered, and the button carries the option’s own name. An option that would leave standing permission behind is answered with reject_once instead.
rejectSelect reject_once when available; otherwise cancel the permission request.
trust windowWhile one is open, an ordinary request is allowed once, announced in the chat, and audited; a high-risk one keeps its buttons.
callbackRandom id plus truncated HMAC, 33 characters — inside Telegram’s 64-byte callback_data and inside Discord’s custom_id.
codeWhere a channel has no buttons, four characters from randomBytes over a 32-symbol alphabet, stored on the approval row and printed on that card alone — never in an audit row, a log line, or a prompt. Replying ok or no with it spends it once. Five wrong codes close the route for that session, and a channel that has buttons is given no code.
bindingValidated against the channel principal, local session, ACP session, and tool-call record.
TTLExpires after ten minutes.
replayThe database update succeeds once; later taps are rejected.
shutdownPending permission requests are cancelled before the adapter closes.
!The approval card shows the tool title and a scrubbed target or command when ACP supplies one.
05
Secrets & audit
The bridge accepts untrusted chat input, so identity checks and scrubbing happen before Claude or disk receives data.
chat allowlistA message is dropped unless its chat id is listed. Channel posts are never served.
sender allowlistThe gateway refuses to start empty, and a sender outside it is audited as denied wherever it wrote.
group pairingA group or guild channel is confirmed in the operator’s DM, never in the room itself. Telegram privacy mode stays on, group admin is never requested, and Discord is never asked for the MESSAGE_CONTENT intent.
group disclosurePutting a room on the allowlist chooses to show that work to everyone who can read it: every one of them sees the approval cards, paths, diffs, and command output. A Discord role changes none of it, and a role never approves anything.
secret files~/.caraka/secrets uses mode 0700; every token and the approval key use 0600, and the Baileys auth state is a 0700 directory inside it.
scrubberRuns before every outbound message on every channel and before every audit detail. No CARAKA_ variable reaches an agent subprocess.
auditSQLite triggers reject UPDATE and DELETE on audit rows.
networkNothing is opened to the internet. Two listeners exist and both bind 127.0.0.1: caraka dashboard, GET only with the database read-only, and the WhatsApp Cloud API webhook, which verifies X-Hub-Signature-256 in constant time even on loopback.
outputRich Message first on Telegram with a scrubbed plain-text fallback; plain markdown on Discord and WhatsApp, and a .md attachment past three pieces on both.
!The audit stores prompt length and hash, not the raw private prompt.
06
Configuration
One validated YAML file names the workspaces, the configured channels, their allowlists, the interface language, the memory provider, and the agent. Secrets are separate.
version: 1
language: en
workspace:
name: toko-api
path: /home/user/dev/toko-api
telegram:
botUsername: toko_caraka_bot
allowFrom: ["88123456"]
allowChats: ["88123456"]
topics: true
discord: # optional
appId: "140000000000000000"
allowFrom: ["230000000000000000"]
allowChats: ["990000000000000000"]
whatsapp: # optional
provider: cloud-api
phoneNumberId: "1500000000"
allowFrom: ["628123456789"]
agent:
adapter: claude-agent-acp
adapterVersion: 0.63.0
!CARAKA_HOME changes the local data directory. CARAKA_TELEGRAM_TOKEN, CARAKA_DISCORD_TOKEN, and the three CARAKA_WHATSAPP_ variables are available for controlled automation, but a 0600 file under ~/.caraka/secrets is the safer default, and no CARAKA_ variable is passed down to an agent subprocess. Choosing the baileys provider needs acknowledgeRisk: true written by hand, and start refuses without it. The interface language, English or Indonesian, is asked once during init and never guessed from an incoming message.
07
CLI reference
The command surface is small on purpose, and it grows one verb at a time.
npx caraka init [--workspace PATH]Check prerequisites, choose the interface language, validate the bot, pair one Telegram principal, and write private config.
npx caraka doctorRead-only checks for runtime, config, permissions, workspace, Claude, allowlist, Telegram, and topic capability.
npx caraka startRun the long-polling Telegram-to-Claude gateway in the foreground.
npx caraka stopSend SIGTERM to the PID the running gateway wrote to ~/.caraka/caraka.pid.
npx caraka statusReport whether the gateway runs, with its PID, workspace, and bot username. No token, and nothing anyone wrote in chat.
npx caraka dashboard [--port n]Serve a read-only page on 127.0.0.1:7718 that reads the same database the gateway writes: sessions, runs, approvals, audit, policy, memory. It answers GET only, and it works while the gateway is stopped.
npx caraka trust <ws> --for 30mOpen a trust window from the terminal, sixty minutes at most. Adding --bypass hands the permission decisions to Claude itself, where Caraka cannot see them.
npx caraka service --print systemd|launchd|schtasksPrint one unit file to stdout.
npx caraka --versionPrint the package version.
npm i -g carakaOptional global install; use caraka instead of npx afterward.
!There is no doctor --fix, uninstall command, workspace manager, or audit CLI. caraka service writes nothing and installs nothing: it prints a unit for you to save and load yourself, and the macOS one starts at login rather than at boot.
The spec is public, in full.
Thirteen research documents, plus PRD, FRD, architecture, ERD, security model, and roadmap.