sharkmagic.docs
Agents

Agent? Fetch sharkmagic.si/docs/llms.txt or this page as markdown

Agents on Shark#

How to point a coding agent or your own agent loop at Shark. Pick by where the agent runs:

your agent path changes to the agent status
Claude Code, Codex, Cursor or any agent with a shell, on your machine or server A. shark run as its command runner one instructions snippet GA-path
your own loop (any model, any framework) B. one tool backed by the SDK one tool definition GA-path
Claude Code, unmodified, running next to the Space C. the shell shim shark-bash (+ shark-rg) none: environment variables beta, self-hosted
a harness that cannot be intercepted D. sharkfn over MCP one MCP server beta
Claude Code, Codex or OpenCode, running in the cloud with its UI in your terminal shark code none beta, validated locally only
LangChain, LangGraph, smolagents, Prefect the SDK's integrations a few lines beta: integrations.md

In every path the model keeps thinking where it already does; only commands run in Shark, each in a fresh microVM next to the agent's persistent files and services. No VM exists for the Space while the model thinks.

A. Claude Code, Codex, Cursor: shark run as the command runner#

  1. Install the CLI and log in once on the machine where the agent runs (shark login --api-key -; quickstart.md).
  2. Create a Space for the project: shark create --name myproject, and put the code in it: shark cp -r . myproject:. (or git clone inside it).
  3. Paste the AGENTS.md snippet into the project's instructions file: AGENTS.md (Codex, Cursor and others) or CLAUDE.md (Claude Code). It tells the agent to run builds, tests and installs with shark run myproject -- '…', how exit codes work, and what not to do with keys.

What this gives you: the agent's heavy and risky commands run in a microVM with the project's files, its own Postgres or Redis when declared, and the Space's egress policy; your machine runs only the agent. Files the agent edits locally are not synced into the Space by this path: have it write files through commands (git apply, heredocs), push changes with shark cp, or keep the whole project in the Space.

