#!/usr/bin/env bash # # Set up shared agent state for agent-container. # # Moves agent state (Claude Code, Pi, OpenCode) from the real $HOME into the # container home and symlinks it back, so the containerized tools (claude, pi, # opencode) and the local variants (claude-local, pi-local, opencode-local) # share logins, settings, and history. See README.md, section "Sharing agent # state between host and container via symlinks". # # Safe to re-run: already shared items are detected and left alone. set -euo pipefail XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" CONTAINER_HOME="$XDG_DATA_HOME/agent-container/container-home" # State directories to share. Created in the container home (and linked into # $HOME) even if they don't exist yet, so both sides share from the start. DIRS=( .claude .pi .agents .config/opencode .local/share/opencode ) # Single files to share. Only linked when they exist on one side, tools create # them on first use. FILES=( .claude.json ) info() { printf ' %s\n' "$*"; } warn() { printf ' warning: %s\n' "$*" >&2; } # Print the action taken for an item, shared by both helpers below. _report() { local action="$1" item="$2" case "$action" in moved) info "moved $item into the container home, symlinked from \$HOME" ;; linked) info "linked $item (container home already had it)" ;; created) info "created $item in the container home, symlinked from \$HOME" ;; ok) info "ok $item (already shared)" ;; skip) info "skip $item (does not exist yet, the tool will create it)" ;; esac } share_item() { local item="$1" must_exist="$2" local host="$HOME/$item" target="$CONTAINER_HOME/$item" if [ -L "$host" ]; then case "$(readlink -f "$host")" in "$CONTAINER_HOME"/*) _report ok "$item" return ;; *) warn "$item is a symlink to $(readlink "$host"), not touching it" return ;; esac fi if [ -e "$host" ] && [ -e "$target" ]; then warn "$item exists in both \$HOME and the container home" warn "reconcile the two copies manually, then re-run this script" return fi if [ ! -e "$host" ] && [ ! -e "$target" ]; then if [ "$must_exist" = "yes" ]; then _report skip "$item" return fi mkdir -p "$target" _report created "$item" elif [ -e "$host" ]; then mkdir -p "$(dirname "$target")" mv "$host" "$target" _report moved "$item" else _report linked "$item" fi mkdir -p "$(dirname "$host")" ln -s "$target" "$host" } main() { printf 'Sharing agent state via %s\n\n' "$CONTAINER_HOME" local item for item in "${DIRS[@]}"; do share_item "$item" no; done for item in "${FILES[@]}"; do share_item "$item" yes; done if [ -f "$HOME/.gitconfig" ] && [ ! -e "$CONTAINER_HOME/.gitconfig" ]; then printf '\n' info "Tip: share your git config too (see README):" info " ln $HOME/.gitconfig $CONTAINER_HOME/.gitconfig" fi } main "$@"