Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/guardrails/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,5 @@
"min": 1
}
},
"version": "0.32.5"
"version": "0.32.6"
}
24 changes: 24 additions & 0 deletions plugins/guardrails/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,30 @@
All notable changes to the `guardrails` plugin are documented here. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning.

## [0.32.6]

### Changed

- **The Bash dispatcher and every always-on guard locate `hook-utils.sh`
with parameter expansion, not `dirname`, and the dispatcher copies its jq
cache helper without `sed`.** A benign `git status --short` on this host
spent 7 `dirname` execs (one per enabled Bash guard; the default-off
`flag-commit-pr-skill-bypass` exits before `source`) plus one `sed` to rename
`hook::jq_fields`, of 13 counted PATH-shim spawns. After: 0 `dirname`, 0
`sed`, 5 remaining (`3 git` + `2 jq`, the classification work and the one primed
payload parse). Spawn census through a stable PATH shim, `HOOK_TELEMETRY_SINK`
unset, same payload: **13 → 5**. Wall clock on this measurable Linux host
(spawn floor 0.5–0.7 ms, n=20): p50 70.0 → 60.7 ms, p95 73.5 → 62.1 ms.
The milliseconds are context; on a host whose spawn floor is tens of
milliseconds the durable figure is the eight PATH-visible execs that
disappeared.
`${BASH_SOURCE[0]%/*}` equals `dirname` for every shape BASH_SOURCE takes; a
dispatched guard still sees the real `dirname` command, not a dispatcher
shadow. `run-guards.test.sh` pins both the empty shim log and the source
shape, plus `./run-guards.sh` and a bare `run-guards.sh` / `block-no-verify.sh`
so the relative `cd && pwd` arm and the `_HOOK_SELF=.` fallback are not
comment-only. What each guard checks is unchanged.

## [0.32.5]

### Changed
Expand Down
26 changes: 26 additions & 0 deletions plugins/guardrails/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,32 @@ out of scope until such a signal exists.

### Hook budget accounting

**0.32.6, remaining `dirname`/`sed` execs on the Bash dispatcher.** 2026-09-05,
Linux CI host. The 0.31.1 paired table still carries the pre-cut figures for the
whole Bash dispatcher (52.6 spawn-equivalents); this entry supersedes that
row's counted-exec half. Neither guard's decision changed. Every always-on
Bash guard located `hook-utils.sh` with `source "$(dirname …)"` even after the
dispatcher had already loaded the library, and the dispatcher copied
`hook::jq_fields` through `sed`. Those are PATH-visible execs; the per-guard
`$(source …)` isolation fork is a function-level fork the census does not
count, and is unchanged.

*Method.* Spawn census via a stable PATH shim (`plugins/performance/scripts/spawn-census.sh`),
`HOOK_TELEMETRY_SINK` unset, benign `git status --short` payload, same host as
the wall-clock pass. Wall clock is p50/p95 of 20 samples after 2 warmup on a
host `spawn_probe` characterised as measurable (min 0.5 ms, spread 1.42×).

| Counter | before | after |
|---|---|---|
| Counted PATH-shim spawns | 13 (`7 dirname`, `3 git`, `2 jq`, `1 sed`) | 5 (`3 git`, `2 jq`) |
| `dirname` | 7 | 0 |
| `sed` | 1 | 0 |
| Wall p50 / p95 (n=20) | 70.0 / 73.5 ms | 60.7 / 62.1 ms |

The remaining five execs are the one primed `jq` payload parse and the git
probes the classification guards still run on a `git` command; those were
measured and deliberately not folded earlier (0.31.1).

**0.32.5, the PostToolUse `if` rows.** 2026-09-05, Linux CI host. The three
PostToolUse verifiers accept five extensions between them (`cli-flag-verify` scans
`.md`, `.sh`, `.bash`, `.ps1` and `.psm1`; the other two scan `.md`), and every
Expand Down
15 changes: 13 additions & 2 deletions plugins/guardrails/hooks/block-convention-violation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,25 @@ set -uo pipefail
# and fails a guard that sources anything ahead of it.
[[ "${CLAUDE_PLUGIN_OPTION_BLOCK_CONVENTION_GATE_ENABLED:-true}" == "true" ]] || exit 0

