computeAllowedClaudeToolsString generates the tool specification string for Claude's --allowed-tools flag. Why --allowed-tools instead of --tools (introduced in v2.0.31)? While --tools is simpler (e.g., "Bash,Edit,Read"), it lacks the fine-grained control gh-aw requires: - Specific bash commands: B
(tools map[string]any, safeOutputs *SafeOutputsConfig, cacheMemoryConfig *CacheMemoryConfig, mcpScripts *MCPScriptsConfig, sandboxConfig *SandboxConfig)
| 120 | // allowlist (unlike bypassPermissions which silently ignores it). |
| 121 | // Panics if callers pass a Claude-specific tools section instead of neutral tools. |
| 122 | func (e *ClaudeEngine) computeAllowedClaudeToolsString(tools map[string]any, safeOutputs *SafeOutputsConfig, cacheMemoryConfig *CacheMemoryConfig, mcpScripts *MCPScriptsConfig, sandboxConfig *SandboxConfig) string { |
| 123 | claudeToolsLog.Print("Computing allowed Claude tools string") |
| 124 | |
| 125 | tools = e.prepareClaudeToolsForAllowedList(tools) |
| 126 | allowedTools := collectClaudeAllowedTools(tools) |
| 127 | allowedTools = appendTopLevelClaudeTools(allowedTools, tools, cacheMemoryConfig) |
| 128 | allowedTools = appendSandboxWritableTools(allowedTools, sandboxConfig) |
| 129 | allowedTools = appendSafeOutputsTools(allowedTools, safeOutputs) |
| 130 | allowedTools = appendMCPScriptsTools(allowedTools, mcpScripts) |
| 131 | allowedTools = dedupeAllowedTools(allowedTools) |
| 132 | |
| 133 | // Sort the allowed tools alphabetically for consistent output |
| 134 | sort.Strings(allowedTools) |
| 135 | |
| 136 | claudeToolsLog.Printf("Generated allowed tools string with %d tools", len(allowedTools)) |
| 137 | |
| 138 | return strings.Join(allowedTools, ",") |
| 139 | } |
| 140 | |
| 141 | func (e *ClaudeEngine) prepareClaudeToolsForAllowedList(tools map[string]any) map[string]any { |
| 142 | if tools == nil { |