Skip to content

feat: improve workspace Claude Code configuration completeness #33

@subotic

Description

@subotic

Problem

After working through a full SIPI bugfix session in a LOOM workspace (sipi-sentry-crash-fixing), several configuration gaps became apparent. The generated .claude/settings.json was missing settings that had to be added manually or via settings.local.json during the session. This friction could be eliminated by extending LOOM's config and code generation.

Findings

What LOOM already handles well

  • additionalDirectories — auto-generated from manifest repos
  • enabledPlugins + extraKnownMarketplaces — fully configured
  • permissions.allow — gh, git, cargo, WebFetch rules
  • sandbox — enabled, auto_allow, excluded commands, filesystem, network
  • presets — the rust preset works well for Rust projects
  • model — emitted correctly when set in config.toml (verified on origin/main)

Gap 1: No preset for C++/Nix projects

The sipi repo needed these permissions that don't exist in any preset:

[agents.claude-code.presets.cpp-nix]
allowed_tools = [
    "Bash(nix develop:*)",
    "Bash(make nix-*)",
    "Bash(cmake *)",
    "Bash(gcc *)",
    "Bash(g++ *)",
    "Bash(ls:*)",
]

Fix: Add a cpp-nix preset to config.toml. No code changes needed — just config.

Gap 2: Skill permissions not pre-configured

The eng plugin skills (eng:workflows:plan, eng:workflows:work, eng:plan-review, eng:plan-deepen) had to be manually allowed via settings.local.json. These are used in virtually every workspace.

Fix: Add to global allowed_tools in config.toml:

"Skill(eng:workflows:plan)",
"Skill(eng:workflows:work)",
"Skill(eng:plan-review)",
"Skill(eng:plan-deepen)",

Gap 3: MCP tool permissions not pre-configured

Sentry and Linear MCP servers were connected mid-session. Their tool permissions had to be manually approved each time. If these MCP servers are always connected at the user level, the tool permissions should be pre-allowed.

Fix: Add to global allowed_tools:

# Sentry
"mcp__sentry__find_organizations",
"mcp__sentry__find_projects",
"mcp__sentry__search_issues",
"mcp__sentry__get_issue_details",
"mcp__sentry__search_events",
"mcp__sentry__get_issue_tag_values",
"mcp__sentry__analyze_issue_with_seer",
# Linear
"mcp__linear-server__list_teams",
"mcp__linear-server__save_issue",
"mcp__linear-server__list_issues",
"mcp__linear-server__get_issue",

Blocker: These are bare tool names without parentheses. The current validate_permission_entry() in config/mod.rs requires the ToolName(specifier) format and would reject them. The validator needs to be extended first (see Gap 4).

Gap 4: Permission validator rejects bare MCP tool names

validate_permission_entry() requires entries to match ToolName(specifier) format:

if !trimmed.ends_with(')') || !trimmed.contains('(') {
    anyhow::bail!("{context}: invalid format '{trimmed}' — expected ToolName(specifier)");
}

Bare MCP tool names like mcp__sentry__find_organizations don't have parentheses and would fail validation. Claude Code itself accepts them — the validator is too strict.

Fix: Allow entries that start with mcp__ to pass without requiring () specifiers. Something like:

// Bare MCP tool names are valid (e.g., "mcp__sentry__find_organizations")
if trimmed.starts_with("mcp__") && !trimmed.contains('(') {
    return Ok(());
}

Similarly, Skill(name) entries should also be accepted — the validator currently allows them since they have parentheses, but worth confirming.

Gap 5: No MCP server configuration generation

LOOM doesn't generate .mcp.json for the workspace. MCP servers (Sentry, Linear, Context7) had to be connected manually each session.

Possible future feature: A [agents.claude-code.mcp_servers] section in config.toml that generates a workspace-level .mcp.json. This is lower priority since MCP servers configured at the user level (~/.claude/) are inherited by all projects.

Gap 6: settings.local.json pattern

LOOM only generates settings.json. The settings.local.json (gitignored, user-specific overrides) was created manually. This is probably fine as-is — the .local pattern exists for per-session overrides that shouldn't be committed. But LOOM could document this pattern in the generated CLAUDE.md.

Proposed Changes

Quick wins (config.toml only — no code changes)

  1. Add Skill permissions to global allowed_tools
  2. Add cpp-nix preset

Code changes required

  1. Extend permission validator to accept bare MCP tool names (Gap 4)
    • mcp__* names without () specifiers should pass validation
    • Unblocks adding MCP tool permissions to config.toml (Gap 3)

Future / nice-to-have

  1. MCP server config generation (Gap 5)
  2. Document settings.local.json pattern in generated CLAUDE.md (Gap 6)

Context

This was discovered during the sipi-sentry-crash-fixing workspace where:

The session required ~8 manual permission approvals that could have been pre-configured.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions