mirror of
https://github.com/nix-community/home-manager.git
synced 2025-11-08 19:46:05 +01:00
claude-code: added 'hooks' and 'hooksDir' options to specify hooks from filesystem
This commit is contained in:
parent
be37a3492d
commit
5e06d0f184
6 changed files with 88 additions and 1 deletions
|
|
@ -156,6 +156,26 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hooks = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf lib.types.lines;
|
||||||
|
default = { };
|
||||||
|
description = ''
|
||||||
|
Custom hooks for Claude Code.
|
||||||
|
The attribute name becomes the hook filename, and the value is the hook script content.
|
||||||
|
Hooks are stored in .claude/hooks/ directory.
|
||||||
|
'';
|
||||||
|
example = {
|
||||||
|
pre-edit = ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "About to edit file: $1"
|
||||||
|
'';
|
||||||
|
post-commit = ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "Committed with message: $1"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
memory = {
|
memory = {
|
||||||
text = lib.mkOption {
|
text = lib.mkOption {
|
||||||
type = lib.types.nullOr lib.types.lines;
|
type = lib.types.nullOr lib.types.lines;
|
||||||
|
|
@ -206,6 +226,16 @@ in
|
||||||
example = lib.literalExpression "./commands";
|
example = lib.literalExpression "./commands";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hooksDir = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.path;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Path to a directory containing hook files for Claude Code.
|
||||||
|
Hook files from this directory will be symlinked to .claude/hooks/.
|
||||||
|
'';
|
||||||
|
example = lib.literalExpression "./hooks";
|
||||||
|
};
|
||||||
|
|
||||||
mcpServers = lib.mkOption {
|
mcpServers = lib.mkOption {
|
||||||
type = lib.types.attrsOf jsonFormat.type;
|
type = lib.types.attrsOf jsonFormat.type;
|
||||||
default = { };
|
default = { };
|
||||||
|
|
@ -265,6 +295,10 @@ in
|
||||||
assertion = !(cfg.commands != { } && cfg.commandsDir != null);
|
assertion = !(cfg.commands != { } && cfg.commandsDir != null);
|
||||||
message = "Cannot specify both `programs.claude-code.commands` and `programs.claude-code.commandsDir`";
|
message = "Cannot specify both `programs.claude-code.commands` and `programs.claude-code.commandsDir`";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
assertion = !(cfg.hooks != { } && cfg.hooksDir != null);
|
||||||
|
message = "Cannot specify both `programs.claude-code.hooks` and `programs.claude-code.hooksDir`";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.claude-code.finalPackage =
|
programs.claude-code.finalPackage =
|
||||||
|
|
@ -319,6 +353,11 @@ in
|
||||||
source = cfg.commandsDir;
|
source = cfg.commandsDir;
|
||||||
recursive = true;
|
recursive = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
".claude/hooks" = lib.mkIf (cfg.hooksDir != null) {
|
||||||
|
source = cfg.hooksDir;
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// lib.mapAttrs' (
|
// lib.mapAttrs' (
|
||||||
name: content:
|
name: content:
|
||||||
|
|
@ -331,7 +370,13 @@ in
|
||||||
lib.nameValuePair ".claude/commands/${name}.md" {
|
lib.nameValuePair ".claude/commands/${name}.md" {
|
||||||
text = content;
|
text = content;
|
||||||
}
|
}
|
||||||
) cfg.commands;
|
) cfg.commands
|
||||||
|
// lib.mapAttrs' (
|
||||||
|
name: content:
|
||||||
|
lib.nameValuePair ".claude/hooks/${name}" {
|
||||||
|
text = content;
|
||||||
|
}
|
||||||
|
) cfg.hooks;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,12 @@
|
||||||
test-command = "test content";
|
test-command = "test content";
|
||||||
};
|
};
|
||||||
commandsDir = ./commands;
|
commandsDir = ./commands;
|
||||||
|
|
||||||
|
# assert fail: cannot set hooks and hooksDir at the same time.
|
||||||
|
hooks = {
|
||||||
|
test-hook = "test content";
|
||||||
|
};
|
||||||
|
hooksDir = ./hooks;
|
||||||
};
|
};
|
||||||
|
|
||||||
test.asserts.assertions.expected = [
|
test.asserts.assertions.expected = [
|
||||||
|
|
@ -39,5 +45,6 @@
|
||||||
"Cannot specify both `programs.claude-code.memory.text` and `programs.claude-code.memory.source`"
|
"Cannot specify both `programs.claude-code.memory.text` and `programs.claude-code.memory.source`"
|
||||||
"Cannot specify both `programs.claude-code.agents` and `programs.claude-code.agentsDir`"
|
"Cannot specify both `programs.claude-code.agents` and `programs.claude-code.agentsDir`"
|
||||||
"Cannot specify both `programs.claude-code.commands` and `programs.claude-code.commandsDir`"
|
"Cannot specify both `programs.claude-code.commands` and `programs.claude-code.commandsDir`"
|
||||||
|
"Cannot specify both `programs.claude-code.hooks` and `programs.claude-code.hooksDir`"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,4 +7,5 @@
|
||||||
claude-code-memory-from-source = ./memory-from-source.nix;
|
claude-code-memory-from-source = ./memory-from-source.nix;
|
||||||
claude-code-agents-dir = ./agents-dir.nix;
|
claude-code-agents-dir = ./agents-dir.nix;
|
||||||
claude-code-commands-dir = ./commands-dir.nix;
|
claude-code-commands-dir = ./commands-dir.nix;
|
||||||
|
claude-code-hooks-dir = ./hooks-dir.nix;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,17 @@
|
||||||
Focus on user-friendly explanations and examples.
|
Focus on user-friendly explanations and examples.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hooks = {
|
||||||
|
pre-edit = ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "About to edit file: $1"
|
||||||
|
'';
|
||||||
|
post-commit = ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "Committed with message: $1"
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
nmt.script = ''
|
nmt.script = ''
|
||||||
|
|
@ -122,5 +133,11 @@
|
||||||
|
|
||||||
assertFileExists home-files/.claude/commands/commit.md
|
assertFileExists home-files/.claude/commands/commit.md
|
||||||
assertFileContent home-files/.claude/commands/commit.md ${./expected-commit}
|
assertFileContent home-files/.claude/commands/commit.md ${./expected-commit}
|
||||||
|
|
||||||
|
assertFileExists home-files/.claude/hooks/pre-edit
|
||||||
|
assertFileRegex home-files/.claude/hooks/pre-edit "About to edit file"
|
||||||
|
|
||||||
|
assertFileExists home-files/.claude/hooks/post-commit
|
||||||
|
assertFileRegex home-files/.claude/hooks/post-commit "Committed with message"
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
tests/modules/programs/claude-code/hooks-dir.nix
Normal file
14
tests/modules/programs/claude-code/hooks-dir.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
programs.claude-code = {
|
||||||
|
enable = true;
|
||||||
|
hooksDir = ./hooks;
|
||||||
|
};
|
||||||
|
|
||||||
|
nmt.script = ''
|
||||||
|
assertFileExists home-files/.claude/hooks/test-hook
|
||||||
|
assertLinkExists home-files/.claude/hooks/test-hook
|
||||||
|
assertFileContent \
|
||||||
|
home-files/.claude/hooks/test-hook \
|
||||||
|
${./hooks/test-hook}
|
||||||
|
'';
|
||||||
|
}
|
||||||
3
tests/modules/programs/claude-code/hooks/test-hook
Normal file
3
tests/modules/programs/claude-code/hooks/test-hook
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Test hook for claude-code
|
||||||
|
echo "Test hook executed with: $@"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue