Installation
Install the shk CLI with npm, bun, the bundled installer script, Homebrew, or from source, and keep the CLI and desktop app up to date.
On this page
shk is distributed as a single CLI binary.
| Goal | Setting / tool | Details |
|---|---|---|
| Use npm / bun | CLI | Go to section |
| Use an installer script | CLI | Go to section |
| Verify an archive | CLI | Go to section |
| Use Homebrew | CLI | Go to section |
| Use a GUI | Desktop + CLI for hooks | Go to section |
| Update an installation | CLI / Desktop | Go to section |
npm
Each tagged CLI release publishes the security-harness-kit package to npm. The installed command is shk:
npm install -g security-harness-kit
shk --versionThe npm package is generated by dist from the same release. On install it fetches the matching prebuilt release archive for your platform and exposes the shk command, so it supports the same platforms as the release archives.
For one-off runs without a global install:
npx security-harness-kit scanbun
The same package works with bun. The package's postinstall script downloads the binary at install time; when bun skips lifecycle scripts, which is its default for packages it does not trust, the shk launcher fetches the matching release archive on the first run instead, so the install still works:
bun add -g security-harness-kit
shk --versionFor one-off runs without a global install:
bunx security-harness-kit scanInstall With Script
macOS and Linux releases can be installed with the bundled installer:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Kazuki-tam/security-harness-kit/releases/latest/download/shk-cli-installer.sh | shWindows releases can be installed from PowerShell:
powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://github.com/Kazuki-tam/security-harness-kit/releases/latest/download/shk-cli-installer.ps1 | iex"-ExecutionPolicy Bypass is scoped to this one PowerShell process, so it avoids common script policy failures without changing the user's machine or profile policy. If you are already in PowerShell, this equivalent form also works:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force; irm https://github.com/Kazuki-tam/security-harness-kit/releases/latest/download/shk-cli-installer.ps1 | iexIf your organization enforces PowerShell through MachinePolicy or UserPolicy, the script installer may still be blocked. In that case, install with npm or bun instead, or download the .zip archive and verify its checksum by hand (see Download A Release Archive).
The installers are generated by dist and download the latest matching release archive. The shell installer verifies the selected archive against the SHA-256 checksum embedded at release time before installing shk. The generated PowerShell installer does not currently perform checksum verification; Windows users who require verification should verify the .zip archive manually. By default, script installers use the Cargo-style install path ($CARGO_HOME/bin, or ~/.cargo/bin when CARGO_HOME is unset).
Download A Release Archive
Tagged releases publish platform archives, per-archive checksums, installers, a Homebrew formula, maintainer WinGet manifests, and a CycloneDX SBOM:
shk-cli-aarch64-apple-darwin.tar.xz
shk-cli-aarch64-unknown-linux-gnu.tar.xz
shk-cli-x86_64-apple-darwin.tar.xz
shk-cli-x86_64-pc-windows-msvc.zip
shk-cli-x86_64-unknown-linux-gnu.tar.xz
shk-cli-installer.sh
shk-cli-installer.ps1
shk-winget-manifests.zip
shk.rb
shk-cli-npm-package.tar.gz
*-dist-manifest.json
*.sha256
shk-sbom.cdx.jsonVerify the archive before unpacking:
shasum -a 256 -c shk-cli-x86_64-unknown-linux-gnu.tar.xz.sha256Each archive contains the shk binary. Tagged releases also generate GitHub artifact attestations for release assets. Verify a downloaded asset with the GitHub CLI:
gh attestation verify shk-cli-x86_64-unknown-linux-gnu.tar.xz \
--repo Kazuki-tam/security-harness-kitOn Windows, download shk-cli-x86_64-pc-windows-msvc.zip and its .sha256 file, compare Get-FileHash -Algorithm SHA256 against the checksum, unpack shk.exe, and place it in a directory on PATH (the installer default is %USERPROFILE%\.cargo\bin).
Verified Archive Install
For CI or security-sensitive environments, install from a pinned release tag and verify both the checksum and the GitHub artifact attestation before placing the binary on PATH:
version=v0.7.4
target=x86_64-unknown-linux-gnu
asset="shk-cli-${target}.tar.xz"
repo=Kazuki-tam/security-harness-kit
gh release download "$version" -R "$repo" -p "$asset" -p "${asset}.sha256"
shasum -a 256 -c "${asset}.sha256"
gh attestation verify "$asset" -R "$repo"
tmp="$(mktemp -d)"
tar -xJf "$asset" -C "$tmp"
install -m 755 "$tmp/shk-cli-${target}/shk" "$HOME/.cargo/bin/shk"Replace target with the archive that matches your platform. Avoid latest in CI so builds are reproducible and reviewable. shk ci init github generates a workflow that performs exactly this verified install.
Homebrew
Each tagged CLI release publishes the generated Homebrew formula to the public tap Kazuki-tam/homebrew-tap. Install with:
brew install Kazuki-tam/homebrew-tap/shkHomebrew drops the homebrew- prefix, so the short form also works:
brew install kazuki-tam/tap/shkThe formula always tracks the latest release. To upgrade later, run brew upgrade shk.
Alternatively, the formula (shk.rb) is attached to each release as an asset and can be installed from a local copy without the tap. Current Homebrew refuses to install a formula straight from an https:// URL, so download the file first:
curl -LO https://github.com/Kazuki-tam/security-harness-kit/releases/latest/download/shk.rb
brew install --formula ./shk.rbTo install a pinned release this way, replace latest/download with download/<tag> (e.g. download/v0.7.4).
Intel macOS, Apple Silicon macOS, Linux x86_64/aarch64, and Windows x86_64 are supported. Scoop manifests are not published by the current release pipeline.
Desktop App
The desktop app is distributed separately from the CLI and adds a GUI on top of
it: the hooks its Quick Setup installs run the shk command, so keep the CLI
installed as well (see Desktop App). Releases are published
from desktop-vX.Y.Z (or combined shk-vX.Y.Z) tags as shk-desktop_* assets
on GitHub Releases. Starting with desktop-v0.6.0, macOS builds are
Developer ID signed, notarized, and stapled. Windows installers are currently
not Authenticode-signed (see
Windows SmartScreen below).
The Mask screen can redact ([REDACTED]) or pseudonymize (consistent codes)
content before it goes to an AI tool. Pseudonymize needs a project with
shk.toml selected because the key that keeps codes consistent is stored per
project, in the same credential store the CLI uses; the first run from the app
asks before creating it, and macOS may ask once before the app can read a key
the CLI created (or the other way round), since they are separate signed
binaries. See Desktop App → Pseudonymize for the
app flow and shk mask --pseudonymize for the
underlying behaviour and restore maps.
See desktop-release.md for maintainer release steps.
Choose an installer
| Platform | Asset pattern | Notes |
|---|---|---|
| Linux x86_64 | shk-desktop_*_x86_64-unknown-linux-gnu_*.AppImage or *.deb |
AppImage needs chmod +x |
| Linux aarch64 | shk-desktop_*_aarch64-unknown-linux-gnu_*.AppImage or *.deb |
Same as above |
| macOS Intel | shk-desktop_*_x86_64-apple-darwin_*.dmg |
Signed and notarized; drag shk.app to /Applications |
| macOS Apple Silicon | shk-desktop_*_aarch64-apple-darwin_*.dmg |
Same as above |
| Windows x86_64 | shk-desktop_*_x86_64-pc-windows-msvc_*setup.exe or *.msi |
Currently unsigned |
Stable download links
The desktop-latest release always carries the installers from the newest
signed desktop release under version-free names, so these URLs never change:
desktop-latest also carries shk-desktop.sha256sum for the stable names and
shk-desktop-latest.json, whose release_tag says which versioned release the
stable files currently come from. The files are byte-identical to the
shk-desktop_* assets of that release, so its provenance attestation verifies
them too.
Verify a stable download:
curl -LO https://github.com/Kazuki-tam/security-harness-kit/releases/download/desktop-latest/shk-desktop-aarch64-apple-darwin.dmg
curl -LO https://github.com/Kazuki-tam/security-harness-kit/releases/download/desktop-latest/shk-desktop.sha256sum
awk '$2 == "shk-desktop-aarch64-apple-darwin.dmg"' shk-desktop.sha256sum \
| shasum -a 256 -c -To pin a specific version instead, download the versioned shk-desktop_*
assets and shk-desktop.sha256sum from that tag's release page, for example
desktop-v0.7.4.
macOS
Installers from desktop-v0.6.0 onward are Developer ID signed and notarized;
Gatekeeper opens them without workarounds. If you still run an older unsigned
early access build, replace it with a signed .dmg install — the in-app
updater also migrates existing installs because all releases share the same
Tauri updater signing keys.
Windows SmartScreen
Windows installers are currently not Authenticode-signed, so SmartScreen may show Windows protected your PC. Choose More info → Run anyway if you trust the release checksum and attestation.
Blocked-activity notifications
While the app is open it tails .shk/audit.log for every project in the
sidebar and raises an OS notification when a hook blocks AI activity, so an
agent running in the background is visible without switching to the app. The
bell menu in the top bar turns notifications off, or narrows them to one kind
of block; both kinds are on by default.
Details worth knowing:
- Only blocks recorded after a project appears in the sidebar are announced — existing history never produces a backlog of notifications.
- Blocks arriving within a few seconds collapse into a single notification.
- Notification text is limited to the block reason, the risky-action category, and the AI tool. File paths are deliberately left out, because notifications render on the lock screen and are persisted by the OS; use the Blocked AI activity panel to see them.
- Turning notifications off stops the banners, not the tailing: the audit panel still updates while the app is open.
- The first block prompts for OS notification permission (on macOS the
installed app appears as shk; a
tauri devbinary sends through the Terminal identity instead, so allow Terminal notifications when testing). - No banner but blocks listed in the panel almost always means macOS is suppressing display: check Focus mode, and the per-app notification style in System Settings → Notifications.
In-app updates
The desktop app checks desktop-latest/latest.json on GitHub for updater
metadata. Updater packages are always signed with the project Tauri updater
key, independent of OS code signing. Update steps are in
Update The Desktop App.
Build From Source
Building from source requires Rust 1.88 or newer.
git clone https://github.com/Kazuki-tam/security-harness-kit.git
cd security-harness-kit
cargo build --releaseThe release binaries are written to:
target/release/shkUpdate
shk has no self-update command. Update the CLI with the same tool you installed it with, and update the desktop app from its top bar. The two are versioned and updated independently: updating one never touches the other.
Check For A New Release
shk --version prints the installed version. shk status and shk doctor version compare it with the latest GitHub release; they are the only commands that contact the network for version information (see shk doctor version):
shk --version
shk status
shk doctor versionIf several copies of shk are on PATH (for example one from npm and one from the installer script), the first one wins and the others stay at their old version. shk doctor prints an shk executable section with the running binary, the first shk on PATH, and a warning that lists every distinct installation it found. Update the copy that is first on PATH, or remove the extra ones.
Update The CLI
| Install method | Update |
|---|---|
| npm | npm install -g security-harness-kit@latest |
| bun | bun add -g security-harness-kit@latest |
| Installer script | Re-run the same curl ... | sh or PowerShell command from Install With Script; it downloads the latest release and overwrites the binary in place. |
| Homebrew tap | brew upgrade shk |
Homebrew formula file (shk.rb) |
A formula installed from a file belongs to no tap, so brew upgrade cannot find newer versions. Download the new shk.rb, run brew uninstall shk, then brew install --formula ./shk.rb. |
| Release archive | Repeat the steps in Download A Release Archive or Verified Archive Install with the new tag and overwrite the existing binary. |
| Build from source | git pull in the clone, then cargo build --release and copy the binary over the installed one. |
Verify afterwards with shk --version.
After Updating The CLI
- Hooks installed by
shk hooks installandshk hooks install-aiinvokeshkfromPATH, so they use the new binary the next time they fire. No reinstall is needed. - Skills are static files copied by
shk skills install. Re-run it with--force(and--globalfor user-level installs) to pick up a newer bundled skill. - CI workflows generated by
shk ci init githubpin the release that generated them. Re-run with--shk-version <new tag> --forceto move the pin (see Pin A Release). shk statusshould now report the new version as current.
Update The Desktop App
The desktop app does not check for updates on its own. Choose Check updates in the top bar; when a newer release exists, the app offers Download and restart, downloads the signed updater package, and relaunches. Installs from the macOS .dmg, the Windows setup.exe, and the Linux AppImage update this way. Do not use it for a Windows .msi or Linux .deb install: download the new package from the stable download links and install it over the existing version. Full details are in Desktop App → In-app updates.
Uninstall
shk does not ship a dedicated shk uninstall command. Removal has two layers: the CLI binary, and any project or user-level files written by shk while it was in use.
1. Remove The Binary
Pick the method that matches how shk was installed.
Script installer (default ~/.cargo/bin):
rm -f "${CARGO_HOME:-$HOME/.cargo}/bin/shk"Windows (PowerShell installer; default %USERPROFILE%\.cargo\bin when CARGO_HOME is unset):
$BinDir = if ($env:CARGO_HOME) { Join-Path $env:CARGO_HOME "bin" } else { "$env:USERPROFILE\.cargo\bin" }
Remove-Item (Join-Path $BinDir "shk.exe") -ErrorAction SilentlyContinueHomebrew formula:
brew uninstall shk
# If installed from a tap, you can also remove it:
# brew untap Kazuki-tam/homebrew-tapnpm package:
npm uninstall -g security-harness-kitbun package:
bun remove -g security-harness-kitSource build: run cargo clean in the cloned repository to remove build output, or remove target/release/shk directly. If you copied that binary into a directory on PATH, remove the copied binary there as well.
2. Remove Project Artifacts
shk does not modify project files unless you explicitly run a command that writes to disk. The artifacts created by those commands are listed below. Remove any that you no longer need from each project.
| Source | Path | Notes |
|---|---|---|
shk init / shk policy init |
shk.toml |
Project policy file. |
shk init with npm hardening |
.npmrc, pnpm-workspace.yaml, .yarnrc.yml, bunfig.toml as applicable |
Project package-manager hardening files. Remove only settings added for ignore-scripts or package age gates if the file also contains your own package-manager configuration. |
shk scan --audit, audit-mode hooks |
.shk/audit.log and the .shk/ directory |
Metadata-only audit log. |
shk hooks install |
.git/hooks/pre-commit |
Managed block delimited by # shk-managed-start / # shk-managed-end. Delete the file if shk is the only owner, or remove just the managed block to keep other pre-commit logic. |
shk hooks install-ai (Claude Code) |
.claude/settings.json |
Remove entries tagged with "_shk_managed": true. Delete the file if it has no remaining entries. If you used --apply-deny or --apply-sandbox, also review the permissions.deny and sandbox settings that were merged into the same file. |
shk hooks install-ai (Cursor) |
.cursor/hooks.json |
Remove entries tagged with "_shk_managed": true. |
shk hooks install-ai (Codex) |
.codex/config.toml |
Remove the block delimited by # shk-managed-start / # shk-managed-end, and features.hooks = true if no longer needed. The managed block covers PreToolUse, PermissionRequest, UserPromptSubmit, and PostToolUse. If you used --apply-sandbox, also review the top-level sandbox_mode and approval_policy values. |
shk hooks install-ai (Copilot) |
.github/hooks/shk-security.json |
Remove entries whose command contains shk scan --hook-mode copilot. |
shk hooks install-ai (Antigravity) |
.agents/hooks.json |
Remove the top-level shk-security entry (its hook entries are tagged with "_shk_managed": true). Delete the file if it has no remaining entries. |
shk hooks install-ai (Grok Build) |
.grok/hooks/shk-security.json |
Remove handlers whose command contains shk scan --hook-mode grok, and any matcher groups left empty. Delete the file if it has no remaining entries. |
shk hooks install-ai (Windsurf) |
.windsurf/hooks.json |
Remove entries whose command contains shk scan --hook-mode windsurf. Delete the file if it has no remaining entries. |
shk skills install (Claude Code) |
.claude/skills/shk/SKILL.md |
Bundled skill file. Installs from 0.3.17 or earlier used .claude/skills/shk.md; remove that file too if present. |
shk skills install (Copilot) |
.github/skills/shk/SKILL.md |
Bundled skill file. |
shk skills install (Codex / Cursor / Antigravity) |
.agents/skills/shk/SKILL.md |
Bundled skill file. |
shk skills install (Grok Build) |
.grok/skills/shk/SKILL.md |
Bundled skill file. |
shk skills install (Windsurf) |
.windsurf/skills/shk/SKILL.md |
Bundled skill file. |
shk ci init github |
.github/workflows/shk.yml by default |
Generated GitHub Actions workflow. If you passed --output, remove that custom path instead. |
For commands that support it, re-running with --dry-run is a safe way to confirm the exact paths used in your project before deleting them. This applies to shk hooks install-ai, shk skills install, and shk ci init github; shk hooks install and shk init do not have a dry-run mode.
3. Remove User-Level Files
--global installs write to the user's home directory instead of the project. Remove these only if you want to disable shk for every project on this machine.
| Source | Path |
|---|---|
shk hooks install-ai --global --tool claude-code |
~/.claude/settings.json (managed entries, plus any permissions.deny or sandbox settings you explicitly enabled) |
shk hooks install-ai --global --tool codex |
~/.codex/config.toml (managed block, plus top-level sandbox settings if you used --apply-sandbox) |
shk hooks install-ai --global --tool cursor |
~/.cursor/hooks.json (managed entries) |
shk hooks install-ai --global --tool copilot |
~/.copilot/hooks/shk-security.json (managed entries) |
shk hooks install-ai --global --tool antigravity |
~/.gemini/config/hooks.json (managed shk-security entry) |
shk hooks install-ai --global --tool grok |
~/.grok/hooks/shk-security.json (managed entries identified by --hook-mode grok) |
shk hooks install-ai --global --tool windsurf |
~/.codeium/windsurf/hooks.json (managed entries identified by --hook-mode windsurf) |
shk skills install --global --tool claude-code |
~/.claude/skills/shk/SKILL.md (or the legacy ~/.claude/skills/shk.md from 0.3.17 or earlier) |
shk skills install --global --tool codex / --tool cursor |
~/.agents/skills/shk/SKILL.md |
shk skills install --global --tool copilot |
~/.copilot/skills/shk/SKILL.md |
shk skills install --global --tool antigravity |
~/.gemini/config/skills/shk/SKILL.md |
shk skills install --global --tool grok |
~/.grok/skills/shk/SKILL.md |
shk skills install --global --tool windsurf |
~/.codeium/windsurf/skills/shk/SKILL.md |
Managed entries use the same markers as project installs ("_shk_managed": true for JSON files, # shk-managed-start / # shk-managed-end for shell and TOML files). Copilot, Grok Build, and Windsurf keep schema-clean JSON and are identified by their --hook-mode <tool> command strings. Settings merged by --apply-deny and --apply-sandbox are not individually tagged; review them before removing so you do not discard unrelated user configuration.
4. Remove Stored Env Keys
If you used shk env dotenvx import-keys or shk env key import / shk env encrypt, delete stored private keys before removing the binary so they are not orphaned. Stored keys are scoped to the canonical project root, so run this from each project where keys were stored:
shk env dotenvx delete --all
shk env key delete --allWhen [env].secret_store = "keyring" (the default), dotenvx keys live under the OS credential service security-harness-kit/dotenvx, and native keys live under security-harness-kit/env. If shk has already been removed, search for those service names in the platform credential store UI.
When [env].secret_store = "1password", keys are stored as tagged 1Password items (shk tag) in the vault configured by env.onepassword.vault. Item titles look like shk:{project_id}:env:DOTENV_PRIVATE_KEY or shk:{project_id}:dotenvx:DOTENV_PRIVATE_KEY_PRODUCTION. Delete them from the vault UI, or migrate back to the keyring first:
shk env key migrate --to keyringVerify the keyring copy, then remove the old tagged items explicitly from 1Password. Automatic source deletion is intentionally refused for a shared 1Password source.