Migration guide
Version upgrades and breaking changes
Overview
This page documents breaking changes between versions and how to upgrade. klaudiush follows semantic versioning - breaking changes only happen in minor version bumps during the pre-1.0 phase.
v1.24.0 - XDG base directory migration
v1.24.0 moves all global/user-level paths to follow the XDG Base Directory specification. Files that previously lived under ~/.klaudiush/ are
split across config, data, and state directories.
| Old path | New path (XDG) |
|---|---|
~/.klaudiush/config.toml | $XDG_CONFIG_HOME/klaudiush/config.toml |
~/.claude/hooks/dispatcher.log | $XDG_STATE_HOME/klaudiush/dispatcher.log |
~/.klaudiush/exceptions/state.json | $XDG_DATA_HOME/klaudiush/exceptions/state.json |
~/.klaudiush/exception_audit.jsonl | $XDG_STATE_HOME/klaudiush/exception_audit.jsonl |
~/.klaudiush/crash_dumps/ | $XDG_DATA_HOME/klaudiush/crash_dumps/ |
~/.klaudiush/patterns/ | $XDG_DATA_HOME/klaudiush/patterns/ |
~/.klaudiush/.backups/ | $XDG_DATA_HOME/klaudiush/backups/ |
~/.klaudiush/plugins/ | $XDG_DATA_HOME/klaudiush/plugins/ |
# Default XDG locations (when env vars are not set)
# $XDG_CONFIG_HOME = ~/.config
# $XDG_DATA_HOME = ~/.local/share
# $XDG_STATE_HOME = ~/.local/state
# So the global config defaults to:
~/.config/klaudiush/config.toml
# Logs default to:
~/.local/state/klaudiush/dispatcher.log What happens on upgrade
On first run after upgrade, klaudiush detects the old ~/.klaudiush/ directory and moves files to their XDG locations. The migration is automatic and
idempotent - running it twice is safe.
- Files are moved, not copied
- Symlinks are created at
~/.klaudiush/config.tomland~/.claude/hooks/dispatcher.logfor backward compatibility - Files that already exist at the destination are skipped
- Custom absolute paths in your config are not affected
- Project-local paths (
.klaudiush/config.toml,.klaudiush/patterns.json,.klaudiush/plugins/) are unchanged
Verifying the migration
Run the XDG doctor category to check migration status and directory permissions:
# Check XDG migration status and directory layout
klaudiush doctor --category xdg
# Auto-fix: migrate remaining files and create missing directories
klaudiush doctor --fix --category xdg New environment variable
KLAUDIUSH_LOG_FILE overrides the log file location. When set,
klaudiush writes logs to this path instead of the XDG state directory.
v1.18.0 - JSON stdout output
v1.18.0 changed how klaudiush communicates with Claude Code. Instead of exit codes, it uses JSON stdout for all responses.
Before (v1.17 and earlier):
Block: exit code 2, formatted text to stderr
Allow: exit code 0
After (v1.18+):
Block: exit 0, JSON stdout with permissionDecision: "deny"
Allow: exit 0, JSON stdout with permissionDecision: "allow"
Crash: exit 3 (panic recovery) Exit code change
If you have scripts that check for exit code 2, they need to parse JSON stdout instead. Exit code 2 is no longer used.
The reason for this change: Claude Code conflates exit code 2 with user denials. With JSON output, the model gets structured error information and can self-correct. See ADR-0001 for the full rationale.
JSON output format
The JSON output includes separate fields for model-facing and user-facing messages:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "[GIT001] Message for the model",
"additionalContext": "Extra context"
},
"systemMessage": "Message for the user"
} | Field | Purpose |
|---|---|
permissionDecision | deny or allow - replaces exit code |
permissionDecisionReason | Error code and message for the model to self-correct |
additionalContext | Extra context the model can use |
systemMessage | Message shown to the user in the terminal |
Upgrade steps
For most users, upgrading is just updating the binary. Configuration files are backwards-compatible - all existing configs continue to work.
# 1. Update klaudiush
brew upgrade klaudiush
# or
curl -sSfL https://klaudiu.sh/install.sh | sh
# 2. Verify version
klaudiush version
# 3. Run doctor to check setup
klaudiush doctor
# 4. Test validation still works
echo '{"tool_name":"Bash","command":"git commit -m fix"}' | klaudiush --hook-type PreToolUse klaudiush also has a self-update command:
# Check for updates
klaudiush update --check
# Update to latest
klaudiush update
# Update to specific version
klaudiush update --to v1.20.0 On first run after upgrade, klaudiush automatically backs up your existing config
before applying any changes. You can restore the backup with klaudiush backup restore if anything goes wrong.