[Sync] llm stuff

This commit is contained in:
Coja
2026-09-17 20:58:21 +02:00
parent ed7e34552d
commit d8f6b30e2c
52 changed files with 2233 additions and 237 deletions
+55 -9
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""PostToolUse hook: format an edited file with the right formatter.
Reads the hook JSON from stdin, extracts the edited file path, and runs a
Reads the hook JSON from stdin, works out which file(s) were just edited, and runs a
language-appropriate formatter -- but, to avoid imposing a style on a project
that never asked for it, every formatter here only runs when the project opts in
via a config file discoverable by walking up from the edited file: stylua, ruff,
@@ -9,6 +9,15 @@ prettier and taplo on their own configs, gofmt and rustfmt on go.mod / Cargo.tom
shfmt and fish_indent on .editorconfig. No marker, no formatting -- a repo that
hand-formats its shell keeps its own layout.
Two entry points, both wired in settings.json > hooks > PostToolUse:
* Edit|Write -- the edited path is `tool_input.file_path`.
* Bash -- under `defaultMode: auto` Claude is steered to edit through the shell
(sed -i, heredocs, python), which the Edit|Write matcher never sees.
There is no per-file event for that (`FileChanged` only watches literal
filenames), so this scans `tool_input.command` for path-like tokens with a
handled extension and formats the ones modified in the last few seconds --
the mtime gate keeps a parallel session's dirty files out of it.
Best-effort: always exits 0 so a format hiccup never blocks an edit. jq is not
guaranteed on the host, hence python for the stdin JSON parse.
"""
@@ -19,6 +28,7 @@ import re
import shutil
import subprocess
import sys
import time
def find_up(start, names):
@@ -178,14 +188,13 @@ HANDLERS = {
}
def main():
try:
data = json.load(sys.stdin)
except Exception:
return
ti = data.get("tool_input") or {}
tr = data.get("tool_response") or {}
path = ti.get("file_path") or tr.get("filePath") or ""
RECENT_SECS = 30 # a Bash edit is "ours" if the file changed this recently
_EXT_ALT = "|".join(re.escape(e[1:]) for e in HANDLERS)
_PATHISH = re.compile(r"[\w.~/@+-]+\.(?:" + _EXT_ALT + r")\b")
def format_one(path):
if not path or not os.path.isfile(path):
return
# Resolve symlinks before walking for markers: deployed dotfiles get edited via
@@ -204,5 +213,42 @@ def main():
pass
def recent_paths_in_command(command, cwd):
"""Files a shell command plausibly just wrote: path-like tokens with a handled
extension, resolved against the tool's cwd, that exist and changed within RECENT_SECS.
Unchanged mentions (the source of a `cp`, a file merely grepped) fail the mtime gate."""
now = time.time()
seen, out = set(), []
for tok in _PATHISH.findall(command or ""):
p = os.path.expanduser(tok)
if not os.path.isabs(p):
p = os.path.join(cwd, p)
p = os.path.normpath(p)
if p in seen:
continue
seen.add(p)
try:
if os.path.isfile(p) and now - os.path.getmtime(p) <= RECENT_SECS:
out.append(p)
except OSError:
pass
return out
def main():
try:
data = json.load(sys.stdin)
except Exception:
return
ti = data.get("tool_input") or {}
tr = data.get("tool_response") or {}
if data.get("tool_name") == "Bash":
cwd = data.get("cwd") or os.getcwd()
for p in recent_paths_in_command(ti.get("command"), cwd):
format_one(p)
return
format_one(ti.get("file_path") or tr.get("filePath") or "")
if __name__ == "__main__":
main()