Various fixes for claude-sandbox -> dejima

This commit is contained in:
2026-07-27 16:45:17 -07:00
parent 889e51f10d
commit a53f854095
7 changed files with 48 additions and 29 deletions
-6
View File
@@ -1,6 +0,0 @@
# The claude-sandbox build context is this whole repo (so it can COPY
# bin/gitea-pr into the image), but it only needs a couple of paths from it.
**
!bin/gitea-pr
!docker/claude-sandbox/**
!config/nvim/**
+18 -13
View File
@@ -39,6 +39,17 @@ function require_token() {
fi
}
# Feeds the auth header to curl as a config on stdin rather than as an
# argument. Command lines are world-readable through /proc, so `-H
# "Authorization: token $GITEA_TOKEN"` exposes the token to every other
# process on the host for as long as the request runs - and to anything that
# scrapes `ps` output, including the agents this repo exists to sandbox.
# printf is a bash builtin, so the token never lands in another argv.
function gitea_api() {
printf 'header = "Authorization: token %s"\n' "$GITEA_TOKEN" |
curl -sS -w '\n%{http_code}' -K - "$@"
}
function gitea_owner_repo() {
local remote_url host owner_repo
remote_url=$(git remote get-url origin 2>/dev/null) || {
@@ -104,8 +115,7 @@ ${body}"
base="${base:-main}"
fi
response=$(curl -sS -w '\n%{http_code}' "${GITEA_API}/repos/${owner}/${repo}/pulls?state=open" \
-H "Authorization: token ${GITEA_TOKEN}")
response=$(gitea_api "${GITEA_API}/repos/${owner}/${repo}/pulls?state=open")
http_code=$(echo "$response" | tail -1)
json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
@@ -123,8 +133,7 @@ ${body}"
title="$current_branch"
fi
response=$(curl -sS -w '\n%{http_code}' -X POST "${GITEA_API}/repos/${owner}/${repo}/pulls" \
-H "Authorization: token ${GITEA_TOKEN}" \
response=$(gitea_api -X POST "${GITEA_API}/repos/${owner}/${repo}/pulls" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg head "$current_branch" --arg base "$base" --arg title "$title" --arg body "$body" \
'{head: $head, base: $base, title: $title, body: $body}')")
@@ -146,8 +155,7 @@ ${body}"
fi
echo "=== Issue comments ==="
response=$(curl -sS -w '\n%{http_code}' "${GITEA_API}/repos/${owner}/${repo}/issues/${pr_number}/comments" \
-H "Authorization: token ${GITEA_TOKEN}")
response=$(gitea_api "${GITEA_API}/repos/${owner}/${repo}/issues/${pr_number}/comments")
http_code=$(echo "$response" | tail -1)
json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
@@ -158,8 +166,7 @@ ${body}"
echo "$json" | jq -r '.[] | "[\(.user.login) @ \(.created_at)]\n\(.body)\n"'
echo "=== Reviews ==="
response=$(curl -sS -w '\n%{http_code}' "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/reviews" \
-H "Authorization: token ${GITEA_TOKEN}")
response=$(gitea_api "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/reviews")
http_code=$(echo "$response" | tail -1)
reviews_json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
@@ -172,9 +179,8 @@ ${body}"
echo "=== Inline review comments ==="
review_ids=$(echo "$reviews_json" | jq -r '.[] | select(.comments_count > 0) | .id')
for review_id in $review_ids; do
response=$(curl -sS -w '\n%{http_code}' \
"${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/reviews/${review_id}/comments" \
-H "Authorization: token ${GITEA_TOKEN}")
response=$(gitea_api \
"${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/reviews/${review_id}/comments")
http_code=$(echo "$response" | tail -1)
json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
@@ -192,8 +198,7 @@ ${body}"
exit 1
fi
response=$(curl -sS -w '\n%{http_code}' -X POST "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/merge" \
-H "Authorization: token ${GITEA_TOKEN}" \
response=$(gitea_api -X POST "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/merge" \
-H "Content-Type: application/json" \
-d '{"Do": "merge"}')
http_code=$(echo "$response" | tail -1)
+19
View File
@@ -10,6 +10,25 @@ PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1
FIVE_H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
# Claude Code omits rate_limits when ANTHROPIC_BASE_URL isn't the literal
# api.anthropic.com host (e.g. the dejima sandbox's credential-injecting
# loopback proxy), even though the usage endpoint itself works fine through
# it. Fetch it ourselves in that case, cached briefly to avoid a network
# round-trip on every render.
if [ -z "$FIVE_H" ] && [ -n "${ANTHROPIC_BASE_URL:-}" ] && [ -n "${ANTHROPIC_AUTH_TOKEN:-}" ]; then
CACHE="${TMPDIR:-/tmp}/claude-statusline-usage-${UID}.json"
if [ ! -s "$CACHE" ] || [ -n "$(find "$CACHE" -mmin +1 2>/dev/null)" ]; then
if curl -fsS --max-time 3 "$ANTHROPIC_BASE_URL/api/oauth/usage" \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
-H "anthropic-beta: oauth-2025-04-20" \
-o "$CACHE.tmp" 2>/dev/null; then
mv "$CACHE.tmp" "$CACHE"
fi
fi
FIVE_H=$(jq -r '.five_hour.utilization // empty' "$CACHE" 2>/dev/null)
WEEK=$(jq -r '.seven_day.utilization // empty' "$CACHE" 2>/dev/null)
fi
GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; RESET='\033[0m'
if [ "$PCT" -ge 90 ]; then BAR_COLOR="$RED"
+5 -5
View File
@@ -33,14 +33,14 @@ vim.api.nvim_create_autocmd({ "BufNewFile", "BufReadPre", "FileReadPre", "BufEnt
end,
})
-- claude-sandbox (docker/claude-sandbox) sets CLAUDE_SANDBOX, never present
-- on a normal host session, so this only fires inside the sandbox: open
-- claudecode.nvim's terminal on startup rather than requiring <leader>ac,
-- since starting a Claude session is the entire point of being in there.
-- dejima sets DEJIMA, never present on a normal host session, so this only
-- fires inside the sandbox: open claudecode.nvim's terminal on startup
-- rather than requiring <leader>ac, since starting a Claude session is the
-- entire point of being in there.
-- :ClaudeCode is defined by the plugin itself, so it doesn't exist until
-- claudecode.nvim has actually loaded - it's lazy-loaded on the <leader>ac
-- keymap only (no `cmd` in its lazy.nvim spec), so force that load first.
if vim.env.CLAUDE_SANDBOX then
if vim.env.DEJIMA then
vim.api.nvim_create_autocmd("VimEnter", {
once = true,
callback = function()
+1 -1
View File
@@ -74,7 +74,7 @@ opt.shortmess:append("c")
-- reply, so use the terminal's own native paste (e.g. Ctrl-Shift-V)
-- instead. Guarded on executable() rather than assumed present - not every
-- machine this config runs on has the rest of dotfiles checked out too
-- (e.g. claude-sandbox mounts in only this nvim config directory), and
-- (e.g. dejima mounts in only this nvim config directory), and
-- without the guard vim.g.clipboard would point at a script that isn't
-- there, erroring on every yank instead of just falling back to nvim's
-- default clipboard handling.
+2 -2
View File
@@ -122,9 +122,9 @@ if program_installed i3; then
export QT_QPA_PLATFORMTHEME="qt5ct"
fi
# Extra domains claude-sandbox's firewall should allow beyond its defaults
# Extra domains dejima's firewall should allow beyond its defaults
export ALLOWED_DOMAINS=""
# Gitea host, used by bin/gitea-pr and claude-sandbox's git-push-guard hook
# Gitea host, used by bin/gitea-pr and dejima's git-push-guard hook
export GITEA_SSH_HOST="gitbox.bradina.localdomain"
export GITEA_API="https://gitbox.branderson.io/api/v1"
+3 -2
View File
@@ -134,11 +134,12 @@ xfce4
picom.conf
picom-extended.conf
libinput-gestures.conf
dejima
"
# Files and directories under ~/.claude
# Whole-item symlinks for anything directly under claude/ that isn't itself
# a shared directory another tool also drops files into (hooks/ is handled
# separately below, per-file, since a standalone claude-sandbox install
# separately below, per-file, since a standalone dejima install
# also symlinks into ~/.claude/hooks).
claude_configs="
statusline.sh
@@ -298,7 +299,7 @@ function link_dotfiles {
ln -s $config_dir/claude/CLAUDE.md $HOME/.claude/CLAUDE.md
fi
# ~/.claude/hooks is a real directory, not a single symlink: other
# installs (e.g. a standalone claude-sandbox checkout) also drop
# installs (e.g. a standalone dejima checkout) also drop
# their own hook files in there, so dotfiles only ever links its own
# individual files into it, never claims the whole directory.
mkdir -p "$HOME/.claude/hooks"