Compare commits
8
Commits
75dcd21776
...
e55f053efb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e55f053efb | ||
|
|
7ec89551cc | ||
|
|
2c6236135c | ||
|
|
47fe0fbc0e | ||
|
|
31439db2f8 | ||
|
|
64f3e2b320 | ||
|
|
c86c24ed9b | ||
|
|
3ca85c3bfb |
@@ -0,0 +1,3 @@
|
||||
[submodule "mattpocock-skills"]
|
||||
path = mattpocock-skills
|
||||
url = ssh://git@git.grosinger.net:22322/tgrosinger/mattpocock-skills.git
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/code-review
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/codebase-design
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/diagnosing-bugs
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/domain-modeling
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/grill-with-docs
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/productivity/grilling
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/productivity/handoff
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/implement
|
||||
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/improve-codebase-architecture
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/prototype
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/research
|
||||
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/resolving-merge-conflicts
|
||||
|
Before Width: | Height: | Size: 420 B After Width: | Height: | Size: 420 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/tdd
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/productivity/teach
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/productivity/to-questionnaire
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/to-spec
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/to-tickets
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/productivity/wait-what
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/wayfinder
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/engineering/wizard
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../mattpocock-skills/skills/productivity/writing-for-agents
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Source: https://github.com/mattpocock/skills
|
||||
|
||||
INPUT=$(cat)
|
||||
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')
|
||||
|
||||
DANGEROUS_PATTERNS=(
|
||||
"git push"
|
||||
"git reset --hard"
|
||||
"git clean -fd"
|
||||
"git clean -f"
|
||||
"git branch -D"
|
||||
"git checkout \."
|
||||
"git restore \."
|
||||
"push --force"
|
||||
"reset --hard"
|
||||
)
|
||||
|
||||
for pattern in "${DANGEROUS_PATTERNS[@]}"; do
|
||||
if echo "$COMMAND" | grep -qE "$pattern"; then
|
||||
echo "BLOCKED: '$COMMAND' matches dangerous pattern '$pattern'. The user has prevented you from doing this." >&2
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Blocks Bash commands that delete or destroy files.
|
||||
# Companion to CLAUDE.md's "never delete files" rule.
|
||||
|
||||
block() {
|
||||
printf 'BLOCKED: %s\n' "$1" >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
command -v jq >/dev/null 2>&1 || block "jq is required to validate Bash commands."
|
||||
command -v realpath >/dev/null 2>&1 || block "realpath is required to validate deletion paths."
|
||||
command -v stat >/dev/null 2>&1 || block "stat is required to validate the temporary directory."
|
||||
|
||||
INPUT=$(cat) || block "could not read hook input."
|
||||
COMMAND=$(printf '%s' "$INPUT" | jq -er '.tool_input.command | select(type == "string")') ||
|
||||
block "hook input does not contain a valid tool_input.command string."
|
||||
|
||||
# Do not trust TMPDIR: when it is unset, `$TMPDIR/path` expands to `/path`.
|
||||
# This fixed per-user directory is the only place where deletion is permitted.
|
||||
TMP_ROOT="/tmp/claude-$(id -u)"
|
||||
|
||||
# True only for one command in one of these exact forms:
|
||||
# rm -- /tmp/claude-UID/path [...]
|
||||
# rm -f|-r|-rf|-fr -- /tmp/claude-UID/path [...]
|
||||
#
|
||||
# Paths are deliberately restricted to an unquoted, expansion-free character
|
||||
# set. The filesystem checks reject an escaping canonical path and any symlink
|
||||
# that already exists in the path. This is defense against accidental deletion,
|
||||
# not a race-free security boundary against a process changing paths concurrently.
|
||||
confined_to_tmp() {
|
||||
local cmd="$1" option_part path_part path canonical component partial mode uid
|
||||
local -a paths components
|
||||
|
||||
uid=$(id -u) || return 1
|
||||
[[ -d "$TMP_ROOT" && ! -L "$TMP_ROOT" ]] || return 1
|
||||
[[ "$(realpath -e -- "$TMP_ROOT" 2>/dev/null)" == "$TMP_ROOT" ]] || return 1
|
||||
[[ "$(stat -c '%u' -- "$TMP_ROOT" 2>/dev/null)" == "$uid" ]] || return 1
|
||||
mode=$(stat -c '%a' -- "$TMP_ROOT" 2>/dev/null) || return 1
|
||||
(( (8#$mode & 0022) == 0 )) || return 1
|
||||
|
||||
if [[ "$cmd" =~ ^rm\ (--|-f\ --|-r\ --|-rf\ --|-fr\ --)\ (/tmp/claude-[0-9]+/[A-Za-z0-9._/+,=:@%-]+(\ /tmp/claude-[0-9]+/[A-Za-z0-9._/+,=:@%-]+)*)$ ]]; then
|
||||
option_part="${BASH_REMATCH[1]}"
|
||||
path_part="${BASH_REMATCH[2]}"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
|
||||
# The regex excludes shell syntax and whitespace within paths, so this split
|
||||
# does not attempt to interpret arbitrary Bash source.
|
||||
read -r -a paths <<< "$path_part"
|
||||
((${#paths[@]} > 0)) || return 1
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
[[ "$path" == "$TMP_ROOT"/?* ]] || return 1
|
||||
[[ "$path" != */./* && "$path" != */../* && "$path" != */. && "$path" != */.. ]] || return 1
|
||||
|
||||
canonical=$(realpath -m -- "$path" 2>/dev/null) || return 1
|
||||
[[ "$canonical" == "$TMP_ROOT"/?* ]] || return 1
|
||||
|
||||
# realpath catches symlink escapes. Reject in-tree symlinks too, since rm
|
||||
# must not traverse a link whose target happens to currently be in the tree.
|
||||
partial=""
|
||||
IFS='/' read -r -a components <<< "$path"
|
||||
for component in "${components[@]}"; do
|
||||
[[ -n "$component" ]] || continue
|
||||
partial="$partial/$component"
|
||||
[[ ! -L "$partial" ]] || return 1
|
||||
done
|
||||
done
|
||||
|
||||
# Keep the variable used so shellcheck documents that only allowlisted option
|
||||
# spellings can reach this point.
|
||||
[[ -n "$option_part" ]]
|
||||
}
|
||||
|
||||
confined_to_tmp "$COMMAND" && exit 0
|
||||
|
||||
# These patterns are a backstop for ordinary Bash spellings, not a parser.
|
||||
# Include quotes and backslashes between letters to catch forms such as r""m
|
||||
# and r\m that Bash resolves to rm.
|
||||
DANGEROUS_PATTERNS=(
|
||||
'\br["'"'"'\\]*m\b'
|
||||
'\bu["'"'"'\\]*n["'"'"'\\]*l["'"'"'\\]*i["'"'"'\\]*n["'"'"'\\]*k\b'
|
||||
'\br["'"'"'\\]*m["'"'"'\\]*d["'"'"'\\]*i["'"'"'\\]*r\b'
|
||||
'\bshred\b'
|
||||
'\btruncate\b'
|
||||
'\bfind\b.*-delete\b'
|
||||
'\btrash\b'
|
||||
)
|
||||
|
||||
for pattern in "${DANGEROUS_PATTERNS[@]}"; do
|
||||
if printf '%s\n' "$COMMAND" | grep -qE "$pattern"; then
|
||||
block "'$COMMAND' is a deletion command. Only literal 'rm [-f|-r|-rf|-fr] -- $TMP_ROOT/path' commands without variables, quotes, globs, shell operators, or symlinks are allowed."
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
@@ -18,9 +18,6 @@
|
||||
"Bash(ssh *)",
|
||||
"Bash(ssh)",
|
||||
"Bash(scp *)",
|
||||
"Bash(rm:*)",
|
||||
"Bash(unlink:*)",
|
||||
"Bash(rmdir:*)",
|
||||
"Bash(shred:*)",
|
||||
"Bash(truncate:*)",
|
||||
"Bash(trash:*)",
|
||||
@@ -33,7 +30,7 @@
|
||||
],
|
||||
"defaultMode": "auto"
|
||||
},
|
||||
"model": "opus[1m]",
|
||||
"model": "claude-opus-4-8",
|
||||
"disableClaudeAiConnectors": true,
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
@@ -146,7 +143,7 @@
|
||||
"Thinking"
|
||||
]
|
||||
},
|
||||
"effortLevel": "high",
|
||||
"effortLevel": "xhigh",
|
||||
"tui": "fullscreen",
|
||||
"voice": {
|
||||
"enabled": false,
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../.agents/skills
|
||||
@@ -4,6 +4,8 @@ workspaces = true
|
||||
keymap_mode = "auto"
|
||||
enter_accept = true
|
||||
|
||||
sync_address = "https://atuin.i.grosinger.net"
|
||||
|
||||
history_filter = [
|
||||
"^cd$",
|
||||
"^lg$",
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
# Interactive sessions get exact versions from `mise activate` below.
|
||||
fish_add_path --global ~/.local/bin ~/.local/share/mise/shims ~/go/bin
|
||||
|
||||
if test -d ~/code/yt-dlp
|
||||
fish_add_path --global ~/code/yt-dlp
|
||||
end
|
||||
|
||||
if status is-interactive
|
||||
# Commands to run in interactive sessions can go here
|
||||
|
||||
|
||||
@@ -21,3 +21,4 @@ pnpm = "latest"
|
||||
"github:Satty-org/Satty" = "0.20.1"
|
||||
"github:F1bonacc1/process-compose" = "latest"
|
||||
"npm:@earendil-works/pi-coding-agent" = "latest"
|
||||
uv = "latest"
|
||||
|
||||
@@ -90,9 +90,6 @@
|
||||
[status]
|
||||
submoduleSummary = true
|
||||
|
||||
[url "ssh://git@gitlab.i.extrahop.com/"]
|
||||
insteadOf = https://gitlab.i.extrahop.com/
|
||||
|
||||
[merge]
|
||||
conflictstyle = zdiff3
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#/bin/bash
|
||||
|
||||
podman run --rm -i \
|
||||
-v ${HOME}/Music:/downloads:z \
|
||||
--userns keep-id:uid=1000,gid=1000 \
|
||||
--entrypoint spotdl \
|
||||
yt-dlp:latest $@
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#/bin/bash
|
||||
|
||||
podman run --rm \
|
||||
-v ${HOME}/Videos/youtube:/downloads:z \
|
||||
--userns keep-id:uid=1000,gid=1000 \
|
||||
yt-dlp:latest -S 'res:1080' --extractor-args "youtube:player-client=web_embedded" $@
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#/bin/bash
|
||||
|
||||
podman run --rm \
|
||||
-v ${HOME}/Videos/youtube:/downloads:z \
|
||||
--userns keep-id:uid=1000,gid=1000 \
|
||||
yt-dlp:latest --embed-metadata -o "%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s" -S 'res:1080' $@
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"lastChangelogVersion": "0.79.8",
|
||||
"lastChangelogVersion": "0.83.0",
|
||||
"theme": "catppuccin-latte",
|
||||
"defaultProvider": "openai-codex",
|
||||
"defaultModel": "gpt-5.5",
|
||||
"defaultModel": "gpt-5.6-luna",
|
||||
"defaultThinkingLevel": "high",
|
||||
"skills": [
|
||||
"~/.claude/skills"
|
||||
|
||||
Submodule
+1
Submodule mattpocock-skills added at 0bec6ef0f5
Reference in New Issue
Block a user