#!/usr/bin/env bash # GARC profile.sh — Multi-tenant profile management # # Profiles live at: ~/.garc/profiles// # config.env — tenant-specific env vars (GARC_DRIVE_FOLDER_ID, GARC_SHEETS_ID, ...) # token.json — OAuth token for this tenant # credentials.json — OAuth client credentials (optional; falls back to ~/.garc/credentials.json) # # Usage: # garc profile list List all profiles # garc profile use Switch active profile (sets GARC_PROFILE) # garc profile add Create a new profile directory # garc profile show [] Show profile config # garc profile remove Delete a profile # garc profile current Show current active profile GARC_PROFILES_DIR="${GARC_CONFIG:-${HOME}/.garc}/profiles" garc_profile() { local subcommand="${1:-list}" shift || true case "${subcommand}" in list) _profile_list ;; use) _profile_use "$@" ;; add) _profile_add "$@" ;; show) _profile_show "$@" ;; remove) _profile_remove "$@" ;; current) _profile_current ;; *) cat < Subcommands: list List all configured profiles use Print shell command to activate a profile add Create a new empty profile directory show [] Show the config for a profile (default: current) remove Delete a profile (prompts for confirmation) current Show the currently active profile name How to use: # Add profile-specific config to ~/.garc/profiles//config.env # Then activate with: eval "\$(garc profile use )" # Or export directly: export GARC_PROFILE= Profile config.env example: GARC_DRIVE_FOLDER_ID=1xxxxxx GARC_SHEETS_ID=1xxxxxx GARC_GMAIL_DEFAULT_TO=user@example.com GARC_DEFAULT_AGENT=main EOF return 1 ;; esac } _profile_list() { if [[ ! -d "${GARC_PROFILES_DIR}" ]]; then echo "No profiles configured. Create one with: garc profile add " return 0 fi local current="${GARC_PROFILE:-}" echo "Profiles (dir: ${GARC_PROFILES_DIR}):" echo "" local found=0 for dir in "${GARC_PROFILES_DIR}"/*/; do [[ -d "${dir}" ]] || continue local name name="$(basename "${dir}")" local marker="" [[ "${name}" == "${current}" ]] && marker=" ◀ active" local has_token="" [[ -f "${dir}/token.json" ]] && has_token=" [authenticated]" local has_config="" [[ -f "${dir}/config.env" ]] && has_config=" [configured]" echo " ${name}${marker}${has_token}${has_config}" found=1 done [[ ${found} -eq 0 ]] && echo " (none)" } _profile_current() { if [[ -n "${GARC_PROFILE:-}" ]]; then echo "${GARC_PROFILE}" else echo "(no profile active — using ~/.garc/config.env)" fi } _profile_use() { local name="${1:-}" if [[ -z "${name}" ]]; then echo "Usage: garc profile use " return 1 fi local profile_dir="${GARC_PROFILES_DIR}/${name}" if [[ ! -d "${profile_dir}" ]]; then echo "Profile '${name}' not found. Create it with: garc profile add ${name}" return 1 fi # Output shell export commands so caller can eval them echo "export GARC_PROFILE=${name}" if [[ -f "${profile_dir}/config.env" ]]; then # Read each line and export while IFS= read -r line || [[ -n "${line}" ]]; do # Skip comments and empty lines [[ "${line}" =~ ^[[:space:]]*# ]] && continue [[ -z "${line// }" ]] && continue echo "export ${line}" done < "${profile_dir}/config.env" fi if [[ -f "${profile_dir}/token.json" ]]; then echo "export GARC_TOKEN_FILE=${profile_dir}/token.json" fi if [[ -f "${profile_dir}/credentials.json" ]]; then echo "export GARC_CREDENTIALS_FILE=${profile_dir}/credentials.json" fi # Print hint to stderr so it doesn't get eval'd echo "# Activated profile: ${name}" >&2 echo "# Run: eval \"\$(garc profile use ${name})\"" >&2 } _profile_add() { local name="${1:-}" if [[ -z "${name}" ]]; then echo "Usage: garc profile add " return 1 fi local profile_dir="${GARC_PROFILES_DIR}/${name}" if [[ -d "${profile_dir}" ]]; then echo "Profile '${name}' already exists: ${profile_dir}" return 0 fi mkdir -p "${profile_dir}" cat > "${profile_dir}/config.env" <" echo " (or set GARC_PROFILE to use current profile)" return 1 fi local profile_dir="${GARC_PROFILES_DIR}/${name}" if [[ ! -d "${profile_dir}" ]]; then echo "Profile '${name}' not found." return 1 fi echo "Profile: ${name}" echo "Path: ${profile_dir}" echo "" if [[ -f "${profile_dir}/config.env" ]]; then echo "config.env:" grep -v '^#' "${profile_dir}/config.env" | grep -v '^[[:space:]]*$' \ | sed 's/^/ /' else echo " (no config.env)" fi echo "" echo "Files:" [[ -f "${profile_dir}/token.json" ]] && echo " ✅ token.json (authenticated)" || echo " ⬜ token.json (not authenticated)" [[ -f "${profile_dir}/credentials.json" ]] && echo " ✅ credentials.json" || echo " ⬜ credentials.json (using default)" [[ -f "${profile_dir}/service_account.json" ]] && echo " ✅ service_account.json" } _profile_remove() { local name="${1:-}" if [[ -z "${name}" ]]; then echo "Usage: garc profile remove " return 1 fi local profile_dir="${GARC_PROFILES_DIR}/${name}" if [[ ! -d "${profile_dir}" ]]; then echo "Profile '${name}' not found." return 1 fi echo "Remove profile '${name}'? This deletes: ${profile_dir} [y/N]" read -r confirm [[ "${confirm}" != "y" ]] && echo "Cancelled." && return 0 rm -rf "${profile_dir}" echo "✅ Profile '${name}' removed." }