Help us shape the future of Go! Take the 2026 Go Developer Survey

platform

module
v0.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: MIT

README

Rocketable Platform

Rocketable Platform runs AI agents inside a repository or folder. People talk to the agents through a built-in web page, Slack, or MCP (Model Context Protocol, a standard way for other AI tools to call this one). Agents can read and edit files, run shell commands, use tools and skills, and run saved workflows, but only as far as their permission rules allow.

It is written in Go and runs inside your own workspace. It is not a hosted service shared by many customers.

Experimental software

Rocketable Platform is experimental. It runs actions chosen by an AI model against your files, shell, connected services, and team chat. Review its configuration, permissions, outputs, and integrations before you use it anywhere sensitive or in production.

This software is provided "as is", without warranty of any kind, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, noninfringement, availability, accuracy, or error-free operation. To the maximum extent permitted by law, Rocketable, Inc. and contributors are not liable for any claim, damage, data loss, service interruption, security issue, business loss, or other liability arising from use of, inability to use, or reliance on this software or its outputs.

See LICENSE for the full license terms.

What it does

  • Runs agents that follow your workspace's instructions, agent definitions, and skills, under permission rules you write.
  • Saves conversations and unfinished work in PostgreSQL. After a restart, work continues from the last finished step.
  • Takes requests from the web page, Slack mentions, MCP, scheduled jobs, and one-off or repeating scheduled messages.
  • Runs saved workflows written in Starlark, a small Python-like language.
  • Sends model requests to OpenAI or to any service with the same API, and can use several services side by side.
  • Can send traces of agent runs to OpenTelemetry-compatible tools.

Main parts

  • internal/rocketcode (RocketCode): the agent engine. It builds model requests from the workspace, runs tools, checks permissions, and saves a replayable record of each session.
  • internal/rocketclaw (RocketClaw): the long-running service around RocketCode. It connects the web page, Slack, MCP, scheduled jobs, attachments, and the database. Its program is cmd/rocketclaw.
  • cmd/funneld: a small HTTPS proxy that forwards public paths to internal URLs listed in funneld.json.
  • cmd/quickweb: serves small trusted internal web pages, each with one saved JSON document. See cmd/quickweb/README.md.

Getting started

go run github.com/Rocketable/platform/cmd/rocketclaw@main

Run rocketclaw help to list commands. RocketClaw reads rocketclaw.json (or the older femtoclaw.json) from the current folder. That file points at the workspace, holds the Slack credentials and channels, and turns on other integrations.

A workspace contains AGENTS.md and, optionally, agents/, skills/, scripts/, cron/, and workflows/ folders.

Web page

The web page is the main way to work with RocketClaw. It is built into RocketClaw and listens on 0.0.0.0:3000. To change that, set "web": {"listen_address": "127.0.0.1:3000"}. Links RocketClaw hands out use the tsnet node's HTTPS name once that node serves (see Voice), and this machine's Tailscale address otherwise.

RocketClaw identifies each browser by IP address, using the web_users map (for example "web_users": {"100.64.0.10": "alice"}) or, failing that, a Tailscale lookup. It refuses browsers it cannot identify. See the Web README for the page's features and optional Sentry error tracking.

Voice

The Voice page (/voice) and the voice button in each session's composer let you talk to an agent out loud. The browser sends audio straight to OpenAI's GPT-Live voice model. Each task the voice model hands off becomes a Web message in the conversation, marked media=Voice. Hand-offs enter the conversation in the order they arrive, without waiting for the agent: each one joins the running turn or starts the next. The voice model hears nothing about the agent's work while it runs. When a turn the call handed off finishes, its final reply is spoken once, as written. A reply over about 990 tokens (3,960 bytes) is not spoken: the voice says it is on the screen, and the Voice page switches to its transcript and shows the reply there as written. A message typed during the call cancels the spoken reply of every earlier hand-off; only a later hand-off is spoken again. It also mutes the voice at once, mid-sentence if need be, until the voice answers something you say after it. When the agent asks a question, the voice model says "I need your input. Please respond in the app." and reads the question and its options. Answer it in the app: spoken words never answer a question. Each person has one live call at a time: starting voice on the desk ends their call on the phone, while other people's calls, even on the same conversation, keep running. The Voice page's conversation, agent, voice and transcript choice belong to the person and are kept by RocketClaw, so they are the same on every device and survive restarts until Reset. Ending a call never stops the agent's work.

