Sign inSign up

joaopestana/claude-extended:latest

Machine learning & AI
Manifest digest

sha256:881dad7d8afe3b88caa348b3e6bd9b325d5828ad6e7aeaf843f23049e29acee6

Last pushed

about 1 hour by joaopestana

Type

Sandbox Kit

Manifest digest

sha256:881dad7d8afe3b88caa348b3e6bd9b325d5828ad6e7aeaf843f23049e29acee6

yaml
schemaVersion: "3"
licenses:
    - SEE LICENSE IN https://github.com/anthropics/claude-code/blob/main/LICENSE.md
kind: workload
provides:
    - [email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/ca-certificates-java@20240118
    - deb/ca-certificates@20250419
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/iputils-ping@20240905
    - deb/[email protected]
    - deb/[email protected]
    - deb/less@668
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
capabilities:
    - type: com.docker.sandbox/network-policy@1
      config:
        runtime:
            allow:
                - api.anthropic.com:443
                - platform.claude.com:443
                - downloads.claude.ai:443
                - claude.com:443
                - mcp-proxy.anthropic.com:443
                - bridge.claudeusercontent.com:443
                - api.github.com
    - type: com.docker.sandbox/sbx@1
    - type: com.docker.sandbox/credential@1
      name: Anthropic access
      optional: true
      config:
        apiKey:
            inject:
                - domain: api.anthropic.com
                  format: '%s'
                  header: x-api-key
                - domain: mcp-proxy.anthropic.com
                  format: '%s'
                  header: x-api-key
            name: ANTHROPIC_API_KEY
        oauth:
            credentialFile:
                path: ~/.claude/.credentials.json
                structure:
                    claudeAiOauth:
                        accessToken: '{{.AccessToken}}'
                        expiresAt: '{{.ExpiresAt}}'
                        refreshToken: '{{.RefreshToken}}'
                        scopes: '{{.Scopes}}'
                    primaryApiKey: '{{.PrimaryApiKey}}'
            sentinels:
                accessToken: sk-ant-oat01-proxy-managed
                refreshToken: sk-ant-ort01-proxy-managed
            tokenEndpoint:
                host: platform.claude.com
                path: /v1/oauth/token
        phase: runtime
        service: anthropic
      description: Anthropic API access (API key or claude.ai OAuth)
    - type: com.docker.sandbox/agent-interactive-sessions@1
      optional: true
      config:
        continue:
            - --continue
        prompt:
            - --
            - '{{.Prompt}}'
        resume:
            - --resume
            - '{{.SessionID}}'
        sessionPicker:
            - --resume
      description: Open claude's terminal UI on a chosen session
    - type: com.docker.sandbox/volume@1
      config:
        path: /home/agent/.claude/projects
        size: 2g
      description: Conversation history; grows without bound, gets the headroom
    - type: com.docker.sandbox/volume@1
      config:
        path: /home/agent/.claude/sessions
        size: 512m
      description: Per-session state; load-bearing for `claude -c`
    - type: com.docker.sandbox/volume@1
      config:
        path: /home/agent/.claude/todos
        size: 512m
      description: TodoWrite state
    - type: com.docker.sandbox/volume@1
      config:
        path: /home/agent/.claude/shell-snapshots
        size: 512m
      description: Bash state snapshots across sessions
    - type: com.docker.sandbox/volume@1
      config:
        path: /home/agent/.claude/statsig
        size: 512m
      description: Local feature-flag cache
    - type: com.docker.sandbox/agent-skills@1
      optional: true
      config:
        path: /home/agent/.claude/skills
    - type: com.docker.sandbox/ssh-agent@1
      optional: true
      config:
        phase: runtime
        sign:
            - git
        unrestricted: false
      description: Sign git commits and tags with the host's SSH key
    - type: com.docker.sandbox/git-identity@1
      optional: true
      description: Attribute commits to the host's git identity
    - type: com.docker.sandbox/agent-sessions@1
      config:
        continue:
            - --continue
        list:
            - node
            - /opt/claude-sessions/interactive-sessions.mjs
        prompt:
            - -p
            - --
            - '{{.Prompt}}'
        resume:
            - --resume
            - '{{.SessionID}}'
      description: Drive claude sessions programmatically
    - type: com.docker.sandbox/lifecycle@1
      config:
        install:
            - command:
                - sh
                - -c
                - |
                  set -e
                  ws="${WORKSPACE_DIR:-/}"
                  esc=$(printf '%s' "$ws" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g; s/\r/\\r/g')
                  projects="\"/\": { \"hasTrustDialogAccepted\": true }"
                  [ "$ws" = "/" ] || projects="$projects, \"$esc\": { \"hasTrustDialogAccepted\": true }"
                  printf '%s\n' "{
                    \"bypassPermissionsModeAccepted\": true,
                    \"hasCompletedOnboarding\": true,
                    \"projects\": { $projects }
                  }" > /home/agent/.claude.json
                  chown agent:agent /home/agent/.claude.json
              description: Seed Claude bypass/trust flags (root; overwrites image-shipped file)
              env:
                - WORKSPACE_DIR
              user: "0"
            - command:
                - sh
                - -c
                - mkdir -p /home/agent/.claude && chown agent:agent /home/agent/.claude
              description: Ensure ~/.claude is agent-owned before settings seed
              user: "0"
            - command:
                - sh
                - -c
                - |
                  set -e
                  HELPER=''
                  if [ "${SBX_CRED_ANTHROPIC_MODE:-none}" != none ]; then
                    HELPER='  "apiKeyHelper": "echo proxy-managed",
                  '
                  fi
                  # Model selection from the create-phase args. The args'
                  # patterns admit no quote or backslash, so the expanded
                  # value is safe inside the JSON string. effortLevel accepts
                  # low/medium/high/xhigh; max and auto persist only through
                  # CLAUDE_CODE_EFFORT_LEVEL (settings.json rejects them).
                  model=''
                  effort=''
                  MODEL=''
                  EFFORT=''
                  ENV_BLOCK=''
                  [ -z "$model" ] || MODEL="  \"model\": \"$model\",
                  "
                  case "$effort" in
                    '') ;;
                    max|auto)
                      ENV_BLOCK="  \"env\": { \"CLAUDE_CODE_EFFORT_LEVEL\": \"$effort\" },
                  "
                      ;;
                    *)
                      EFFORT="  \"effortLevel\": \"$effort\",
                  "
                      ;;
                  esac
                  # Lifecycle hooks for sbx Desktop (see /usr/local/bin/sbx-claude-hook):
                  # Stop and StopFailure report a finished turn, Notification the
                  # moments Claude waits on the user, UserPromptSubmit the prompt
                  # that names the conversation (Claude Code lists sessions by id
                  # only). The script never fails, never writes stdout and runs
                  # async, so a session without the desktop app sees no delay and
                  # no hook error.
                  HOOK='{ "type": "command", "command": "/usr/local/bin/sbx-claude-hook claude", "timeout": 10, "async": true }'
                  HOOKS="  \"hooks\": {
                      \"Stop\": [ { \"hooks\": [ $HOOK ] } ],
                      \"StopFailure\": [ { \"hooks\": [ $HOOK ] } ],
                      \"UserPromptSubmit\": [ { \"hooks\": [ $HOOK ] } ],
                      \"Notification\": [ { \"matcher\": \"permission_prompt|idle_prompt|elicitation_dialog|elicitation_url_dialog|agent_needs_input\", \"hooks\": [ $HOOK ] } ]
                    },
                  "
                  # The statusLine command is the only place Claude Code exposes
                  # the live session (model, context window, cost, lines changed);
                  # sbx-agent-hook forwards it to sbx Desktop's status bar and prints
                  # nothing, so no status line is drawn in the terminal. A mixin that
                  # sets its own statusLine (e.g. claude-sbx-statusline) replaces
                  # this one and the app's session view goes quiet for that sandbox.
                  STATUSLINE="  \"statusLine\": { \"type\": \"command\", \"command\": \"/usr/local/bin/sbx-claude-hook claude-status\" },
                  "
                  printf '%s' "{
                    \"themeId\": 1,
                    \"alwaysThinkingEnabled\": true,
                  ${HELPER}${MODEL}${EFFORT}${ENV_BLOCK}${HOOKS}${STATUSLINE}  \"permissions\": { \"defaultMode\": \"bypassPermissions\" },
                    \"bypassPermissionsModeAccepted\": true,
                    \"skipDangerousModePermissionPrompt\": true
                  }
                  " > /home/agent/.claude/settings.json
              description: Seed Claude settings.json from the surfaced auth mode
              env:
                - SBX_CRED_ANTHROPIC_MODE
              user: agent
            - command:
                - sh
                - -c
                - |
                  set -e
                  [ -n "$MCP_GATEWAY_URL" ] || exit 0
                  export PATH="$HOME/.local/bin:$HOME/.claude/local:$PATH"
                  claude mcp add mcp-gateway "$MCP_GATEWAY_URL" \
                    --transport http \
                    --scope user \
                    --header "Authorization: Bearer $MCP_SENTINEL_TOKEN_NAME" || true
              description: Register the sandbox MCP gateway (install-time, race-free)
              env:
                - MCP_GATEWAY_URL
                - MCP_SENTINEL_TOKEN_NAME
              user: agent
            - command:
                - sh
                - -c
                - |
                  set -e
                  mkdir -p /home/agent/.claude
                  f=/home/agent/.claude/settings.json
                  [ -f "$f" ] || echo '{}' > "$f"
                  # Set only the statusLine key (any existing one is replaced by design);
                  # the jq merge leaves all other settings untouched. Temp file lives in the
                  # same dir as $f so the mv below is an atomic rename, not a cross-fs copy.
                  tmp=$(mktemp -p /home/agent/.claude)
                  jq '.statusLine = {type: "command", command: "~/.claude/statusline.sh"}' "$f" > "$tmp"
                  mv "$tmp" "$f"
                  # Shipped files arrive 0644; unexecutable, it renders nothing and no error.
                  chmod +x /home/agent/.claude/statusline.sh
                  # Enumerated, not recursive: ~/.claude holds runtime-managed content
                  # this kit doesn't own, so `chown -R` on the parent would take
                  # ownership of paths outside the kit's control.
                  chown agent:agent /home/agent/.claude "$f" /home/agent/.claude/statusline.sh
              description: Set the statusLine key in ~/.claude/settings.json to ~/.claude/statusline.sh (jq merge, so all other keys are preserved; any existing statusLine is replaced by design) and make the script executable
              user: "0"
            - command:
                - sh
                - -c
                - |
                  set -e

                  # Signing *machinery* stays machine-wide: it is inert unless something
                  # asks for a signature, and keeping it here means `git commit -S` works
                  # in any repository in the sandbox.
                  git config --system gpg.format ssh
                  # The key command is invoked through /bin/sh rather than executed
                  # directly. Files shipped under a kit's files/home/ tree land mode
                  # 0644 when the kit is installed from its OCI artifact -- per-file
                  # executable bits are not representable in a v2 layer (spec/OCI-v2.md)
                  # -- and git execs this value itself, so a bare path would die with
                  # "cannot exec: Permission denied" before a single one of the script's
                  # own diagnostics could run.
                  git config --system gpg.ssh.defaultKeyCommand '/bin/sh /home/agent/.config/git/ssh-signing-key-command'
                  git config --system gpg.ssh.allowedSignersFile /home/agent/.config/git/allowed_signers

                  # user.signingKey MUST stay unset: git only runs
                  # gpg.ssh.defaultKeyCommand when it is empty. Setting it to any value
                  # (even a placeholder) disables dynamic key resolution entirely.
                  git config --system --unset-all user.signingKey || true

                  # Signing *policy* is scoped, not machine-wide. Setting
                  # commit.gpgSign=true in /etc/gitconfig makes every `git commit` in the
                  # sandbox depend on a live SSH agent — including throwaway repositories
                  # created by test suites that have nothing to do with the user's work.
                  # When the forwarded agent goes away, those all fail too.
                  mkdir -p /etc/git
                  cat > /etc/git/signing-enabled.inc <<'INC'
                  # Included by /etc/gitconfig for repositories with a remote.
                  # See the git-ssh-sign kit.
                  [commit]
                  	gpgSign = true
                  [tag]
                  	gpgSign = true
                  INC
                  chmod 0644 /etc/git/signing-enabled.inc

                  # Clear anything an older version of this kit left machine-wide, so a
                  # re-install converges rather than layering.
                  git config --system --unset-all commit.gpgSign || true
                  git config --system --unset-all tag.gpgSign || true
                  git config --system --unset-all 'includeIf.hasconfig:remote.*.url:**.path' || true

                  # `includeIf "hasconfig:remote.*.url:**"` needs git >= 2.36. Probe for
                  # it rather than parsing a version string: build a throwaway repo with
                  # a remote and see whether the include actually fires. Note that `**`
                  # is only a cross-slash wildcard when it is a whole path component --
                  # `[email protected]:**` does NOT match `[email protected]:org/repo.git`, so
                  # a bare `**` ("has any remote at all") is the pattern to use here.
                  probe=$(mktemp -d)
                  git init -q "$probe"
                  git -C "$probe" remote add origin https://example.invalid/probe.git
                  printf '[commit]\n\tgpgSign = true\n' > "$probe/inc"
                  printf '[includeIf "hasconfig:remote.*.url:**"]\n\tpath = %s/inc\n' "$probe" > "$probe/sys"
                  supported=$(GIT_CONFIG_SYSTEM="$probe/sys" GIT_CONFIG_GLOBAL=/dev/null \
                      git -C "$probe" config --get commit.gpgSign 2>/dev/null || true)
                  rm -rf "$probe"

                  if [ "$supported" = "true" ]; then
                      git config --system 'includeIf.hasconfig:remote.*.url:**.path' /etc/git/signing-enabled.inc
                  else
                      # Old git: an unrecognised includeIf keyword evaluates false, which
                      # would silently disable signing. Fail closed (sign everywhere)
                      # rather than fail open (sign nothing).
                      echo "[git-ssh-sign] git $(git --version | awk '{print $3}') lacks includeIf hasconfig; enabling signing machine-wide" >&2
                      git config --system commit.gpgSign true
                      git config --system tag.gpgSign true
                  fi

                  if [ "$(git config --system --get core.hooksPath || true)" = "/home/agent/.config/git/hooks" ]; then
                      git config --system --unset-all core.hooksPath
                  fi
              description: Configure SSH commit signing, scoped to repositories with a remote
              user: "0"
        startup:
            - command:
                - sh
                - -c
                - chown -R agent:agent /home/agent/.claude/projects /home/agent/.claude/sessions /home/agent/.claude/todos /home/agent/.claude/shell-snapshots /home/agent/.claude/statsig 2>/dev/null || true
              description: Re-own claude session-state volume mount roots to agent
              user: "0"
            - background: true
              command:
                - sh
                - -c
                - command -v apt-get > /dev/null 2>&1 && (apt-get update -qq -y > /dev/null 2>&1 || true)
              description: Update apt package cache in background
              user: "0"
            - command:
                - sh
                - -c
                - |
                  set -e
                  [ -n "$MCP_GATEWAY_URL" ] || exit 0
                  export PATH="$HOME/.local/bin:$HOME/.claude/local:$PATH"
                  claude mcp add mcp-gateway "$MCP_GATEWAY_URL" \
                    --transport http \
                    --scope user \
                    --header "Authorization: Bearer $MCP_SENTINEL_TOKEN_NAME" || true
              description: Register the sandbox MCP gateway (startup fallback)
              env:
                - MCP_GATEWAY_URL
                - MCP_SENTINEL_TOKEN_NAME
              user: agent
    - type: com.docker.sandbox/agent-context@1
      config:
        contentFile: /usr/share/sandbox/kit/claude-extended/context.md
        directory: /home/agent/.claude
        filename: CLAUDE.md
kits:
    - ref: docker.io/docker/sbx-kit-claude:2.1.296
      digest: sha256:c0132e89a89d94ddca3984513afdb36be57bd087fcc75823a4d14064b6a39ea5
    - ref: docker.io/sbx/git-ssh-sign:1.0.0
      digest: sha256:6f5f54127eb6f2870c3fcca9c3d23997b71fb5cb6739ee02350c78cdefd104bc
    - ref: docker.io/sbx/claude-sbx-statusline:1.0.0
      digest: sha256:6885e276ef88d6a57d25c81214151072ac438b634d352e6f707445b91d76b9af