# The hook's own directory is derived with parameter expansion rather than
# `dirname`. GNU Bash forks a subshell for every command substitution even when
# the body is a builtin (Command Substitution, Bash Reference Manual;
# https://mywiki.wooledge.org/CommandSubstitution). On Windows Git Bash that
# fork is a process, and this line runs on every fire — including inside the
# dispatcher, where the include guard makes `source` cheap but `$(dirname …)`
# still execs. `${BASH_SOURCE[0]%/*}` equals `dirname` for every shape
# BASH_SOURCE takes; the fallback covers a bare filename, where the strip is a
# no-op and dirname answers `.`.
_HOOK_SELF="${BASH_SOURCE[0]%/*}"
[[ "$_HOOK_SELF" == "${BASH_SOURCE[0]}" ]] && _HOOK_SELF=.
# shellcheck source=hook-utils.sh
source "$(dirname "${BASH_SOURCE[0]}")/hook-utils.sh"
source "$_HOOK_SELF/hook-utils.sh"

# Bundled PowerShell-command classifier — this gate is matched on both the Bash
# and the (opt-in) PowerShell tool, same as the sibling git guards. Resolved
# under the plugin root (CC sets CLAUDE_PLUGIN_ROOT; the BASH_SOURCE fallback
# keeps the contract tests working when it is unset).
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$_HOOK_SELF/.." && pwd)}"
# shellcheck source=../lib/powershell/ps-command.sh
source "$PLUGIN_ROOT/lib/powershell/ps-command.sh"

Expand Down
15 changes: 13 additions & 2 deletions plugins/guardrails/hooks/block-dangerous-git.sh
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,26 @@ set -uo pipefail
# and fails a guard that sources anything ahead of it.
[[ "${CLAUDE_PLUGIN_OPTION_BLOCK_DANGEROUS_GIT_ENABLED:-true}" == "true" ]] || exit 0

# The hook's own directory is derived with parameter expansion rather than
# `dirname`. GNU Bash forks a subshell for every command substitution even when
# the body is a builtin (Command Substitution, Bash Reference Manual;
# https://mywiki.wooledge.org/CommandSubstitution). On Windows Git Bash that
# fork is a process, and this line runs on every fire — including inside the
# dispatcher, where the include guard makes `source` cheap but `$(dirname …)`
# still execs. `${BASH_SOURCE[0]%/*}` equals `dirname` for every shape
# BASH_SOURCE takes; the fallback covers a bare filename, where the strip is a
# no-op and dirname answers `.`.
_HOOK_SELF="${BASH_SOURCE[0]%/*}"
[[ "$_HOOK_SELF" == "${BASH_SOURCE[0]}" ]] && _HOOK_SELF=.
# shellcheck source=hook-utils.sh
source "$(dirname "${BASH_SOURCE[0]}")/hook-utils.sh"
source "$_HOOK_SELF/hook-utils.sh"

# Bundled PowerShell-command classifier — the git guards are matched on both the
# Bash and the (opt-in) PowerShell tool, whose command arrives in the same
# tool_input.command field with PowerShell grammar. Resolved under the plugin
# root (CC sets CLAUDE_PLUGIN_ROOT; the BASH_SOURCE fallback keeps the contract
# tests working when it is unset).
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$_HOOK_SELF/.." && pwd)}"
# shellcheck source=../lib/powershell/ps-command.sh
source "$PLUGIN_ROOT/lib/powershell/ps-command.sh"

Expand Down
13 changes: 12 additions & 1 deletion plugins/guardrails/hooks/block-exported-msys-pathconv.sh
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,19 @@ set -uo pipefail
# and fails a guard that sources anything ahead of it.
[[ "${CLAUDE_PLUGIN_OPTION_BLOCK_EXPORTED_MSYS_PATHCONV_ENABLED:-true}" == "true" ]] || exit 0

# The hook's own directory is derived with parameter expansion rather than
# `dirname`. GNU Bash forks a subshell for every command substitution even when
# the body is a builtin (Command Substitution, Bash Reference Manual;
# https://mywiki.wooledge.org/CommandSubstitution). On Windows Git Bash that
# fork is a process, and this line runs on every fire — including inside the
# dispatcher, where the include guard makes `source` cheap but `$(dirname …)`
# still execs. `${BASH_SOURCE[0]%/*}` equals `dirname` for every shape
# BASH_SOURCE takes; the fallback covers a bare filename, where the strip is a
# no-op and dirname answers `.`.
_HOOK_SELF="${BASH_SOURCE[0]%/*}"
[[ "$_HOOK_SELF" == "${BASH_SOURCE[0]}" ]] && _HOOK_SELF=.
# shellcheck source=hook-utils.sh
source "$(dirname "${BASH_SOURCE[0]}")/hook-utils.sh"
source "$_HOOK_SELF/hook-utils.sh"

