How to Configure Blocked Commands with Regex Patterns in Claudian

Claudian blocks Bash commands by matching them against user-defined regex patterns stored in .claude/claudian-settings.json, automatically falling back to substring matching for invalid or overly long patterns.

Claudian is an Obsidian plugin that protects your host system by intercepting shell commands before they execute. When you configure blocked commands with regex patterns, you create a security policy that prevents accidental or malicious execution of dangerous operations like recursive deletes or forced repository pushes.

How the Blocklist System Works

The blocklist architecture separates storage, configuration, and enforcement across four core components.

Settings UI and Storage

The Blocked Commands section in the Settings UI provides a textarea for each platform where you enter one pattern per line. In src/features/settings/ClaudianSettings.ts (lines 48-62), the UI captures your input, splits it on newlines, trims whitespace, and persists the resulting array to plugin.settings.blockedCommands[platformKey]. This data is saved in .claude/claudian-settings.json in your Obsidian vault.

Platform-Specific Data Structures

The PlatformBlockedCommands interface, defined in src/core/types/settings.ts (lines 51-54), maintains two separate arrays: unix and windows. Because the Bash tool on Windows can invoke both Unix-style and Windows-style commands, the helper function getBashToolBlockedCommands (lines 78-83) merges both arrays on Windows while using only the current platform's array on macOS and Linux.

Runtime Enforcement Pipeline

Before any Bash tool executes, the createBlocklistHook in src/core/hooks/SecurityHooks.ts (lines 30-44) fetches the merged blocklist and calls isCommandBlocked from src/core/security/BlocklistChecker.ts (lines 19-29). If a match is found, the hook returns {continue: false, permissionDecision: 'deny'} and displays a notice reading "Command blocked by security policy," preventing the command from reaching the operating system.

Writing Effective Regex Patterns

Claudian evaluates each pattern as a case-insensitive regular expression using the JavaScript RegExp constructor with the 'i' flag. This means rm matches RM, Rm, and rm regardless of case.

Pattern Syntax Guidelines

  • Word boundaries: Use \\b to prevent partial matches. For example, \\brm\\b blocks the standalone command rm but allows rmbackup.
  • Whitespace matching: Use \\s+ to match one or more spaces or tabs between command arguments.
  • Anchoring: Use ^ to match the start of the command string, ensuring you block the command itself rather than arguments that might contain the same characters.
  • Escaping: Because patterns are stored as JSON strings, you must double-escape backslashes in the Settings UI. Enter \\s+ in the textarea to create a regex matching whitespace.

Example Blocklist Patterns

Add these to the "Blocked Commands" textarea for Unix systems:

^rm\s+-rf\b          # Block rm -rf with any whitespace variation

^chmod\s+7{3}\b      # Block chmod 777 but not chmod 755

^git\s+push\s+--force # Block dangerous forced pushes

^dd\s+if=.*of=/dev/  # Block disk writes to device files

The UI stores these as JSON-escaped strings in your settings:

{
  "blockedCommands": {
    "unix": [
      "^rm\\s+-rf\\b",
      "^chmod\\s+7{3}\\b",
      "^git\\s+push\\s+--force",
      "^dd\\s+if=.*of=/dev/"
    ],
    "windows": []
  }
}

Fallback Behavior for Long Patterns

Claudian implements a safety guard to prevent performance issues from pathological regular expressions. In BlocklistChecker.ts (lines 19-29), patterns longer than 500 characters (the MAX_PATTERN_LENGTH constant) bypass regex compilation entirely and are matched using a simple case-insensitive substring search (includes()).

Additionally, if your pattern contains invalid regex syntax, the try-catch block falls back to substring matching. This ensures that accidental entries like rm -rf * (where * is a glob, not a regex quantifier) still function as literal blocklist entries rather than throwing exceptions.

Programmatically Updating the Blocklist

If you are building a companion plugin or automation script, you can manipulate the blocklist directly through the plugin API:

import { PlatformBlockedCommands } from '@/core/types';

async function addBlockPattern(
  plugin: any, 
  pattern: string, 
  platform: 'unix' | 'windows'
) {
  const cmds: PlatformBlockedCommands = plugin.settings.blockedCommands;
  
  // Add new pattern, avoiding duplicates
  cmds[platform] = [...new Set([...cmds[platform], pattern.trim()])];
  
  plugin.settings.blockedCommands = cmds;
  await plugin.saveSettings(); // Persists to claudian-settings.json
}

To verify if a command would be blocked without executing it, use the internal checker:

import { isCommandBlocked } from '@/core/security/BlocklistChecker';
import { getBashToolBlockedCommands } from '@/core/types';

function checkCommandSafety(
  command: string, 
  settings: any
): boolean {
  const merged = getBashToolBlockedCommands(settings.blockedCommands);
  return !isCommandBlocked(command, merged, settings.enableBlocklist);
}

Summary

  • Configuration location: Edit the "Blocked Commands" textarea in Claudian Settings, which writes to .claude/claudian-settings.json.
  • Pattern format: Enter one regex pattern per line; use double backslashes for escapes (e.g., \\b for word boundaries).
  • Platform handling: Unix and Windows arrays are maintained separately but merged on Windows hosts.
  • Enforcement: SecurityHooks.createBlocklistHook intercepts Bash tools and denies execution when isCommandBlocked returns true.
  • Fallback logic: Patterns exceeding 500 characters or containing invalid regex syntax automatically use substring matching instead.

Frequently Asked Questions

How do I block a specific command with arguments but allow other uses?

Use anchored patterns with word boundaries. For example, ^rm\s+-rf\b blocks rm -rf / but allows rm -i file.txt. The ^ ensures the match starts at the beginning of the command, and \\b ensures -rf is a complete word.

Why is my regex pattern not working as expected?

Check that you have double-escaped backslashes in the Settings UI. A pattern entered as \s+ will be interpreted as the literal characters "s+" because JSON unescaping occurs before regex compilation. You must enter \\s+ to match whitespace. Also verify your pattern is under 500 characters to ensure it evaluates as a regex rather than a literal substring.

Can I block Windows PowerShell commands or only Bash?

The blocklist applies to the Bash tool execution environment. On Windows, getBashToolBlockedCommands merges both the unix and windows arrays, so you can block Windows-specific commands (like del /f /s /q) by adding them to the Windows textarea. On macOS and Linux, only the unix array is consulted.

What happens when a command is blocked?

The createBlocklistHook returns a denial decision to the tool execution framework, which displays a notice reading "Command blocked by security policy" in the Obsidian UI. The command string never executes in the host shell, and the AI interaction continues without the tool result.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →