Sessions started for implementation work should carry IW_METALS=1 #799
Labels
No labels
agent-ready
bug
contract
documentation
duplicate
enhancement
good first issue
help wanted
invalid
needs-human
needs-input
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
iterative-works/iw-cli#799
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The Metals MCP launcher on this machine now starts Metals only when IW_METALS=1 is in the environment that starts Claude Code. The default is off. iw-cli is the component that knows when a session is implementation work, so it is the right place to set it.
WHY THE GATE EXISTS
Measured over the 14 days to 2026-10-01, across both Claude config trees: of 382 sessions where a Metals tool became available, 86 called it and 296 did not. Each of those 296 paid for a Metals JVM of about 1 GB plus a build-server child beside it.
On 2026-10-15, 18 Metals JVMs and their build-server children held 40.7 GB across 44 processes, on a 128 GB box with 3.3 GB of RAM free and 74 GB in swap. Nothing is shared: every session gets its own Metals JVM and its own BSP/Bloop/Mill daemon, so three sessions in one repository pay three times over for the same build. Subagents inherit the parent session's connection rather than opening their own.
The launcher's only test used to be whether the directory holds build.sbt, build.mill or build.sc. A build file says what the PROJECT is. It never says whether THIS session will ask Metals anything, and that is the question that decides the cost.
Of the 86 sessions that did call Metals, 84 used a build tool (compile-module, compile-file, compile-full, test, format-file, list-modules) and only 26 touched a search tool. So the sessions worth paying for are the ones that compile.
WHAT IS ASKED
A session that iw-cli launches for implementation work should carry IW_METALS=1 in its environment. The obvious candidates:
iw start <ISSUE-ID>andiw open <key>, where the SessionAction hook launches a workflow session in a worktreebatch-implementspawns, which are exactly the compiling onesA session opened for triage, analysis, review reading or a docs edit does not need it and should not carry it.
There is precedent for iw-cli composing a session environment deliberately: loop sessions already start with an allow-listed environment, and batch-implement already drops IW_CORE_JAR, JAVA_OPTS, JDK_JAVA_OPTIONS and XDG_CACHE_HOME from its children on purpose. This is the same kind of decision in the other direction.
A design note rather than a requirement: a per-repository switch in .iw/config.conf would let a Scala repository opt in while leaving non-Scala repositories untouched, which keeps the flag from becoming unconditional. Whether that is worth the configuration surface is your call.
WHAT HAPPENS UNTIL THEN
Metals starts nowhere unless the variable is exported by hand (
IW_METALS=1 claude, or an export in a repository's .envrc). That is the intended default and it is deliberate, but it means the 84 sessions a fortnight that compile through Metals currently lose it unless the operator remembers. That is the gap this issue closes.The launcher lives outside iw-cli, in a home-manager service, so no iw-cli change is required for the gate itself - only for setting the variable on the sessions iw-cli starts.
Type: feature
Filed from:
/home/mph/ops/kanon-DEVDOCS-293on branchdrop-zgIntake: needs-input
1. Do we move this issue to the dev-docs repository, where the code that starts these sessions is?
The issue says that iw-cli starts the implementation sessions. It does not. In iw-cli,
iw startandiw openonly run whichever session command a plugin hook gives them, andrg IW_METALSfinds nothing in iw-cli. Theclaudecommand line comes from the kanon plugin hook:(claude-session.hook-start.scala#L16). The
batch-implementchild environment, including the list of variables it removes, is also in the plugin (BatchImplementation.scala#L142-L160).ClaudeEnvironmentsetIW_METALS=1, and iw-cli does not change. Close IW-799 here..iw/config.conf(for examplemetals = true) that the plugin reads. A second issue in dev-docs sets the variable. This adds configuration surface across two repositories.Recommended: a) — this changes the least: the two edits go in the code that starts the sessions, and no new configuration or contract is needed.
Answer in a comment on this issue, per number, for example "1: a", or in your own words; intake reads it on its next iteration.