# High-res start stamp for the telemetry envelope. EPOCHREALTIME is Bash 5.0+;
# on older bash it is unset, so default to empty and skip telemetry (the block
Expand Down
15 changes: 13 additions & 2 deletions plugins/guardrails/hooks/block-hook-bypass.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,19 @@ set -uo pipefail
# is loaded in time for. scripts/check-killswitch-hoist.sh knows this shape.
[[ "${CLAUDE_PLUGIN_OPTION_BLOCK_HOOK_BYPASS_ENABLED:-true}" == "false" ]] && exit 0

# The hook's own directory is derived with parameter expansion rather than
# `dirname`. GNU Bash forks a subshell for every command substitution even when
# the body is a builtin (Command Substitution, Bash Reference Manual;
# https://mywiki.wooledge.org/CommandSubstitution). On Windows Git Bash that
# fork is a process, and this line runs on every fire — including inside the
# dispatcher, where the include guard makes `source` cheap but `$(dirname …)`
# still execs. `${BASH_SOURCE[0]%/*}` equals `dirname` for every shape
# BASH_SOURCE takes; the fallback covers a bare filename, where the strip is a
# no-op and dirname answers `.`.
_HOOK_SELF="${BASH_SOURCE[0]%/*}"
[[ "$_HOOK_SELF" == "${BASH_SOURCE[0]}" ]] && _HOOK_SELF=.
# shellcheck source=hook-utils.sh
source "$(dirname "${BASH_SOURCE[0]}")/hook-utils.sh"
source "$_HOOK_SELF/hook-utils.sh"