Voice has no settings of its own. It uses the provider behind the conversation agent's model:

  • rocketcode_auth: api_key: the public GPT-Live API, model gpt-live-1. It costs about $0.05 per minute, silence included. An api_base_url must use HTTPS unless its host is localhost or a loopback IP; otherwise voice refuses to send the API key.
  • rocketcode_auth: chatgpt: Codex's internal voice route, model gpt-live-1-codex, with the provider's ChatGPT login. This route is unofficial and may stop working at any time. The ChatGPT account's data settings apply.

On both routes, a redirect to another scheme, host, or port drops the voice credentials.

Per call, OpenAI receives your microphone audio; up to 40 of the conversation's recent messages, as written, each cut to 600 bytes and 12,000 bytes in total; the final replies it speaks; and the question notices. It never receives tool names, tool arguments, tool results, progress, reasoning, or attachments.

A call ends when you stop it, when the page closes or stays hidden for 30 seconds, when the page loses its connection to RocketClaw, when the browser's audio connection fails, or when OpenAI ends the call. There are no idle or no-speech timers. If the audio connection is not up 20 seconds after OpenAI answers, the browser retries once on the same microphone. If RocketClaw's connection to OpenAI drops, the chatgpt route reconnects, as Codex does, and the Voice page shows "Reconnecting to the agent…" meanwhile; the api_key route ends the call as lost. With Sticky on, the Voice page instead starts a new call after any of these connection losses, with sound cues, until you hang up; see the Web README.

The microphone needs a secure page: HTTPS, or http://127.0.0.1:3000 on the RocketClaw machine. For a phone or another device, RocketClaw can join your tailnet as its own Tailscale node (tsnet) and serve the web page over HTTPS. Turn on MagicDNS and HTTPS certificates for the tailnet, then add web.tsnet:

"web": {"tsnet": {"hostname": "rocketclaw", "tags": ["tag:rocketclaw"]}}

"tsnet": {} also works: the hostname defaults to rocketclaw and may use only a-z, 0-9, and -. Each tag must start with tag:.

  1. With RocketClaw stopped, run rocketclaw ts login. It prints a login link (and asks for device approval if your tailnet requires it), waits until the node is running, and exits. With "auth_key": "tskey-auth-…" under web.tsnet, it logs in with that key instead, and so does the server when the node is logged out. Prefer a single-use, pre-approved, tagged key; the key sits in the config file like other secrets.
  2. In the Tailscale admin console, confirm that the node appears in your own tailnet. The login link adds the node to whichever tailnet signs in with it.
  3. Start RocketClaw. It never prints a login link or waits for one: a logged-out node without a key only logs "Tailscale authentication unavailable", and the Web serves its plain listener.
  4. On the phone, with Tailscale connected, open https://<hostname>.<tailnet>.ts.net/voice.
  • Tag the node, for example tag:rocketclaw (the tailnet policy must list the tag under tagOwners). Add a tailnet rule that lets only named users reach it and lets it reach nothing. An untagged node acts as the Tailscale user who logged it in.
  • The node signs each phone in as the phone's Tailscale user. It refuses tagged devices, and no request header can choose the user.
  • Node keys expire after 180 days unless the node is tagged or key expiry is disabled for it in the admin console. An expired node needs rocketclaw ts login again.
  • Turning on tailnet HTTPS publishes machine names, including this node's, in public certificate-transparency logs.
  • The node keeps its state outside the workspace, in rocketclaw/tsnet-<hostname> under the OS user config directory (~/Library/Application Support on macOS, $XDG_CONFIG_HOME or ~/.config on Linux). Tailscale's log upload is off.
  • Never use tailscale funnel: it would put RocketClaw on the public internet.

