Commit 701cf5b59d0e
Changed files (7)
dots
config
pi
agent
dots/config/claude/skills/CORE/hook-system.md
@@ -278,7 +278,7 @@ Claude Code supports these additional hook events that are **not currently confi
**When:** Before Claude compacts context (long conversations)
**Use Cases:** Preserve important context, log compaction events
-To configure these events, add them to `/home/vincent/.config/claude/settings.json` in the `"hooks"` section. You would need to create corresponding Go implementations in the `claude-hooks` project.
+To configure these events, add them to `~/.config/claude/settings.json` in the `"hooks"` section with a corresponding TypeScript hook in `~/.config/claude/hooks/`.
---
@@ -518,51 +518,15 @@ func shouldDebounce() bool {
## Installation and Setup
-### Building from Source (Nix)
+### Source Location
-```bash
-cd /home/vincent/src/home
-
-# Build all hooks
-# Old Nix build (removed)
-
-# Install to user profile
-# No longer needed - hooks are TypeScript
-```
-
-### Adding to Home Manager
-
-In your `home.nix` or equivalent:
-```nix
-home.packages = with pkgs; [
- claude-hooks
-];
-```
-
-### Manual Setup
-
-```bash
-cd /home/vincent/src/home/tools/claude-hooks
-
-# Build all hooks
-# Old Go build: bun run ~/.config/claude/hooks/initialize-session.ts ./cmd/initialize-session
-# Old Go build: bun run ~/.config/claude/hooks/capture-tool-output.ts ./cmd/capture-tool-output
-# Old Go build: bun run ~/.config/claude/hooks/save-session.ts ./cmd/save-session
-
-# Copy to PATH
-sudo cp bin/* /usr/local/bin/
-
-# Run setup script (configures settings.json)
-./setup-hooks.sh
-```
+Hooks are TypeScript files in `~/src/home/dots/config/claude/hooks/`, symlinked to `~/.config/claude/hooks/` via `make -C dots`.
### Verify Installation
```bash
-# Check binaries are in PATH
-which bun run ~/.config/claude/hooks/initialize-session.ts
-which bun run ~/.config/claude/hooks/capture-tool-output.ts
-which bun run ~/.config/claude/hooks/save-session.ts
+# Check hooks are in place
+ls ~/.config/claude/hooks/*.ts
# Test hooks manually
bun run ~/.config/claude/hooks/initialize-session.ts
@@ -574,7 +538,7 @@ echo '{"tool_name":"Bash","tool_input":{},"tool_response":{},"conversation_id":"
### Configuration
-Edit `/home/vincent/.config/claude/settings.json` to enable hooks (should already be configured):
+Edit `~/.config/claude/settings.json` to enable hooks (should already be configured):
```json
{
@@ -622,73 +586,27 @@ Restart Claude Code after editing settings.json.
### Step 1: Choose Hook Event
Decide which event should trigger your hook (SessionStart, PostToolUse, etc.)
-### Step 2: Create Hook Command
+### Step 2: Create Hook Script
-**Option A: TypeScript Implementation** (recommended)
+Create a TypeScript file in `~/src/home/dots/config/claude/hooks/`:
-Create new command in `~/.config/claude/hooks/ (source: dots/config/claude/hooks/)cmd/`:
+```typescript
+// my-hook.ts
+import { readInput, getSessionDir } from "./lib";
-```go
-package main
+const input = await readInput();
+// input has: tool_name, tool_input, tool_response, conversation_id
-import (
- "encoding/json"
- "fmt"
- "io"
- "os"
-)
+// Your hook logic here
-type HookInput struct {
- // Define fields based on hook event type
- ConversationID string `json:"conversation_id"`
- // ... other fields
-}
-
-func main() {
- // Read stdin
- input, err := io.ReadAll(os.Stdin)
- if err != nil {
- fmt.Fprintf(os.Stderr, "[my-hook] Error reading stdin: %v\n", err)
- os.Exit(0)
- }
-
- var data HookInput
- if err := json.Unmarshal(input, &data); err != nil {
- fmt.Fprintf(os.Stderr, "[my-hook] Error parsing JSON: %v\n", err)
- os.Exit(0)
- }
-
- // Your hook logic here
-
- os.Exit(0) // Always exit 0
-}
+// For PreToolUse: output JSON to stdout to block
+// { "decision": "block", "reason": "..." }
+// Or exit 0 silently to allow
```
-**Option B: Shell Script**
+Shared utilities are in `lib.ts` (paths, dates, slugs, debouncing).
-```bash
-#!/usr/bin/env bash
-set -euo pipefail
-
-# Read stdin (optional)
-input=$(cat)
-
-# Your hook logic here
-
-exit 0 # Always exit 0
-```
-
-### Step 3: Build (if Go)
-
-```bash
-cd /home/vincent/src/home/tools/claude-hooks
-# Old Go build: my-custom-hook ./cmd/my-custom-hook
-sudo cp bin/my-custom-hook /usr/local/bin/
-```
-
-Or add to `default.nix` for Nix packaging.
-
-### Step 4: Add to settings.json
+### Step 3: Add to settings.json
```json
{
@@ -855,27 +773,18 @@ tail ~/.config/claude/history/tool-outputs/$(date +%Y-%m)/$(date +%Y-%m-%d)_tool
---
-### Build Errors (Go)
+### TypeScript Hook Errors
**Check:**
```bash
-# Check Go version
-go version # Requires Go 1.23+
+# Verify bun is available
+bun --version
-# Update dependencies
-cd /home/vincent/src/home/tools/claude-hooks
-go mod tidy
+# Test a hook directly
+echo '{}' | bun run ~/.config/claude/hooks/initialize-session.ts
-# Rebuild
-go build ./cmd/initialize-session
-```
-
-**Nix Build:**
-```bash
-cd /home/vincent/src/home
-# Old Nix build (removed)
-
-# If vendorHash error, update in default.nix
+# Check for syntax errors
+bun run --check ~/.config/claude/hooks/lib.ts
```
---
dots/config/copilot-hooks/copilot-to-claude.sh
@@ -1,45 +0,0 @@
-#!/usr/bin/env bash
-# Wrapper script to translate Copilot hook JSON format to Claude Code format
-# Usage: copilot-to-claude.sh <claude-hooks-binary>
-#
-# Copilot format:
-# { "toolName": "bash", "toolArgs": "{\"command\":\"...\"}", "toolResult": {...} }
-#
-# Claude Code format:
-# { "tool_name": "Bash", "tool_input": {"command": "..."}, "tool_response": {...} }
-
-set -euo pipefail
-
-BINARY="${1:-}"
-if [[ -z "$BINARY" ]]; then
- echo "Usage: $0 <claude-hooks-binary>" >&2
- exit 1
-fi
-
-# Read stdin
-INPUT=$(cat)
-
-# Check if we have input
-if [[ -z "$INPUT" ]]; then
- exit 0
-fi
-
-# Transform Copilot format to Claude Code format using jq
-# - toolName -> tool_name (capitalize first letter for Claude Code convention)
-# - toolArgs (string) -> tool_input (parsed object)
-# - toolResult -> tool_response
-TRANSFORMED=$(echo "$INPUT" | jq -c '
-{
- tool_name: (.toolName | split("") | .[0:1] | map(ascii_upcase) | join("") + (.toolName | .[1:])),
- tool_input: (if .toolArgs then (.toolArgs | fromjson) else {} end),
- tool_response: (.toolResult // {}),
- conversation_id: (.sessionId // "copilot")
-}
-' 2>/dev/null) || {
- # If jq fails, just pass through empty and let binary handle it
- exit 0
-}
-
-# Call the Claude hooks binary with transformed input
-echo "$TRANSFORMED" | "$BINARY"
-exit $?
dots/config/emacs/init.el
@@ -2038,39 +2038,14 @@ Use this function via a hook."
(org-habit-show-habits-only-for-today nil)
(org-habit-graph-column 80))
-;; org-ql is required by pi-org-todos
+;; org-ql is used by org-batch-functions / pi-org-todos
(use-package org-ql
- :after org
:commands (org-ql-search org-ql-query))
-;; org-batch-functions provides batch operations for org files
-(use-package org-batch-functions
- :after org-ql
- :commands (org-batch-list-todos
- org-batch-scheduled-today
- org-batch-get-upcoming
- org-batch-get-overdue
- org-batch-search
- org-batch-get-todo-content
- org-batch-get-sections
- org-batch-by-section
- org-batch-get-statistics
- org-batch-update-state
- org-batch-schedule-task
- org-batch-set-deadline
- org-batch-set-priority
- org-batch-add-todo
- org-batch-append-content
- org-batch-archive-done
- org-batch-add-tags
- org-batch-remove-tags
- org-batch-list-all-tags
- org-batch-get-property
- org-batch-set-property))
-
-;; Pi coding agent org-mode TODO interface
+;; org-batch-functions and pi-org-todos are site-lisp packages called
+;; externally via emacsclient — their require chains pull in org/org-ql.
+(use-package org-batch-functions)
(use-package pi-org-todos
- :after org-batch-functions
:commands (pi/org-todo-list
pi/org-todo-list-all
pi/org-todo-scheduled
dots/pi/agent/README.md
@@ -6,31 +6,47 @@ a minimal terminal coding agent.
## Structure
```
-~/.config/pi/agent/
+~/.pi/agent/
├── settings.json # Global settings (provider, model, thinking)
├── extensions/ # TypeScript extensions
-│ └── claude-hooks.ts # Wrapper for Claude Code hook binaries
-├── skills/ # Skills directory (SKILL.md format)
+│ ├── ai-storage/ # Unified AI storage (sessions, research, plans, learnings)
+│ ├── org-todos/ # Org-mode TODO management via emacsclient
+│ ├── path-validator/ # Validate file paths and filenames
+│ ├── terminal-status.ts # Terminal title updates
+│ └── validate-git-push.ts # Block unsafe git push
+├── AGENTS.md # Global agent instructions
└── README.md
```
## Extensions
-### claude-hooks.ts
+### ai-storage
-Wraps the Go-based Claude Code hook binaries to provide consistent hook behavior:
+Unified AI storage extension. Saves sessions, research, plans, and learnings
+to `~/.local/share/ai/` with consistent `YYYY-MM-DD-description.md` naming.
+Shared across pi, claude, and opencode.
-| Pi Event | Claude Hook Binary | Purpose |
-|----------|-------------------|---------|
-| session_start | claude-hooks-initialize-session | Session initialization |
-| session_shutdown | claude-hooks-save-session | Save session summary |
-| tool_call | claude-hooks-validate-git-push | Block unsafe git push |
-| tool_result | claude-hooks-capture-tool-output | Capture tool output |
-| tool_result | claude-hooks-update-terminal-title | Update terminal title |
+### org-todos
+
+Org-mode TODO management via emacsclient. Provides the `org_todo` tool for
+listing, searching, creating, and managing TODOs without direct file edits.
+
+### path-validator
+
+Validates file paths and filenames against policies in `~/.config/ai/path-policies.json`.
+Blocks writes to old storage locations and enforces naming conventions.
+
+### validate-git-push.ts
+
+Blocks unsafe git commands: bare `git push` (no refspec), `git add .`, etc.
+
+### terminal-status.ts
+
+Updates terminal title with project and context info after tool calls.
## Skills
-Pi is compatible with Claude Code skills format. Skills are configured in `settings.json`:
+Pi loads Claude Code skills via `settings.json`:
```json
{
@@ -40,18 +56,6 @@ Pi is compatible with Claude Code skills format. Skills are configured in `setti
}
```
-This loads all skills from the Claude skills directory automatically.
-
-## Settings
-
-The `settings.json` configures:
-
-- **defaultProvider**: LLM provider (vertex, anthropic, openai, etc.)
-- **defaultModel**: Model to use
-- **enabledModels**: Models available for cycling (Ctrl+P)
-- **defaultThinkingLevel**: off, low, medium, high, xhigh
-- **steeringMode**: Message delivery control
-
## Usage
```bash
tools/README.org
@@ -211,10 +211,6 @@
* Other Tools
-** claude-hooks
-
-Claude Code hooks for session management and tool output capture.
-
** org-manager
Org-mode management utilities for programmatic org file manipulation.
tools/test-all-packages.sh
@@ -18,7 +18,6 @@ PACKAGES=(
"govanityurl"
"manifest-tool"
"ram"
- "claude-hooks"
"arr"
"download-kiwix-zim"
"gh-restart-failed"
README.org
@@ -48,7 +48,7 @@
Custom tools and utilities:
- DNS management scripts (show-dns.sh, update-gandi-dns.sh)
- Media management (arr CLI for *arr services, music-playlist-dl for podcasts)
-- GitHub tools (gh-pr for pull request management, claude-hooks for Claude Code)
+- GitHub tools (gh-pr for pull request management)
- System utilities (battery-monitor, cliphist-cleanup, toggle-color-scheme)
- Content tools (download-kiwix-zim for offline Wikipedia)
- Emacs configuration and org-mode utilities (org-manager)
@@ -326,7 +326,6 @@
- =chmouzies-kubernetes= - Kubernetes and OpenShift helper scripts
**** Claude Code Tools
-- =claude-hooks= - Claude Code hooks for session management, tool output capture, and documentation validation
- =gh-pr= - GitHub PR management tool for approving, reviewing, and managing pull requests
**** Media and Content Management