@@ -25,3 +25,127 @@ is not set outside of SessionStart context.
2525- [ ] Tests passing — ` mvn -f client/pom.xml verify -e ` exits 0
2626- [ ] No regressions in existing functionality
2727- [ ] E2E: Invoke a CLI tool (e.g., ` get-status-output ` ) and confirm it no longer requires ` CLAUDE_ENV_FILE ` to be set
28+
29+ ## Research Findings
30+
31+ ### Current Architecture
32+
33+ The ` getEnvFile() ` method exists in two parallel interface hierarchies:
34+ - ` ClaudeTool ` (for CLI tools) → ` AbstractClaudeTool ` (stores ` envFile ` field) → ` MainClaudeTool ` (reads env var at
35+ construction)
36+ - ` ClaudeHook ` (for hook handlers) → ` AbstractClaudeHook ` (declares abstract) → ` MainClaudeHook ` (reads env var
37+ on-demand)
38+
39+ Neither ` JvmScope ` (the base interface) defines ` getEnvFile() ` — it's specific to ` ClaudeTool ` and ` ClaudeHook ` .
40+
41+ ### Single Real Consumer
42+
43+ Only ` InjectEnv.java ` (line 68) calls ` scope.getEnvFile() ` . It uses the path to write environment variable export
44+ statements for subsequent Bash tool invocations. ` InjectEnv ` receives a ` ClaudeTool ` scope, so it can simply call
45+ ` System.getenv("CLAUDE_ENV_FILE") ` directly instead of going through the scope.
46+
47+ ### Files to Modify
48+
49+ | File | Change |
50+ | ------| --------|
51+ | ` client/src/main/java/io/github/cowwoc/cat/hooks/ClaudeTool.java ` | Remove ` getEnvFile() ` method declaration |
52+ | ` client/src/main/java/io/github/cowwoc/cat/hooks/ClaudeHook.java ` | Remove ` getEnvFile() ` method declaration |
53+ | ` client/src/main/java/io/github/cowwoc/cat/hooks/AbstractClaudeTool.java ` | Remove ` envFile ` field, constructor param, ` getEnvFile() ` impl |
54+ | ` client/src/main/java/io/github/cowwoc/cat/hooks/AbstractClaudeHook.java ` | Remove abstract ` getEnvFile() ` declaration |
55+ | ` client/src/main/java/io/github/cowwoc/cat/hooks/MainClaudeTool.java ` | Remove ` CLAUDE_ENV_FILE ` from constructor |
56+ | ` client/src/main/java/io/github/cowwoc/cat/hooks/MainClaudeHook.java ` | Remove ` getEnvFile() ` implementation |
57+ | ` client/src/main/java/io/github/cowwoc/cat/hooks/session/InjectEnv.java ` | Read ` CLAUDE_ENV_FILE ` via ` System.getenv() ` directly |
58+ | ` client/src/test/java/io/github/cowwoc/cat/hooks/test/TestClaudeTool.java ` | Remove envFile constructor params and ` withEnvFile() ` factory |
59+ | ` client/src/test/java/io/github/cowwoc/cat/hooks/test/TestClaudeHook.java ` | Remove ` getEnvFile() ` implementation |
60+ | ` client/src/test/java/io/github/cowwoc/cat/hooks/test/TestClaudeToolTest.java ` | Remove ` getEnvFile() ` test assertion |
61+ | ` client/src/test/java/io/github/cowwoc/cat/hooks/test/TestClaudeHookTest.java ` | Remove ` getEnvFile() ` test assertions |
62+ | ` client/src/test/java/io/github/cowwoc/cat/hooks/test/EnforceJvmScopeEnvAccessTest.java ` | Add ` InjectEnv.java ` to whitelist |
63+
64+ ## Sub-Agent Waves
65+
66+ ### Wave 1
67+
68+ Each step below is a discrete edit. Read each file before editing. Commit type: ` refactor: ` .
69+
70+ ** Step 1: Remove ` getEnvFile() ` from ` ClaudeTool ` interface**
71+ - File: ` client/src/main/java/io/github/cowwoc/cat/hooks/ClaudeTool.java `
72+ - Remove the ` getEnvFile() ` method declaration and its Javadoc comment block
73+
74+ ** Step 2: Remove ` getEnvFile() ` from ` ClaudeHook ` interface**
75+ - File: ` client/src/main/java/io/github/cowwoc/cat/hooks/ClaudeHook.java `
76+ - Remove the ` getEnvFile() ` method declaration and its Javadoc comment block
77+
78+ ** Step 3: Remove ` envFile ` from ` AbstractClaudeTool ` **
79+ - File: ` client/src/main/java/io/github/cowwoc/cat/hooks/AbstractClaudeTool.java `
80+ - Remove the ` private final Path envFile; ` field
81+ - Remove the ` envFile ` parameter from the protected constructor and the ` this.envFile = envFile; ` assignment
82+ - Remove the entire ` getEnvFile() ` method implementation
83+ - Remove the ` @Override ` annotation above ` getEnvFile() ` if present
84+ - Keep all other fields and methods intact
85+
86+ ** Step 4: Remove abstract ` getEnvFile() ` from ` AbstractClaudeHook ` **
87+ - File: ` client/src/main/java/io/github/cowwoc/cat/hooks/AbstractClaudeHook.java `
88+ - Remove the ` @Override public abstract Path getEnvFile(); ` declaration
89+
90+ ** Step 5: Remove ` CLAUDE_ENV_FILE ` from ` MainClaudeTool ` constructor**
91+ - File: ` client/src/main/java/io/github/cowwoc/cat/hooks/MainClaudeTool.java `
92+ - In the constructor, remove the ` Path.of(getEnvVar("CLAUDE_ENV_FILE")) ` argument from the ` super() ` call
93+ - The super call should become:
94+ ` super(getEnvVar("CLAUDE_SESSION_ID"), Path.of(getEnvVar("CLAUDE_PROJECT_DIR")), Path.of(getEnvVar("CLAUDE_PLUGIN_ROOT"))) `
95+
96+ ** Step 6: Remove ` getEnvFile() ` from ` MainClaudeHook ` **
97+ - File: ` client/src/main/java/io/github/cowwoc/cat/hooks/MainClaudeHook.java `
98+ - Remove the entire ` getEnvFile() ` method (the ` @Override ` block that reads ` System.getenv("CLAUDE_ENV_FILE") ` )
99+
100+ ** Step 7: Update ` InjectEnv ` to read ` CLAUDE_ENV_FILE ` directly**
101+ - File: ` client/src/main/java/io/github/cowwoc/cat/hooks/session/InjectEnv.java `
102+ - At line 68 (or wherever ` Path envPath = scope.getEnvFile(); ` appears), replace with:
103+ ``` java
104+ String envFileValue = System . getenv(" CLAUDE_ENV_FILE" );
105+ if (envFileValue == null || envFileValue. isBlank())
106+ throw new AssertionError (" CLAUDE_ENV_FILE is not set" );
107+ Path envPath = Path . of(envFileValue);
108+ ```
109+ - Update imports if needed (should already have ` java.nio.file.Path ` )
110+
111+ ** Step 8: Update ` TestClaudeTool ` **
112+ - File: ` client/src/test/java/io/github/cowwoc/cat/hooks/test/TestClaudeTool.java `
113+ - Remove the ` envFile ` parameter from ALL constructors (there are multiple — check each one)
114+ - Remove the ` withEnvFile() ` factory method (around line 194-198)
115+ - Update ` super() ` calls to no longer pass ` envFile `
116+ - Remove any constructor that defaults to ` claudeProjectPath.resolve(".env") ` — remove that default
117+
118+ ** Step 9: Update ` TestClaudeHook ` **
119+ - File: ` client/src/test/java/io/github/cowwoc/cat/hooks/test/TestClaudeHook.java `
120+ - Remove the ` getEnvFile() ` implementation method
121+
122+ ** Step 10: Update ` TestClaudeToolTest ` **
123+ - File: ` client/src/test/java/io/github/cowwoc/cat/hooks/test/TestClaudeToolTest.java `
124+ - Remove any test assertion that calls ` getEnvFile() ` (around line 276)
125+
126+ ** Step 11: Update ` TestClaudeHookTest ` **
127+ - File: ` client/src/test/java/io/github/cowwoc/cat/hooks/test/TestClaudeHookTest.java `
128+ - Remove test assertions that call ` getEnvFile() ` (around lines 42 and 184)
129+ - If entire test methods only test ` getEnvFile() ` , remove the whole test method
130+
131+ ** Step 12: Update ` EnforceJvmScopeEnvAccessTest ` whitelist**
132+ - File: ` client/src/test/java/io/github/cowwoc/cat/hooks/test/EnforceJvmScopeEnvAccessTest.java `
133+ - Add ` io/github/cowwoc/cat/hooks/session/InjectEnv.java ` to the whitelist set (around lines 64-73)
134+ - This authorizes ` InjectEnv ` to call ` System.getenv() ` directly
135+ - If ` MainClaudeHook.java ` no longer calls ` System.getenv("CLAUDE_ENV_FILE") ` , verify whether it still
136+ needs to be in the whitelist (it may call ` System.getenv() ` for other variables — check before removing)
137+
138+ ** Step 13: Remove unused imports**
139+ - After all changes, check each modified file for unused imports (especially ` java.nio.file.Path ` in files
140+ that no longer reference ` Path ` )
141+
142+ ** Step 14: Build and test**
143+ - Run ` mvn -f client/pom.xml verify -e ` and ensure all tests pass
144+ - Fix any compilation errors from the changes above
145+
146+ ** Step 15: Update ` index.json ` **
147+ - Update ` .cat/issues/v2/v2.1/remove-env-file-from-scopes/index.json ` to set status to ` closed `
148+
149+ ** Step 16: Commit**
150+ - Stage all changed files
151+ - Commit with message: ` refactor: remove CLAUDE_ENV_FILE from ClaudeTool and ClaudeHook scopes `
0 commit comments