The listen_address listener keeps its IP rules: web_users, then a Tailscale lookup. It never trusts Tailscale-User-* headers. A browser on the RocketClaw machine can use http://127.0.0.1:3000 after mapping 127.0.0.1 to yourself: "web_users": {"127.0.0.1": "you@example.com"} (localhost may connect from ::1, which needs its own mapping). Tailscale logins and web_users names are separate, so one person may appear under two names.

Processes on this machine, including agent tools and MCP servers, can still act as the owner: through the listen_address listener, or through this machine's own Tailscale address. See the transport README for the identity details.

Slack

Slack has three jobs: showing cron reports, showing MCP sessions, and quick help when an allowed user mentions the bot. Everything else happens in the web page.

Under slack.channels, map each channel to a list of agents and the Slack user IDs allowed to use them. A row named @ is not a channel: it gives agents and allowed users for mentions in any other channel or group DM the bot is already in.

Only a mention from an allowed user starts work. Messages without a mention, including replies in threads the bot answers in, reactions, and edited messages start nothing, and 1:1 DMs never start work. A top-level mention in a configured channel starts a new thread answered by the channel's first agent; a top-level mention with no text, file, or forward is ignored. A mention in a thread the bot does not know takes that thread over and reads up to 50 earlier messages. A mention in a thread the bot already answers in is that conversation's next turn and adds only the mention itself. It waits for running work and active goals instead of steering them. Mentions keep their files and forwarded threads. The bot marks each accepted mention with 🤖 and accepts it once, even if Slack delivers it again. If it cannot read the thread or take the request, it replies with a short error.

While it works, Slack shows one placeholder message, then the final answer and any files. Mention replies and cron reports end with a footer: the agent, its state (working, done, failed, or stopped), and an Open in Web link.

Cron report threads and MCP threads are read-only in Slack: the bot ignores every reply and mention in them, even after their record expires. Open the conversation in Web to keep working.

Slack has no commands. $stop, $agent, $goal, $enqueue, skill names, and any other $ text reach the agent as plain text. There is no agent picker, steering, queue card, question button, or reaction control. Mention turns cannot use ask_user_question, so the agent asks in its reply or hands the work to Web. Use Web to switch agents, run commands and skills, start goals, manage queued work, and stop any turn. Web messages used in a Slack thread are still posted there, and every reply in that conversation still goes to Slack.

Set up the Slack app with the bot event app_mention and these bot scopes, then reinstall it:

  • users:read and usergroups:read, so the web page shows names instead of Slack IDs.
  • users:read.email, so a mention's turn gets the sender's email as ROCKETCLAW_PRINCIPAL_EMAIL (see Agents and permissions). Without it, Slack turns get only ROCKETCLAW_PRINCIPAL_NAME.
  • channels:read and channels:history, so the bot can expand threads forwarded from public channels. It never joins channels on its own.

The message.* event subscriptions and Interactivity are no longer used and can be removed.

Slack's own Stop button needs two more steps: turn the app into an agent (Agents in the app settings, manifest features.agent_view), which cannot be undone, and subscribe to the bot event agent_session_stopped. Then each turn a mention started shows Slack's working state until it ends, and Stop from an allowed user ends the turn and its goal, like Web $stop. Slack drops the working state after one hour, and RocketClaw does not renew it. A workspace without agent sessions logs the refusal and runs turns normally; stop them from the footer's Web link. agent_view also adds an agent chat to the app's Messages tab that RocketClaw never answers.

See the cheatsheet for the full Slack app setup.

Release note for mention-only Slack:

  • Slack is now mention-only, and cron and MCP threads are read-only.
  • Edited messages don't start work, even when the edit adds a mention.
  • Mentions wait behind an active goal in their conversation.
  • Queue cards and agent-picker buttons posted by earlier versions do nothing, and so do ⏫ and 🛑 reactions.
  • Mention replies and cron reports end with a footer that links to Web. Where the workspace supports Slack agent sessions, an allowed user can stop a running mention turn with Slack's Stop; elsewhere, open the footer link and stop the turn in Web.
  • Slack no longer shows questions. Question buttons posted by earlier versions do nothing, and a question still waiting fails when its turn resumes.
