From 512348477e8597e2a796ad68c37e271a48c36eb3 Mon Sep 17 00:00:00 2001 From: Tyrone Avnit Date: Fri, 13 Feb 2026 09:41:20 -0600 Subject: [PATCH] feat: add chrome config option for browser automation Add per-agent `chrome` boolean field (Anthropic only, default: true) that passes --chrome to Claude Code CLI, enabling browser automation via the Claude in Chrome extension. - Add `chrome?: boolean` to AgentConfig type - Pass `--chrome` flag when agent.chrome !== false - Set chrome: true on default Anthropic agents - Add Chrome prompt to setup wizard and agent add - Display Chrome status in agent list - Log chrome status on startup - Add --chrome to legacy messaging path Co-Authored-By: Claude Opus 4.6 --- lib/agents.sh | 60 +++++++++++++++++++++++++++++++++--------- lib/messaging.sh | 2 +- lib/setup-wizard.sh | 33 +++++++++++++++++++++-- src/lib/config.ts | 1 + src/lib/invoke.ts | 3 +++ src/lib/types.ts | 1 + src/queue-processor.ts | 3 ++- 7 files changed, 86 insertions(+), 17 deletions(-) diff --git a/lib/agents.sh b/lib/agents.sh index 36ec61a..a486730 100644 --- a/lib/agents.sh +++ b/lib/agents.sh @@ -28,10 +28,17 @@ agent_list() { echo "=================" echo "" - jq -r '(.agents // {}) | to_entries[] | "\(.key)|\(.value.name)|\(.value.provider)|\(.value.model)|\(.value.working_directory)"' "$SETTINGS_FILE" 2>/dev/null | \ - while IFS='|' read -r id name provider model workdir; do + jq -r '(.agents // {}) | to_entries[] | "\(.key)|\(.value.name)|\(.value.provider)|\(.value.model)|\(.value.working_directory)|\(.value.chrome // "null")"' "$SETTINGS_FILE" 2>/dev/null | \ + while IFS='|' read -r id name provider model workdir chrome; do echo -e " ${GREEN}@${id}${NC} - ${name}" echo " Provider: ${provider}/${model}" + if [ "$provider" = "anthropic" ]; then + if [ "$chrome" = "false" ]; then + echo " Chrome: disabled" + else + echo " Chrome: enabled" + fi + fi echo " Directory: ${workdir}" echo "" done @@ -135,6 +142,17 @@ agent_add() { esac fi + # Chrome browser automation (Anthropic only) + AGENT_CHROME="true" + if [ "$AGENT_PROVIDER" = "anthropic" ]; then + echo "" + read -rp "Enable Chrome browser automation? [Y/n]: " AGENT_CHROME_INPUT + if [[ "$AGENT_CHROME_INPUT" =~ ^[nN] ]]; then + AGENT_CHROME="false" + fi + echo -e "${GREEN}✓ Chrome: $AGENT_CHROME${NC}" + fi + # Working directory - automatically set to agent directory AGENT_WORKDIR="$AGENTS_DIR/$AGENT_ID" @@ -143,17 +161,33 @@ agent_add() { # Build the agent JSON object local agent_json - agent_json=$(jq -n \ - --arg name "$AGENT_NAME" \ - --arg provider "$AGENT_PROVIDER" \ - --arg model "$AGENT_MODEL" \ - --arg workdir "$AGENT_WORKDIR" \ - '{ - name: $name, - provider: $provider, - model: $model, - working_directory: $workdir - }') + if [ "$AGENT_PROVIDER" = "anthropic" ]; then + agent_json=$(jq -n \ + --arg name "$AGENT_NAME" \ + --arg provider "$AGENT_PROVIDER" \ + --arg model "$AGENT_MODEL" \ + --arg workdir "$AGENT_WORKDIR" \ + --argjson chrome "$AGENT_CHROME" \ + '{ + name: $name, + provider: $provider, + model: $model, + working_directory: $workdir, + chrome: $chrome + }') + else + agent_json=$(jq -n \ + --arg name "$AGENT_NAME" \ + --arg provider "$AGENT_PROVIDER" \ + --arg model "$AGENT_MODEL" \ + --arg workdir "$AGENT_WORKDIR" \ + '{ + name: $name, + provider: $provider, + model: $model, + working_directory: $workdir + }') + fi # Ensure agents section exists and add the new agent jq --arg id "$AGENT_ID" --argjson agent "$agent_json" \ diff --git a/lib/messaging.sh b/lib/messaging.sh index a36a894..04434f2 100644 --- a/lib/messaging.sh +++ b/lib/messaging.sh @@ -9,7 +9,7 @@ send_message() { log "[$source] Sending: ${message:0:50}..." cd "$SCRIPT_DIR" - RESPONSE=$(claude --dangerously-skip-permissions -c -p "$message" 2>&1) + RESPONSE=$(claude --dangerously-skip-permissions --chrome -c -p "$message" 2>&1) echo "$RESPONSE" diff --git a/lib/setup-wizard.sh b/lib/setup-wizard.sh index c7acfe2..a5640fa 100755 --- a/lib/setup-wizard.sh +++ b/lib/setup-wizard.sh @@ -137,6 +137,17 @@ else echo "" fi +# Chrome browser automation (Anthropic only) +CHROME_ENABLED="true" +if [ "$PROVIDER" = "anthropic" ]; then + read -rp "Enable Chrome browser automation? [Y/n]: " CHROME_INPUT + if [[ "$CHROME_INPUT" =~ ^[nN] ]]; then + CHROME_ENABLED="false" + fi + echo -e "${GREEN}✓ Chrome: $CHROME_ENABLED${NC}" + echo "" +fi + # Heartbeat interval echo "Heartbeat interval (seconds)?" echo -e "${YELLOW}(How often Claude checks in proactively)${NC}" @@ -190,7 +201,11 @@ DEFAULT_AGENT_DIR="$WORKSPACE_PATH/$DEFAULT_AGENT_NAME" # Capitalize first letter of agent name (proper bash method) DEFAULT_AGENT_DISPLAY="$(tr '[:lower:]' '[:upper:]' <<< "${DEFAULT_AGENT_NAME:0:1}")${DEFAULT_AGENT_NAME:1}" AGENTS_JSON='"agents": {' -AGENTS_JSON="$AGENTS_JSON \"$DEFAULT_AGENT_NAME\": { \"name\": \"$DEFAULT_AGENT_DISPLAY\", \"provider\": \"$PROVIDER\", \"model\": \"$MODEL\", \"working_directory\": \"$DEFAULT_AGENT_DIR\" }" +if [ "$PROVIDER" = "anthropic" ]; then + AGENTS_JSON="$AGENTS_JSON \"$DEFAULT_AGENT_NAME\": { \"name\": \"$DEFAULT_AGENT_DISPLAY\", \"provider\": \"$PROVIDER\", \"model\": \"$MODEL\", \"working_directory\": \"$DEFAULT_AGENT_DIR\", \"chrome\": $CHROME_ENABLED }" +else + AGENTS_JSON="$AGENTS_JSON \"$DEFAULT_AGENT_NAME\": { \"name\": \"$DEFAULT_AGENT_DISPLAY\", \"provider\": \"$PROVIDER\", \"model\": \"$MODEL\", \"working_directory\": \"$DEFAULT_AGENT_DIR\" }" +fi ADDITIONAL_AGENTS=() # Track additional agent IDs for directory creation @@ -241,7 +256,21 @@ if [[ "$SETUP_AGENTS" =~ ^[yY] ]]; then NEW_AGENT_DIR="$WORKSPACE_PATH/$NEW_AGENT_ID" - AGENTS_JSON="$AGENTS_JSON, \"$NEW_AGENT_ID\": { \"name\": \"$NEW_AGENT_NAME\", \"provider\": \"$NEW_PROVIDER\", \"model\": \"$NEW_MODEL\", \"working_directory\": \"$NEW_AGENT_DIR\" }" + # Chrome browser automation (Anthropic only) + NEW_CHROME_ENABLED="true" + if [ "$NEW_PROVIDER" = "anthropic" ]; then + read -rp " Enable Chrome browser automation? [Y/n]: " NEW_CHROME_INPUT + if [[ "$NEW_CHROME_INPUT" =~ ^[nN] ]]; then + NEW_CHROME_ENABLED="false" + fi + echo -e " ${GREEN}✓ Chrome: $NEW_CHROME_ENABLED${NC}" + fi + + if [ "$NEW_PROVIDER" = "anthropic" ]; then + AGENTS_JSON="$AGENTS_JSON, \"$NEW_AGENT_ID\": { \"name\": \"$NEW_AGENT_NAME\", \"provider\": \"$NEW_PROVIDER\", \"model\": \"$NEW_MODEL\", \"working_directory\": \"$NEW_AGENT_DIR\", \"chrome\": $NEW_CHROME_ENABLED }" + else + AGENTS_JSON="$AGENTS_JSON, \"$NEW_AGENT_ID\": { \"name\": \"$NEW_AGENT_NAME\", \"provider\": \"$NEW_PROVIDER\", \"model\": \"$NEW_MODEL\", \"working_directory\": \"$NEW_AGENT_DIR\" }" + fi # Track this agent for directory creation later ADDITIONAL_AGENTS+=("$NEW_AGENT_ID") diff --git a/src/lib/config.ts b/src/lib/config.ts index 65c5b99..ec63c70 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -60,6 +60,7 @@ export function getDefaultAgentFromModels(settings: Settings): AgentConfig { provider, model, working_directory: defaultAgentDir, + ...(provider === 'anthropic' ? { chrome: true } : {}), }; } diff --git a/src/lib/invoke.ts b/src/lib/invoke.ts index 471eaf2..427b367 100644 --- a/src/lib/invoke.ts +++ b/src/lib/invoke.ts @@ -124,6 +124,9 @@ export async function invokeAgent( const modelId = resolveClaudeModel(agent.model); const claudeArgs = ['--dangerously-skip-permissions']; + if (agent.chrome !== false) { + claudeArgs.push('--chrome'); + } if (modelId) { claudeArgs.push('--model', modelId); } diff --git a/src/lib/types.ts b/src/lib/types.ts index 1a20267..b4b1261 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -3,6 +3,7 @@ export interface AgentConfig { provider: string; // 'anthropic' or 'openai' model: string; // e.g. 'sonnet', 'opus', 'gpt-5.3-codex' working_directory: string; + chrome?: boolean; // Enable Chrome browser automation (Anthropic only, default: true) } export interface TeamConfig { diff --git a/src/queue-processor.ts b/src/queue-processor.ts index 1844d6a..eafc9a6 100644 --- a/src/queue-processor.ts +++ b/src/queue-processor.ts @@ -458,7 +458,8 @@ function logAgentConfig(): void { const agentCount = Object.keys(agents).length; log('INFO', `Loaded ${agentCount} agent(s):`); for (const [id, agent] of Object.entries(agents)) { - log('INFO', ` ${id}: ${agent.name} [${agent.provider}/${agent.model}] cwd=${agent.working_directory}`); + const chromeStatus = agent.provider === 'anthropic' ? ` chrome=${agent.chrome !== false}` : ''; + log('INFO', ` ${id}: ${agent.name} [${agent.provider}/${agent.model}]${chromeStatus} cwd=${agent.working_directory}`); } const teamCount = Object.keys(teams).length;