#!/bin/bash # configure reads TITLE and DESCRIPTION # shellcheck disable=SC2034 TITLE="Agent sandbox" # shellcheck disable=SC2034 DESCRIPTION="Choose what agents may read, e.g. WinBoat's settings" # The sandbox config every sandboxed agent reads (see sandbox/agent) SANDBOX_CONF="$HOME/.config/coredesktop/sandbox/base.json" source "$COREDESKTOP/configure.d/lib/json.sh" # Folders the sandbox hides from agents (sandbox/config/base.json) that you # may let them read: "path|what it is". Your SSH keys, password stores, # browsers and the like aren't here; they're always hidden. A path in # allowRead can be read even inside one in denyRead, so letting agents read # one is adding it to allowRead in your own config. # The paths are written as in sandbox/config/base.json, with ~ for srt to expand # shellcheck disable=SC2088 OPTIONAL_HIDDEN=( "~/.winboat|WinBoat's settings, which include your Windows password" ) # Offered only when one of the folders is on this machine is_installed() { local entry path for entry in "${OPTIONAL_HIDDEN[@]}"; do path="${entry%%|*}" [ -e "${path/#\~/$HOME}" ] && return 0 done return 1 } # Hiding them is the default, so there's nothing you need to do is_configured() { true } # True if agents may read $1 (it's in your config's allowRead) readable() { jq -e --arg path "$1" '.filesystem.allowRead // [] | index($path)' "$SANDBOX_CONF" &> /dev/null } let_read() { edit_json "$SANDBOX_CONF" '{}' --arg path "$1" \ '.filesystem.allowRead = ((.filesystem.allowRead // []) - [$path] + [$path])' } hide() { [ -f "$SANDBOX_CONF" ] || return 0 edit_json "$SANDBOX_CONF" '{}' --arg path "$1" \ 'if .filesystem.allowRead then .filesystem.allowRead -= [$path] else . end' } run_configure() { local choice i path what state echo "Agents in the sandbox can't read these unless you let them. Changes apply the next" echo "time you start an agent (restart Hermes' gateway with: systemctl --user restart hermes-gateway)." echo "Claude Code's own sandbox doesn't use this list." while true; do echo for i in "${!OPTIONAL_HIDDEN[@]}"; do IFS='|' read -r path what <<< "${OPTIONAL_HIDDEN[$i]}" if readable "$path"; then state="\e[33magents can read it\e[0m"; else state="\e[32mhidden\e[0m"; fi printf " %d) %-12s $state %s\n" $((i + 1)) "$path" "$what" done echo " q) Done" echo read -rp "Choose one to switch: " choice || return 0 if ! [[ "$choice" =~ ^[0-9]+$ ]] || (( choice < 1 || choice > ${#OPTIONAL_HIDDEN[@]} )); then return 0 fi IFS='|' read -r path what <<< "${OPTIONAL_HIDDEN[$((choice - 1))]}" if readable "$path"; then hide "$path" || return 1 echo "$path is hidden from agents again." elif confirm "Let agents read $path ($what)?"; then let_read "$path" || return 1 echo "Agents can read $path." fi done }