MCP and scheduled jobs

MCP clients call session_prompt with a conversation ID, an agent, and a configured Slack channel. Each MCP conversation also gets a read-only Slack thread in that channel. Switch its agent or continue it from Web.

A job file in cron/ may name a Slack channel. Then an empty reply posts nothing, and any other reply starts a new read-only thread in that channel; follow up from its conversation in Web. A job without a channel posts nowhere: read or continue its runs from the Cron page in Web.

Agents can use rocketclaw_schedule_message for a follow-up in the current conversation. send_this_in accepts positive durations up to 5040h (210 days), including 12h and 168h. Set recurring to false for one message or true to repeat at that interval (at least 1m) until scheduled messages are reset. Pending schedules protect their conversations and explicit owners from normal retention cleanup.

How a request runs

  1. A request arrives from the web page (including a $workflow command), a Slack mention, MCP, a cron job, or a scheduled message.
  2. RocketClaw passes it to RocketCode with the chosen agent.
  3. RocketCode calls the model and runs tools, within the agent's permissions.
  4. RocketClaw saves each finished step and sends the reply back where the request came from.

On shutdown, tool calls already running finish and are saved, and background jobs are stopped. After a restart, each conversation continues from its last saved step.

Agents and permissions

Each agent file must set model, either as a model name such as gpt-6.1-sol or as a name mapped in rocketclaw.json (see Models and providers).

The root AGENTS.md goes into every agent's instructions. To leave it out for one agent, add this to that agent's frontmatter:

permission:
  rocketclaw:
    load_agents_md: false

For the bash tool, RocketCode checks every command in a script on its own, and each command must be allowed. When several rules match, the last one wins. Scripts it cannot parse are refused, even with bash: allow.