# Crash posture (#3130 F5): fail-open. This guard sits on every Bash/PowerShell
# call. An internal error must not take the session down, and it must not look
Expand Down Expand Up @@ -1458,7 +1469,7 @@ block_bypass() {
# the parse tax. Resolved under the plugin root (CC sets CLAUDE_PLUGIN_ROOT;
# the BASH_SOURCE fallback keeps the contract tests working when it is unset).
if [[ "$TOOL_NAME" == "PowerShell" ]]; then
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$_HOOK_SELF/.." && pwd)}"
# shellcheck source=../lib/powershell/ps-command.sh
source "$PLUGIN_ROOT/lib/powershell/ps-command.sh"
if ps::write_bypass "$COMMAND"; then
Expand Down
15 changes: 13 additions & 2 deletions plugins/guardrails/hooks/block-no-verify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,26 @@ set -uo pipefail
# and fails a guard that sources anything ahead of it.
[[ "${CLAUDE_PLUGIN_OPTION_BLOCK_NO_VERIFY_ENABLED:-true}" == "true" ]] || exit 0

# The hook's own directory is derived with parameter expansion rather than
# `dirname`. GNU Bash forks a subshell for every command substitution even when
# the body is a builtin (Command Substitution, Bash Reference Manual;
# https://mywiki.wooledge.org/CommandSubstitution). On Windows Git Bash that
# fork is a process, and this line runs on every fire — including inside the
# dispatcher, where the include guard makes `source` cheap but `$(dirname …)`
# still execs. `${BASH_SOURCE[0]%/*}` equals `dirname` for every shape
# BASH_SOURCE takes; the fallback covers a bare filename, where the strip is a
# no-op and dirname answers `.`.
_HOOK_SELF="${BASH_SOURCE[0]%/*}"
[[ "$_HOOK_SELF" == "${BASH_SOURCE[0]}" ]] && _HOOK_SELF=.
# shellcheck source=hook-utils.sh
source "$(dirname "${BASH_SOURCE[0]}")/hook-utils.sh"
source "$_HOOK_SELF/hook-utils.sh"

# Bundled PowerShell-command classifier — the git guards are matched on both the
# Bash and the (opt-in) PowerShell tool, whose command arrives in the same
# tool_input.command field with PowerShell grammar. Resolved under the plugin
# root (CC sets CLAUDE_PLUGIN_ROOT; the BASH_SOURCE fallback keeps the contract
# tests working when it is unset).
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$_HOOK_SELF/.." && pwd)}"
# shellcheck source=../lib/powershell/ps-command.sh
source "$PLUGIN_ROOT/lib/powershell/ps-command.sh"

Expand Down
15 changes: 13 additions & 2 deletions plugins/guardrails/hooks/block-noncanonical-commit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,26 @@ set -uo pipefail
# and fails a guard that sources anything ahead of it.
[[ "${CLAUDE_PLUGIN_OPTION_BLOCK_NONCANONICAL_COMMIT_ENABLED:-true}" == "true" ]] || exit 0

# The hook's own directory is derived with parameter expansion rather than
# `dirname`. GNU Bash forks a subshell for every command substitution even when
# the body is a builtin (Command Substitution, Bash Reference Manual;
# https://mywiki.wooledge.org/CommandSubstitution). On Windows Git Bash that
# fork is a process, and this line runs on every fire — including inside the
# dispatcher, where the include guard makes `source` cheap but `$(dirname …)`
# still execs. `${BASH_SOURCE[0]%/*}` equals `dirname` for every shape
# BASH_SOURCE takes; the fallback covers a bare filename, where the strip is a
# no-op and dirname answers `.`.
_HOOK_SELF="${BASH_SOURCE[0]%/*}"
[[ "$_HOOK_SELF" == "${BASH_SOURCE[0]}" ]] && _HOOK_SELF=.
# shellcheck source=hook-utils.sh
source "$(dirname "${BASH_SOURCE[0]}")/hook-utils.sh"
source "$_HOOK_SELF/hook-utils.sh"

# Bundled PowerShell-command classifier — the git guards are matched on both the
# Bash and the (opt-in) PowerShell tool, whose command arrives in the same
# tool_input.command field with PowerShell grammar. Resolved under the plugin
# root (CC sets CLAUDE_PLUGIN_ROOT; the BASH_SOURCE fallback keeps the contract
# tests working when it is unset).
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$_HOOK_SELF/.." && pwd)}"
# shellcheck source=../lib/powershell/ps-command.sh
source "$PLUGIN_ROOT/lib/powershell/ps-command.sh"

Expand Down
13 changes: 12 additions & 1 deletion plugins/guardrails/hooks/block-windows-drive-tmp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,19 @@ set -uo pipefail
# and fails a guard that sources anything ahead of it.
[[ "${CLAUDE_PLUGIN_OPTION_BLOCK_WINDOWS_DRIVE_TMP_ENABLED:-true}" == "true" ]] || exit 0

# The hook's own directory is derived with parameter expansion rather than
# `dirname`. GNU Bash forks a subshell for every command substitution even when
# the body is a builtin (Command Substitution, Bash Reference Manual;
# https://mywiki.wooledge.org/CommandSubstitution). On Windows Git Bash that
# fork is a process, and this line runs on every fire — including inside the
# dispatcher, where the include guard makes `source` cheap but `$(dirname …)`
# still execs. `${BASH_SOURCE[0]%/*}` equals `dirname` for every shape
# BASH_SOURCE takes; the fallback covers a bare filename, where the strip is a
# no-op and dirname answers `.`.
_HOOK_SELF="${BASH_SOURCE[0]%/*}"
[[ "$_HOOK_SELF" == "${BASH_SOURCE[0]}" ]] && _HOOK_SELF=.
# shellcheck source=hook-utils.sh
source "$(dirname "${BASH_SOURCE[0]}")/hook-utils.sh"
source "$_HOOK_SELF/hook-utils.sh"

# Non-Windows hosts: /tmp is the real POSIX temp, so this guard can never find a
# violation here. Skip entirely. Tests force OSTYPE=msys to exercise the Windows
Expand Down
15 changes: 13 additions & 2 deletions plugins/guardrails/hooks/cli-flag-verify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,25 @@ start=${EPOCHREALTIME:-}
# hook::is_enabled; scripts/check-killswitch-hoist.sh pins the two together.
[[ "${CLAUDE_PLUGIN_OPTION_CLI_FLAG_VERIFY_ENABLED:-true}" == "true" ]] || exit 0

# The hook's own directory is derived with parameter expansion rather than
# `dirname`. GNU Bash forks a subshell for every command substitution even when
# the body is a builtin (Command Substitution, Bash Reference Manual;
# https://mywiki.wooledge.org/CommandSubstitution). On Windows Git Bash that
# fork is a process, and this line runs on every fire — including inside the
# dispatcher, where the include guard makes `source` cheap but `$(dirname …)`
# still execs. `${BASH_SOURCE[0]%/*}` equals `dirname` for every shape
# BASH_SOURCE takes; the fallback covers a bare filename, where the strip is a
# no-op and dirname answers `.`.
_HOOK_SELF="${BASH_SOURCE[0]%/*}"
[[ "$_HOOK_SELF" == "${BASH_SOURCE[0]}" ]] && _HOOK_SELF=.
# shellcheck source=hook-utils.sh
source "$(dirname "${BASH_SOURCE[0]}")/hook-utils.sh"
source "$_HOOK_SELF/hook-utils.sh"

hook::ctx_reset

# Bundled verifier — resolved under the plugin root (CC sets CLAUDE_PLUGIN_ROOT;
# the BASH_SOURCE fallback keeps the contract tests working when it is unset).
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$_HOOK_SELF/.." && pwd)}"
VERIFIER="$PLUGIN_ROOT/lib/verification/verify-cli-flag.sh"

# hook::buffer_stdin encapsulates the Win32-pipe-safe bounded fd0 read; empty
Expand Down
15 changes: 13 additions & 2 deletions plugins/guardrails/hooks/flag-commit-pr-skill-bypass.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,25 @@ set -uo pipefail
# the hoist only moves it; scripts/check-killswitch-hoist.sh keeps it here.
[[ "${CLAUDE_PLUGIN_OPTION_FLAG_COMMIT_PR_SKILL_BYPASS_ENABLED:-false}" == "true" ]] || exit 0

# The hook's own directory is derived with parameter expansion rather than
# `dirname`. GNU Bash forks a subshell for every command substitution even when
# the body is a builtin (Command Substitution, Bash Reference Manual;
# https://mywiki.wooledge.org/CommandSubstitution). On Windows Git Bash that
# fork is a process, and this line runs on every fire — including inside the
# dispatcher, where the include guard makes `source` cheap but `$(dirname …)`
# still execs. `${BASH_SOURCE[0]%/*}` equals `dirname` for every shape
# BASH_SOURCE takes; the fallback covers a bare filename, where the strip is a
# no-op and dirname answers `.`.
_HOOK_SELF="${BASH_SOURCE[0]%/*}"
[[ "$_HOOK_SELF" == "${BASH_SOURCE[0]}" ]] && _HOOK_SELF=.
# shellcheck source=hook-utils.sh
source "$(dirname "${BASH_SOURCE[0]}")/hook-utils.sh"
source "$_HOOK_SELF/hook-utils.sh"

# Bundled PowerShell-command classifier — this guard is matched on both the Bash
# and the (opt-in) PowerShell tool. Resolved under the plugin root (CC sets
# CLAUDE_PLUGIN_ROOT; the BASH_SOURCE fallback keeps the contract tests working
# when it is unset).
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$_HOOK_SELF/.." && pwd)}"
# shellcheck source=../lib/powershell/ps-command.sh
source "$PLUGIN_ROOT/lib/powershell/ps-command.sh"

Expand Down
15 changes: 13 additions & 2 deletions plugins/guardrails/hooks/hardcoded-path-check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,24 @@ set -uo pipefail
# and fails a guard that sources anything ahead of it.
[[ "${CLAUDE_PLUGIN_OPTION_HARDCODED_PATH_CHECK_ENABLED:-true}" == "true" ]] || exit 0

# The hook's own directory is derived with parameter expansion rather than
# `dirname`. GNU Bash forks a subshell for every command substitution even when
# the body is a builtin (Command Substitution, Bash Reference Manual;
# https://mywiki.wooledge.org/CommandSubstitution). On Windows Git Bash that
# fork is a process, and this line runs on every fire — including inside the
# dispatcher, where the include guard makes `source` cheap but `$(dirname …)`
# still execs. `${BASH_SOURCE[0]%/*}` equals `dirname` for every shape
# BASH_SOURCE takes; the fallback covers a bare filename, where the strip is a
# no-op and dirname answers `.`.
_HOOK_SELF="${BASH_SOURCE[0]%/*}"
[[ "$_HOOK_SELF" == "${BASH_SOURCE[0]}" ]] && _HOOK_SELF=.
# shellcheck source=hook-utils.sh
source "$(dirname "${BASH_SOURCE[0]}")/hook-utils.sh"
source "$_HOOK_SELF/hook-utils.sh"

# Bundled pattern lib — resolved under the plugin root (CC sets
# CLAUDE_PLUGIN_ROOT; the BASH_SOURCE fallback keeps the contract tests working
# when it is unset).
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$_HOOK_SELF/.." && pwd)}"
# shellcheck source=../lib/path-detection/hardcoded-path-patterns.sh
source "$PLUGIN_ROOT/lib/path-detection/hardcoded-path-patterns.sh"

Expand Down
Loading
Loading