Skip to content

Commit ea8263f

Browse files
authored
fix(qoder): install permission request hooks (#272)
1 parent 3e2aec7 commit ea8263f

3 files changed

Lines changed: 42 additions & 3 deletions

File tree

Sources/CodeIsland/ConfigInstaller.swift

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,12 +294,25 @@ struct ConfigInstaller {
294294
format: .traecli,
295295
events: defaultEvents(for: .traecli)
296296
),
297-
// Qoder — Claude Code fork
297+
// Qoder — Claude Code fork with its own documented PermissionRequest hook.
298298
CLIConfig(
299299
name: "Qoder", source: "qoder",
300300
configPath: ".qoder/settings.json", configKey: "hooks",
301301
format: .claude,
302-
events: defaultEvents(for: .claude)
302+
events: [
303+
("UserPromptSubmit", 5, true),
304+
("PreToolUse", 5, false),
305+
("PostToolUse", 5, true),
306+
("PostToolUseFailure", 5, true),
307+
("PermissionRequest", 86400, false),
308+
("Stop", 5, true),
309+
("SubagentStart", 5, true),
310+
("SubagentStop", 5, true),
311+
("SessionStart", 5, false),
312+
("SessionEnd", 5, true),
313+
("Notification", 86400, false),
314+
("PreCompact", 5, true),
315+
]
303316
),
304317
// QoderWork — Qoder's standalone desktop assistant app (not the IDE).
305318
// Claude-format hooks, but user-level ~/.qoderwork/settings.json ONLY
@@ -309,7 +322,20 @@ struct ConfigInstaller {
309322
name: "QoderWork", source: "qoderwork",
310323
configPath: ".qoderwork/settings.json", configKey: "hooks",
311324
format: .claude,
312-
events: defaultEvents(for: .claude)
325+
events: [
326+
("UserPromptSubmit", 5, true),
327+
("PreToolUse", 5, false),
328+
("PostToolUse", 5, true),
329+
("PostToolUseFailure", 5, true),
330+
("PermissionRequest", 86400, false),
331+
("Stop", 5, true),
332+
("SubagentStart", 5, true),
333+
("SubagentStop", 5, true),
334+
("SessionStart", 5, false),
335+
("SessionEnd", 5, true),
336+
("Notification", 86400, false),
337+
("PreCompact", 5, true),
338+
]
313339
),
314340
// Factory — Claude Code fork (uses "droid" as source identifier)
315341
CLIConfig(

Tests/CodeIslandTests/ConfigInstallerTests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ final class ConfigInstallerTests: XCTestCase {
2626
let hooks = try XCTUnwrap(hooksAny as? [Any], file: file, line: line)
2727
return hooks.compactMap { $0 as? [String: Any] }
2828
}
29+
30+
func testQoderConfigIncludesPermissionRequestHook() throws {
31+
let cli = try XCTUnwrap(ConfigInstaller.allCLIs.first { $0.source == "qoder" })
32+
XCTAssertEqual(cli.format, .claude)
33+
XCTAssertEqual(cli.configPath, ".qoder/settings.json")
34+
let permission = try XCTUnwrap(cli.events.first { $0.0 == "PermissionRequest" })
35+
XCTAssertEqual(permission.1, 86400)
36+
XCTAssertFalse(permission.2)
37+
}
38+
2939
func testRemoveManagedHookEntriesAlsoPrunesLegacyVibeIslandHooks() throws {
3040
let hooks: [String: Any] = [
3141
"SessionEnd": [

Tests/CodeIslandTests/QoderWorkSupportTests.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ final class QoderWorkSupportTests: XCTestCase {
2020
XCTFail("QoderWork hooks are Claude-format JSON")
2121
}
2222
XCTAssertFalse(cli.events.isEmpty)
23+
let permission = try XCTUnwrap(cli.events.first { $0.0 == "PermissionRequest" })
24+
XCTAssertEqual(permission.1, 86400)
25+
XCTAssertFalse(permission.2)
2326
}
2427

2528
func testQoderWorkSourceNormalization() {

0 commit comments

Comments
 (0)