claude-warden 1.4.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/config/warden.default.yaml +6 -0
- package/dist/index.cjs +75 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-warden",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "Smart command safety filter for Claude Code — parses shell pipelines and evaluates per-command safety rules to auto-approve safe commands and block dangerous ones",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "banyudu"
|
|
@@ -13,6 +13,12 @@ defaultDecision: ask
|
|
|
13
13
|
# If true, commands containing $() or backticks trigger "ask"
|
|
14
14
|
askOnSubshell: true
|
|
15
15
|
|
|
16
|
+
# Send OS notifications when warden prompts for permission or blocks a command.
|
|
17
|
+
# On macOS, uses terminal-notifier (click to activate terminal) or osascript fallback.
|
|
18
|
+
# On Linux, uses notify-send.
|
|
19
|
+
notifyOnAsk: true
|
|
20
|
+
notifyOnDeny: true
|
|
21
|
+
|
|
16
22
|
# Additional commands to always allow (checked after alwaysDeny within this scope)
|
|
17
23
|
# alwaysAllow:
|
|
18
24
|
# - terraform
|
package/dist/index.cjs
CHANGED
|
@@ -18988,6 +18988,8 @@ function pkgRunnerRule(command) {
|
|
|
18988
18988
|
var DEFAULT_CONFIG = {
|
|
18989
18989
|
defaultDecision: "ask",
|
|
18990
18990
|
askOnSubshell: true,
|
|
18991
|
+
notifyOnAsk: true,
|
|
18992
|
+
notifyOnDeny: true,
|
|
18991
18993
|
trustedSSHHosts: [],
|
|
18992
18994
|
trustedDockerContainers: [],
|
|
18993
18995
|
trustedKubectlContexts: [],
|
|
@@ -19578,6 +19580,12 @@ function mergeNonLayerFields(config, raw) {
|
|
|
19578
19580
|
if (typeof raw.askOnSubshell === "boolean") {
|
|
19579
19581
|
config.askOnSubshell = raw.askOnSubshell;
|
|
19580
19582
|
}
|
|
19583
|
+
if (typeof raw.notifyOnAsk === "boolean") {
|
|
19584
|
+
config.notifyOnAsk = raw.notifyOnAsk;
|
|
19585
|
+
}
|
|
19586
|
+
if (typeof raw.notifyOnDeny === "boolean") {
|
|
19587
|
+
config.notifyOnDeny = raw.notifyOnDeny;
|
|
19588
|
+
}
|
|
19581
19589
|
if (raw.trustedContextOverrides && typeof raw.trustedContextOverrides === "object") {
|
|
19582
19590
|
const overrides = raw.trustedContextOverrides;
|
|
19583
19591
|
const layer = extractLayer(overrides);
|
|
@@ -19666,6 +19674,62 @@ See /claude-warden:warden-allow`;
|
|
|
19666
19674
|
return lines.join("\n");
|
|
19667
19675
|
}
|
|
19668
19676
|
|
|
19677
|
+
// src/notify.ts
|
|
19678
|
+
var import_child_process = require("child_process");
|
|
19679
|
+
var TERMINAL_BUNDLE_IDS = {
|
|
19680
|
+
"iTerm.app": "com.googlecode.iterm2",
|
|
19681
|
+
"Apple_Terminal": "com.apple.Terminal",
|
|
19682
|
+
"Alacritty": "com.github.alacritty.Alacritty",
|
|
19683
|
+
"WezTerm": "io.wezfurlong.wezterm"
|
|
19684
|
+
};
|
|
19685
|
+
var terminalNotifierAvailable = null;
|
|
19686
|
+
function hasTerminalNotifier() {
|
|
19687
|
+
if (terminalNotifierAvailable !== null) return terminalNotifierAvailable;
|
|
19688
|
+
try {
|
|
19689
|
+
(0, import_child_process.execFileSync)("which", ["terminal-notifier"], { stdio: "ignore" });
|
|
19690
|
+
terminalNotifierAvailable = true;
|
|
19691
|
+
} catch {
|
|
19692
|
+
terminalNotifierAvailable = false;
|
|
19693
|
+
}
|
|
19694
|
+
return terminalNotifierAvailable;
|
|
19695
|
+
}
|
|
19696
|
+
function getBundleId() {
|
|
19697
|
+
const termProgram = process.env.TERM_PROGRAM;
|
|
19698
|
+
if (!termProgram) return void 0;
|
|
19699
|
+
return TERMINAL_BUNDLE_IDS[termProgram];
|
|
19700
|
+
}
|
|
19701
|
+
function buildNotifyCommand(title, message) {
|
|
19702
|
+
const platform = process.platform;
|
|
19703
|
+
if (platform === "darwin") {
|
|
19704
|
+
if (hasTerminalNotifier()) {
|
|
19705
|
+
const args2 = ["-title", title, "-message", message];
|
|
19706
|
+
const bundleId = getBundleId();
|
|
19707
|
+
if (bundleId) {
|
|
19708
|
+
args2.push("-activate", bundleId);
|
|
19709
|
+
}
|
|
19710
|
+
return { cmd: "terminal-notifier", args: args2 };
|
|
19711
|
+
}
|
|
19712
|
+
const script = `display notification ${JSON.stringify(message)} with title ${JSON.stringify(title)}`;
|
|
19713
|
+
return { cmd: "osascript", args: ["-e", script] };
|
|
19714
|
+
}
|
|
19715
|
+
if (platform === "linux") {
|
|
19716
|
+
return { cmd: "notify-send", args: [title, message] };
|
|
19717
|
+
}
|
|
19718
|
+
return null;
|
|
19719
|
+
}
|
|
19720
|
+
function sendNotification(title, message, config) {
|
|
19721
|
+
try {
|
|
19722
|
+
const notifyCmd = buildNotifyCommand(title, message);
|
|
19723
|
+
if (!notifyCmd) return;
|
|
19724
|
+
const child = (0, import_child_process.spawn)(notifyCmd.cmd, notifyCmd.args, {
|
|
19725
|
+
detached: true,
|
|
19726
|
+
stdio: "ignore"
|
|
19727
|
+
});
|
|
19728
|
+
child.unref();
|
|
19729
|
+
} catch {
|
|
19730
|
+
}
|
|
19731
|
+
}
|
|
19732
|
+
|
|
19669
19733
|
// src/index.ts
|
|
19670
19734
|
async function main() {
|
|
19671
19735
|
let raw = "";
|
|
@@ -19681,6 +19745,9 @@ async function main() {
|
|
|
19681
19745
|
if (input.tool_name !== "Bash") {
|
|
19682
19746
|
process.exit(0);
|
|
19683
19747
|
}
|
|
19748
|
+
if (input.permission_mode === "dangerously-skip-permissions") {
|
|
19749
|
+
process.exit(0);
|
|
19750
|
+
}
|
|
19684
19751
|
const command = input.tool_input?.command;
|
|
19685
19752
|
if (!command || typeof command !== "string") {
|
|
19686
19753
|
process.exit(0);
|
|
@@ -19700,6 +19767,10 @@ async function main() {
|
|
|
19700
19767
|
process.exit(0);
|
|
19701
19768
|
}
|
|
19702
19769
|
if (result.decision === "deny") {
|
|
19770
|
+
if (config.notifyOnDeny) {
|
|
19771
|
+
const truncated = command.length > 80 ? command.slice(0, 77) + "..." : command;
|
|
19772
|
+
sendNotification("Claude Warden", `Blocked: ${truncated}`, config);
|
|
19773
|
+
}
|
|
19703
19774
|
const msg2 = formatSystemMessage("deny", command, result.details);
|
|
19704
19775
|
const output2 = {
|
|
19705
19776
|
hookSpecificOutput: {
|
|
@@ -19713,6 +19784,10 @@ async function main() {
|
|
|
19713
19784
|
`);
|
|
19714
19785
|
process.exit(2);
|
|
19715
19786
|
}
|
|
19787
|
+
if (config.notifyOnAsk) {
|
|
19788
|
+
const truncated = command.length > 80 ? command.slice(0, 77) + "..." : command;
|
|
19789
|
+
sendNotification("Claude Warden", `Permission needed: ${truncated}`, config);
|
|
19790
|
+
}
|
|
19716
19791
|
const msg = formatSystemMessage("ask", command, result.details);
|
|
19717
19792
|
const output = {
|
|
19718
19793
|
hookSpecificOutput: {
|