Codex runs its shell commands through its own sandbox; shark run needs outbound HTTPS to hel1.sharkmagic.si from there (allow the host in the agent's network settings if it restricts network).

B. Your own agent loop: one tool, the SDK, op_id = tool call id#

Expose one tool to the model and back it with space.run. Pass the tool call's id as op_id: if your loop crashes and replays a tool call, or retries a request, Shark returns the stored result instead of running the command twice.

Tool definition (JSON Schema; adapt the envelope to your model provider's tool format):

{
  "name": "run",
  "description": "Run a bash command in the project's persistent Shark Space. Each command runs in a fresh Linux microVM; files persist between commands, shell state (cd, export) does not. Returns exit code, stdout and stderr.",
  "input_schema": {
    "type": "object",
    "properties": {
      "cmd": {"type": "string", "description": "bash command line, run from the Space root"},
      "cwd": {"type": "string", "description": "optional directory relative to the Space root"},
      "timeout_s": {"type": "number", "description": "optional; up to 900"}
    },
    "required": ["cmd"]
  }
}

Handler (Python):

from shark import Shark

shark = Shark()                                    # SHARK_API_KEY (an account key) from the environment
space = shark.spaces.get("myproject")

def run_tool(tool_call_id: str, cmd: str, cwd: str | None = None, timeout_s: float = 120) -> str:
    r = space.run(cmd, cwd=cwd, timeout=timeout_s, op_id=tool_call_id)
    out = f"exit: {r.exit}\n"
    if r.shark_status != "ok":
        out += f"shark_status: {r.shark_status}\n"
    return out + f"stdout:\n{r.stdout[-20000:]}\nstderr:\n{r.stderr[-10000:]}"

TypeScript is the same: await space.run(cmd, { cwd, opId: toolCallId }). Long commands: space.stream(cmd) yields output as it arrives; space.start(cmd) returns an Op you can re-attach to from another process with space.op(op_id).

Patterns that come free with Shark:

  • One Space per agent, user or customer, each with its own files and services; idle ones cost no compute.
  • Fork per attempt. space.fork(count=3) and run three fixes in parallel; keep the Space whose tests pass, delete the rest.
  • Fork per eval or test shard. One template Space, fork(count=50), one shard per fork.
  • Read files without a VM. space.files.read_text(path) and space.files.list(...) read the committed tree directly; a "read file" tool costs no lease.

C. Unmodified Claude Code: the shell shim#

shark-bash, self-hosted, beta.

How the metal proofs ran real Claude Code with no change to the harness or its prompt. Claude Code runs on the Shark host; its file tools (Read, Edit, Write) work on the Space's host mount; every Bash command goes to a microVM.

  1. Install shark-bash as a file named bash (Claude Code only accepts a shell whose path contains bash or zsh) and point the harness at it: CLAUDE_CODE_SHELL=/opt/shark/bin/bash (or SHELL).
  2. Start Claude Code with its working directory inside the Space and the Space's host environment (SHARK_W, SHARK_SP, SHARK_LEASE, SHARK_CTL), which the host writes when it provisions the Space.
  3. By default the shim runs pure reads (cat, ls, grep, git status, …) on the host mount and everything else in a microVM. SHARK_STRICT=1 sends everything to a microVM and refuses (exit 126) what cannot go there; strict mode in the shim is opt-in because its own pre-registered test did not pass (P76). The HTTP API is always strict.

Per command the shim snapshots the harness's edits into the Space, runs the command in a lease (output streamed while it runs), brings the lease's changes back into the harness's view and reports the final cwd. Ctrl-C and timeouts kill the VM. A second command while one runs waits SHARK_BUSY_MS (3,000) and then exits 125, unless SHARK_CONCURRENCY=N|auto.

Measured on the AX41 (2026-11-05), for commands run through Shark: 91–96 % of a command's time is the user's command; the rest is Shark's overhead (lease start, mount, commit). A lease itself costs 44 ms.

Status: used in the metal proofs with Claude Code 2.1.303 and 2.1.316. Provisioning a Space on a host is part of the proof kit, not a packaged installer: this path is for self-hosted nodes and design partners, not the hosted node.

Grep and Glob: shark-rg#

Beta.

Claude Code's Grep and Glob call rg. Over a lazily-loaded FUSE mount, walking a large tree is slow. shark-rg is an rg-compatible binary that answers those calls from an index of the Space's last commit plus what changed since, and runs the real rg with the same argv for anything it does not cover. The tool definitions the model sees are unchanged (byte-identical, so no token cost).

export USE_BUILTIN_RIPGREP=0                    # make Claude Code use the rg on PATH
export PATH=/opt/shark/rg-shim:$PATH            # a dir where shark-rg is installed as "rg"
export SHARK_RG_MOUNTS=/path/to/space=/path/to/W/ctl.sock   # mountpoint=control socket[,...]

SHARK_RG_OFF=1 forces the real rg. Measured on the AX41 (2026-11-05): served from the index (sharkfn), Grep and Glob on a 100k-file tree are 300–600× faster than ripgrep over the FUSE mount. Flag combinations that gave a different answer in testing go to the real rg by default (P95).

D. MCP: sharkfn#

Beta.

sharkfn serves Read, Write, Edit, Glob and Grep from a Space's committed tree, with no VM:

sharkfn serve -repo R -mount /workspace -stdio -space <id>      # one Space over stdio
sharkfn serve -repo R -mount /workspace -http 127.0.0.1:8792    # many Spaces: POST /mcp/<space>

Use it when the harness cannot be intercepted. MCP adds tool definitions to every model request, so it is not the default path; for Claude Code prefer shark-rg (no extra tokens). Self-hosted nodes only today.

Keys and agents#

  • Give the agent a key with only the scopes it needs. For path A, a default key (spaces:read/write, exec, files:read/write, usage:read) is enough; secrets:write and network:write belong to you, not the agent.
  • Never put the key in the prompt, the repo or the Space. The CLI reads ~/.shark/credentials; the SDKs read SHARK_API_KEY.
  • Third-party credentials the agent's commands need (GitHub, a data API): store them as Space secrets with expose: inject (concepts.md). The command sees a placeholder; the value never enters the VM, so the agent cannot print or exfiltrate it.
  • To hand a single Space to an agent, give it a Space-scoped key: shark keys create --name agent-myproject --space myproject (the secret is printed once; put it in the agent's secret store, not in its prompt). Agents under shark code already get a credential limited to their Space.