Bash rules match command text, not everything a program can do. An executable-path wildcard such as ./scripts/* does not match executable paths containing ..; name such an executable explicitly if it is intended. This check is not a shell sandbox: an approved script can still launch other programs or follow symlinks. To put a sandbox in front of one agent's shell commands, set customShell in that agent's frontmatter to the absolute path of a wrapper program; see the cheatsheet for what the wrapper must do.

A turn that a person starts from Web, voice, or Slack tells its shell commands who asked:

  • ROCKETCLAW_PRINCIPAL_NAME: the person's name. On Web it is the Tailscale display name, or the login when that is blank. On Slack it is the Slack display name, or the real name when that is blank.
  • ROCKETCLAW_PRINCIPAL_EMAIL: on Web, the Tailscale login; on Slack, the profile email.
  • ROCKETCLAW_PRINCIPAL_ID: the lowercase hex SHA-256 of the email after trimming spaces and lowercasing it, so Alice@Example.com and alice@example.com get the same ID.

With a web_users mapping, Web uses the configured value as both name and email. When RocketClaw has no email, only the name is set. The same person's values reach the subagents and shadows of that turn, the later turns of a $goal they set, and their queued or stashed messages when those run. A steer into a running turn keeps the values that turn started with. Cron turns, External MCP turns, messages one agent sends another, goal checks, and workflow workers get none of them. A name is a display name its owner can change, so use it for attribution only. Permission patterns that grant access per person should use ${ROCKETCLAW_PRINCIPAL_ID} or ${ROCKETCLAW_PRINCIPAL_EMAIL}. Such a rule covers everything that runs with that person's values: steers and promoted queued messages that other people deliver into the person's running turn, the later turns of the person's $goal, and a background subagent that starts after the person's turn ended, which takes the values of whichever top-level turn runs then. Per-person rules keep people's work apart for convenience; they are not an authorization boundary between people. The values say who asked for the turn, not a credential: permission patterns read them from the turn, but a script sees whatever value the command that runs it sets.

Some features are off until you turn them on under permission.rocketclaw:

  • rocketclaw_sessions_list, rocketclaw_sessions_get, rocketclaw_sessions_current_id, rocketclaw_sessions_get_url: let an agent read saved conversations and get a chat's Web link. These can read every conversation in the database, not only the agent's own. To protect the database, each call is limited: a list needs a since time and returns at most 200 conversations, and a read returns at most the 100 newest entries before before_entry_id, ending with [next_before_entry_id=N] when older entries remain. A list also takes a required criteria string: empty lists every stored conversation, and anything else is a Web /search query (free text plus tag:, cron:, agent:, room:, model:, is: and sort:) that returns only the chats /search would, with their matching messages. A read shows each call an execute script made as one code_mode line with its command, status, last output line and the approver's reason.
  • rocketclaw_store, rocketclaw_read, rocketclaw_delete, rocketclaw_list, rocketclaw_kv_store, rocketclaw_kv_read: let an agent publish Hosted Pages, such as reports, dashboards, and graphs, and the JSON Page Data they read. Each agent has its own files and data. rocketclaw_store returns a link, /pages/<space>/<agent>/<path>, that only people the Web admits can open; it opens as a tab in the space named after the agent's space:, and each space's Page Index lists its pages. Pages run sandboxed, so their scripts cannot act as the viewer, and they can only read their own agent's Page Data. Generated main agents allow all six.
  • rocketclaw_set_tag: lets an agent tag sessions with labels from groups you define. See the example agent.
  • allow_background: allow: lets long scripts and subagents keep running while the conversation moves on, and lets the agent steer, queue a follow-up behind, or stop a subagent that is still running.
  • rocketclaw_sessions_write: lets the agent start a Web session or send a message into one: steer, queue, stash, or stop. deny (the default) leaves it off. children reaches only sessions the agent's own session created. auto or auto(name) reaches every chat Web lists, with each write reviewed first. allow reaches every chat Web lists without review.

Name each tool under permission.rocketclaw. Wildcards such as "*" and the short form rocketclaw: allow are not accepted there.

permission:
  rocketclaw:
    rocketclaw_sessions_get: allow
    allow_background: allow
    rocketclaw_sessions_write: children

Release note for agent session control:

  • Breaking: under permission.rocketclaw, every tool must be named. An agent file that uses rocketclaw: allow, "*", or another wildcard such as rocketclaw_sessions_* fails to load until you list each tool it needs by name.
  • rocketclaw_start_new_thread, rocketclaw_list_sessions, rocketclaw_get_session, and rocketclaw_current_session_id are removed, with no aliases. Use rocketclaw_sessions_write with an empty session_id, rocketclaw_sessions_list, rocketclaw_sessions_get, and rocketclaw_sessions_current_id. Agent files are not migrated, and rules on the old names match nothing.
  • There is no rocketclaw_sessions_stop. To stop a session without sending it anything, call rocketclaw_sessions_write with mode: stop and an empty prompt. Once the stopped turn has saved, that session's transcript gets one line saying which session and agent stopped it.
  • There is no session.spawn_mode setting. An agent file that still has it fails to load; use rocketclaw_sessions_write instead.
  • rocketclaw_sessions_write defaults to deny, so existing agents can no longer start sessions until you allow it. That includes a deployed agents/main.md that still says rocketclaw_start_new_thread: allow; newly generated main agents have rocketclaw_sessions_write: allow. Also update prompt text that names the old tool.
  • An agent with auto or allow can write into and stop any chat Web lists, including Slack threads RocketClaw manages, and the replies post to Slack. This holds for every turn of that agent, including cron, External MCP, and Slack mention turns.
  • Steering accepts any sender. A steer joins the running turn while that turn still takes input, whoever sent it and whoever started the turn, so a person's Web steer now also joins goal continuations, Completion Note wakes, scheduled messages, and the first turn of a session an agent created. Hidden cron and External MCP runs and $workflow turns still take a steer as their next turn.
  • task's continue is now {session_id, mode} for agents with allow_background: allow. A still-running subagent is no longer refused: mode steers it, queues a follow-up after it, or stops it and runs the prompt next. A steer joins even when a foreground task call is waiting on that subagent. Queued follow-ups survive a restart, and no prompt, steer, follow-up, or wake reaches a subagent twice after a restart.
  • A continue that names a different subagent_type switches the subagent to that type instead of failing. The type must exist, the caller needs task permission for it, and its guardrail reviews the prompt and the answer. A steer switches a running subagent from its next step.
  • Every subagent now runs as a session of its own, on the same turn runner as other sessions, so its queue, steers, stops, and restart recovery work as a top-level session's do. A subagent session is not listed in the sidebar or search. Its Background Jobs report to the subagent itself. It acts for its top-level session's running turn: it writes sessions and tags for that session, the sessions it creates keep that turn's creator and agent limits, the files it attaches go out with that turn's reply, and rocketclaw_sessions_current_id returns that session's ID. It is not offered rocketclaw_schedule_message or rocketclaw_reset_scheduled_messages. Its first prompt carries a header naming the session and agent that delegated it.
  • Stopping a turn while its foreground task call waits also stops the subagent's current turn, and so on down a chain of foreground subagents, unless a background task job waits on that turn. The prompt the call sent, if still queued, is not withdrawn but held: it stays in the subagent's queue, shown in Web like a stash, through restarts, while the rest of the queue moves on. The next message sent to the subagent, by task, rocketclaw_sessions_write, or a person in Web, releases it to run just before that message, and a person's $goal releases it to run before the goal; a stash releases nothing, and a person's stash is never released this way. The stopped session gets no note. A restart is not a stop: the call waits again.
Shadow agents

Put alternative agent definitions in the directory named after their parent:

agents/some-important-agent.md
agents/some-important-agent/name-of-shadow-agent.md
agents/some-important-agent/another-shadow.md

Each immediate Markdown child is a shadow. Use ordinary agent frontmatter, including a model and permissions, in each file. No extra configuration list is needed. Deeper directories and directories without a matching parent file do not declare shadows. Shadows are not choices in the normal agent picker, and cannot create shadows of their own.

Each parent session has a separate saved session for every shadow. Each parent turn gives those sessions the same inputs, in the order the parent uses them: the prepared prompt, attachments, consumed steers, moved-work notices, and Background Job Completion Notes. Queued or stashed work is copied only when used; removed work is not copied. A shadow keeps its own replies, tool results, and history. The parent never waits for a shadow's answer. Model calls, cost, and tool work increase with each shadow.

A shadow may take at most 1.5 times the parent's steps, rounded down, counted from the message that starts the turn and again from each steer a person sends into it. Messages from other agents and system notices, such as Background Job Completion Notes, do not restart the count. A step is one model response in the turn itself; subagents, retries, and permission reviews do not count, and a step repeated after a restart counts once. A shadow that gets ahead of a parent still running pauses until the parent's next step gives it room. A person's steer always reaches the shadow, even one out of steps. Once the parent's turn has ended, a shadow out of steps lets its last tool calls finish and then stops, and its Web comparison tab shows Hit the step limit with both counts. That note is for people only; the shadow's model never sees it. A shadow whose answer comes within the limit completes normally.

Shadows run real tools. This is not a dry run. They share the workspace and external services with the parent, so allowed file edits, shell commands, and external writes can race or happen more than once. Each shadow uses its own permissions, without borrowing the parent's approvals. Start with permission-limited definitions and non-critical work.

Scripts run by shadows receive ROCKETCLAW_SHADOW with the full shadow agent name, such as some-important-agent/name-of-shadow-agent, alongside the other ROCKETCLAW_* environment variables. Scripts can use it to adjust their behavior during a shadow run.

The same inputs do not mean identical model conversations: system instructions, model, independent history, tool results, and compaction can differ. Workflow turns have no shadows.

Inspect shadows in the Web comparison tabs beside their parent. Their output stays there, without an extra Slack reply, cron report, or MCP response. Shadows cannot ask independent human questions, create threads, schedule work, manage goals, reload/restart the service, or start Background Jobs. Read-only comparison does not prevent the real tool effects described above.

New shadows on existing sessions begin at the next parent turn, seeded from the retained parent history without rerunning old work. Removing a file stops future turns, not work already admitted. Switching agents changes the shadows for future turns and retains earlier comparisons. Forks get fresh shadow sessions. Revert hides whole corresponding shadow turns; Redo restores saved comparisons without rerunning effects. Neither operation undoes files or external writes. Clearing history clears comparisons but keeps bindings for future work; deleting a parent deletes its owned shadow sessions.

Skills

Type $ in the web page to list commands and skills for the current agent. $review some text runs the skill named review, and $stop stops the current work. To queue a skill instead of running it now, use $enqueue $review some text. In Slack, $ text is plain text for the agent.

Skill templates read their arguments the same way OpenCode commands do: $ARGUMENTS is the whole text, and $1, $2, and so on are single words or quoted phrases.

Models and providers

The top-level openai object is the default model provider. Add more under providers, and give models short names under models:

{
  "openai": {"rocketcode_auth": "chatgpt"},
  "providers": {"work": {"rocketcode_auth": "chatgpt"}},
  "models": {"coding-high": "work/gpt-6.1-sol"}
}
model: '{{ model "coding-high" }}'

work/gpt-6.1-sol uses the work provider, and a bare gpt-6.1-sol uses openai. RocketClaw never switches to another provider on its own. Each provider compacts conversation history at 200000 tokens unless you set autocompaction_threshold.

Set prompt_cache_markers_relative_position (a negative number) only on a provider that accepts Anthropic cache_control markers, such as CLIProxyAPI in front of Claude. RocketClaw then marks one text piece of the last request message, counted from the end: -2 marks the piece before the last. Automatic permission reviews send the planned action as the last piece, so -2 lets the next review reuse the cached transcript. Leave it unset for OpenAI and other providers that reject unknown fields.

Sign in per provider with rocketclaw oai login [provider] [--headless]. Use rocketclaw oai list to see sign-ins and rocketclaw oai logout [provider] to remove one. Credentials are normally saved in .rocketclaw/auth.json.

Data and storage

  • database_url sets the PostgreSQL database. Only one RocketClaw process uses a database at a time; others wait. RocketClaw upgrades the database schema at startup. Older RocketClaw versions refuse to start on an upgraded database, so you cannot roll back by swapping in an older binary.

  • attachments sets where uploaded and generated files are kept. By default they go in <workspace>/.rocketclaw/attachments. You can pick another folder or an existing S3 bucket:

    "attachments": {"driver": "filesystem", "path": "/srv/rocketclaw/attachments"}
    
    "attachments": {"driver": "s3", "bucket_arn": "arn:aws:s3:::rocketclaw-attachments"}
    

    S3 uses the standard AWS credentials and region settings. Grant s3:PutObject, s3:GetObject, and s3:DeleteObject for attachments, plus s3:DeleteObjectVersion for a versioned bucket. Grant s3:ListBucket so deletion retries can distinguish missing files from denied access. RocketClaw does not create buckets or make files public.

  • Back up the database and the attachment storage together. Restoring only the database brings back references to files, not the files.

  • .rocketclaw/ holds generated runtime files, such as cloned overlays, per-session temporary folders, and oversized command output. Do not treat it as source code.

Monitoring and profiling

RocketClaw logs a health line once a minute with memory, Go scheduler, and database connection figures.

When profiling is enabled, RocketClaw also samples blocking events at an average of one per 10 milliseconds spent blocked and one in 100 mutex contention events.

rocketclaw run turns on Go profiling at 127.0.0.1:6060 by default. Use rocketclaw run --pprof=false to turn it off. Any process on the machine can reach that port, and profiles can contain private data, so do not expose the port and do not share downloaded profiles. To inspect a remote machine, forward the port over SSH:

ssh -N -L 127.0.0.1:6060:127.0.0.1:6060 trusted-host

Repository layout

  • cmd/: runnable programs.
  • internal/rocketcode/: the agent engine.
  • internal/rocketclaw/: the service around RocketCode.
  • internal/funneld/: the HTTPS proxy and its config loading.
  • internal/quickweb/: the small web page server.
  • internal/netutil/: shared networking code.
  • vendor/: copies of Go dependencies.

Development

go test ./...

make build builds RocketClaw and funneld. The RocketClaw step rebuilds the web frontend with Bun before building bin/rocketclaw. The built frontend in internal/rocketclaw/internal/web/dist/ is committed, so a Go-only build does not need Bun. When you change internal/rocketclaw/web/, commit the rebuilt dist/ files too.

make test in internal/rocketclaw starts PostgreSQL in Docker, or uses ROCKETCLAW_TEST_DATABASE_URL if set. It runs the Go tests once with race detection and coverage, enforcing the fixed COVERAGE_REQUIRED minimum in its Makefile. Generated protobuf code (*.pb.go) does not count toward the total. GitHub Actions tests against PostgreSQL 18.

Directories

Path Synopsis
cmd
funneld command
Package main implements the funneld binary.
Package main implements the funneld binary.
quickweb command
Package main implements the quickweb binary.
Package main implements the quickweb binary.
rocketclaw command
Command rocketclaw bridges Slack and external MCP inputs to RocketCode.
Command rocketclaw bridges Slack and external MCP inputs to RocketCode.
internal
funneld
Package funneld implements a small HTTPS reverse-proxy funnel daemon.
Package funneld implements a small HTTPS reverse-proxy funnel daemon.
netutil
Package netutil contains shared network address discovery helpers.
Package netutil contains shared network address discovery helpers.
quickweb
Package quickweb implements the Quickweb internal applet server.
Package quickweb implements the Quickweb internal applet server.
rocketclaw/agentlint
Package agentlint checks effective RocketClaw agent systems for unsafe permission and delegation combinations.
Package agentlint checks effective RocketClaw agent systems for unsafe permission and delegation combinations.
rocketclaw/backend
Package backend owns conversation execution, later-work, and cron.
Package backend owns conversation execution, later-work, and cron.
rocketclaw/backend/harnessbridgetest
Package harnessbridgetest holds test helpers for backend.
Package harnessbridgetest holds test helpers for backend.
rocketclaw/config
Package config loads and validates rocketclaw configuration files.
Package config loads and validates rocketclaw configuration files.
rocketclaw/frontend
Package frontend defines the conversation operations consumed by frontends.
Package frontend defines the conversation operations consumed by frontends.
rocketclaw/frontend/cron
Package cronfrontend schedules cron producers and their conversation Sync.
Package cronfrontend schedules cron producers and their conversation Sync.
rocketclaw/frontend/externalmcp
Package externalmcp hosts MCP servers for rocketclaw integrations.
Package externalmcp hosts MCP servers for rocketclaw integrations.
rocketclaw/frontend/rpc
Package rpc adapts the retained Web protocol to Go-owned conversation storage.
Package rpc adapts the retained Web protocol to Go-owned conversation storage.
rocketclaw/frontend/slack
Package slackconnector bridges Slack events into rocketclaw.
Package slackconnector bridges Slack events into rocketclaw.
rocketclaw/internal/web
Package web serves the compiled browser application embedded in RocketClaw.
Package web serves the compiled browser application embedded in RocketClaw.
rocketclaw/oai
Package oai provides ChatGPT OAuth-backed OpenAI clients for rocketclaw.
Package oai provides ChatGPT OAuth-backed OpenAI clients for rocketclaw.
rocketclaw/protocol
Package protocol defines shared RocketClaw event contracts.
Package protocol defines shared RocketClaw event contracts.
rocketclaw/skel
Package skel seeds the embedded rocketclaw skeleton into workspaces.
Package skel seeds the embedded rocketclaw skeleton into workspaces.
rocketclaw/workflow
Package workflow loads and validates saved RocketClaw workflows.
Package workflow loads and validates saved RocketClaw workflows.
rocketcode
Package rocketcode provides the reusable RocketCode runtime.
Package rocketcode provides the reusable RocketCode runtime.
rocketcode/codemode
Package codemode runs Starlark scripts that call outbound MCP tools.
Package codemode runs Starlark scripts that call outbound MCP tools.
rocketcode/mcpclient
Package mcpclient connects to outbound MCP servers for RocketCode code mode.
Package mcpclient connects to outbound MCP servers for RocketCode code mode.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL