tim-hooks 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +31 -0
  2. package/dist/cadence-runner.d.ts +11 -0
  3. package/dist/cadence-runner.d.ts.map +1 -0
  4. package/dist/cadence-runner.js +30 -0
  5. package/dist/cadence-runner.js.map +1 -0
  6. package/dist/cadence.d.ts +10 -0
  7. package/dist/cadence.d.ts.map +1 -0
  8. package/dist/cadence.js +36 -0
  9. package/dist/cadence.js.map +1 -0
  10. package/dist/checkpoint.d.ts +56 -0
  11. package/dist/checkpoint.d.ts.map +1 -0
  12. package/dist/checkpoint.js +232 -0
  13. package/dist/checkpoint.js.map +1 -0
  14. package/dist/claude-stop.d.ts +32 -0
  15. package/dist/claude-stop.d.ts.map +1 -0
  16. package/dist/claude-stop.js +213 -0
  17. package/dist/claude-stop.js.map +1 -0
  18. package/dist/constants.d.ts +5 -0
  19. package/dist/constants.d.ts.map +1 -0
  20. package/dist/constants.js +8 -0
  21. package/dist/constants.js.map +1 -0
  22. package/dist/delta.d.ts +7 -0
  23. package/dist/delta.d.ts.map +1 -0
  24. package/dist/delta.js +53 -0
  25. package/dist/delta.js.map +1 -0
  26. package/dist/hooks.d.ts +39 -0
  27. package/dist/hooks.d.ts.map +1 -0
  28. package/dist/hooks.js +136 -0
  29. package/dist/hooks.js.map +1 -0
  30. package/dist/index.d.ts +13 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +88 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/marker.d.ts +179 -0
  35. package/dist/marker.d.ts.map +1 -0
  36. package/dist/marker.js +590 -0
  37. package/dist/marker.js.map +1 -0
  38. package/dist/phantom-recovery.d.ts +13 -0
  39. package/dist/phantom-recovery.d.ts.map +1 -0
  40. package/dist/phantom-recovery.js +113 -0
  41. package/dist/phantom-recovery.js.map +1 -0
  42. package/dist/project-creation.d.ts +48 -0
  43. package/dist/project-creation.d.ts.map +1 -0
  44. package/dist/project-creation.js +265 -0
  45. package/dist/project-creation.js.map +1 -0
  46. package/dist/prompt-submit.d.ts +16 -0
  47. package/dist/prompt-submit.d.ts.map +1 -0
  48. package/dist/prompt-submit.js +69 -0
  49. package/dist/prompt-submit.js.map +1 -0
  50. package/dist/rebalance.d.ts +17 -0
  51. package/dist/rebalance.d.ts.map +1 -0
  52. package/dist/rebalance.js +91 -0
  53. package/dist/rebalance.js.map +1 -0
  54. package/dist/session-hooks.d.ts +53 -0
  55. package/dist/session-hooks.d.ts.map +1 -0
  56. package/dist/session-hooks.js +167 -0
  57. package/dist/session-hooks.js.map +1 -0
  58. package/dist/update-check.d.ts +5 -0
  59. package/dist/update-check.d.ts.map +1 -0
  60. package/dist/update-check.js +66 -0
  61. package/dist/update-check.js.map +1 -0
  62. package/package.json +24 -0
  63. package/scripts/README-hermes-statusline.md +47 -0
  64. package/scripts/hermes-cli-tim-statusline.patch +75 -0
  65. package/scripts/lib/resolve-tim-cli.sh +30 -0
  66. package/scripts/post-commit.sh +30 -0
  67. package/scripts/tim-claude-session-start.sh +26 -0
  68. package/scripts/tim-cursor-inject.sh +17 -0
  69. package/scripts/tim-hermes-session-cache.sh +32 -0
  70. package/scripts/tim-hermes-statusline.sh +28 -0
  71. package/scripts/tim-post-commit.sh +14 -0
  72. package/scripts/tim-session-start.sh +104 -0
  73. package/scripts/tim-statusline.sh +16 -0
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bash
2
+ # tim-claude-session-start.sh — Claude Code SessionStart hook (TIM project auto-load).
3
+ # Reads cwd from the SessionStart payload, resolves nearest .tim-project (walk-up),
4
+ # emits additionalContext directive. Requires: jq, node. Override path with TIM_CLI.
5
+ set -euo pipefail
6
+
7
+ SCRIPT_PATH="${BASH_SOURCE[0]}"
8
+ while [[ -L "$SCRIPT_PATH" ]]; do
9
+ SCRIPT_LINK_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
10
+ SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
11
+ [[ "$SCRIPT_PATH" == /* ]] || SCRIPT_PATH="$SCRIPT_LINK_DIR/$SCRIPT_PATH"
12
+ done
13
+ SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
14
+ unset SCRIPT_PATH SCRIPT_LINK_DIR
15
+ # shellcheck source=lib/resolve-tim-cli.sh
16
+ source "$SCRIPT_DIR/lib/resolve-tim-cli.sh"
17
+
18
+ payload="$(cat -)"
19
+ cwd=$(printf '%s' "$payload" | jq -r '.cwd // empty')
20
+ [[ -z "$cwd" ]] && exit 0
21
+
22
+ directive=$(run_tim_cli resolve-project --cwd "$cwd" --format directive 2>/dev/null || true)
23
+ [[ -z "$directive" ]] && exit 0
24
+
25
+ jq -n --arg ctx "$directive" \
26
+ '{hookSpecificOutput: {hookEventName: "SessionStart", additionalContext: $ctx}}'
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env bash
2
+ # tim-cursor-inject.sh — print the TIM load directive for a workspace, for the
3
+ # orchestrator to prepend to Cursor's first prompt (Cursor has no SessionStart hook).
4
+ # Usage: tim-cursor-inject.sh <project-dir>
5
+ set -euo pipefail
6
+ SCRIPT_PATH="${BASH_SOURCE[0]}"
7
+ while [[ -L "$SCRIPT_PATH" ]]; do
8
+ SCRIPT_LINK_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
9
+ SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
10
+ [[ "$SCRIPT_PATH" == /* ]] || SCRIPT_PATH="$SCRIPT_LINK_DIR/$SCRIPT_PATH"
11
+ done
12
+ SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
13
+ unset SCRIPT_PATH SCRIPT_LINK_DIR
14
+ # shellcheck source=lib/resolve-tim-cli.sh
15
+ source "$SCRIPT_DIR/lib/resolve-tim-cli.sh"
16
+ cwd="${1:-$PWD}"
17
+ run_tim_cli resolve-project --cwd "$cwd" --format directive 2>/dev/null || true
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env bash
2
+ # tim-hermes-session-cache.sh — Hermes pre_llm_call: cache session_id + cwd for status bar
3
+ # Output: {} (no prompt injection). Register before tim-hermes-statusline refresh.
4
+ set -euo pipefail
5
+
6
+ SCRIPT_PATH="${BASH_SOURCE[0]}"
7
+ while [[ -L "$SCRIPT_PATH" ]]; do
8
+ SCRIPT_LINK_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
9
+ SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
10
+ [[ "$SCRIPT_PATH" == /* ]] || SCRIPT_PATH="$SCRIPT_LINK_DIR/$SCRIPT_PATH"
11
+ done
12
+ SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
13
+ unset SCRIPT_PATH SCRIPT_LINK_DIR
14
+ # shellcheck source=lib/resolve-tim-cli.sh
15
+ source "$SCRIPT_DIR/lib/resolve-tim-cli.sh"
16
+
17
+ payload="$(cat)"
18
+ session_id=$(printf '%s' "$payload" | jq -r '.session_id // empty')
19
+ cwd=$(printf '%s' "$payload" | jq -r '.cwd // empty')
20
+
21
+ [[ -z "$session_id" && -z "$cwd" ]] && { printf '{}\n'; exit 0; }
22
+
23
+ cache_dir="${TIM_CACHE_DIR:-$HOME/.tim}"
24
+ mkdir -p "$cache_dir"
25
+ jq -n \
26
+ --arg sid "$session_id" \
27
+ --arg cwd "${cwd:-$HOME}" \
28
+ '{session_id: $sid, cwd: $cwd, ts: (now | todate)}' \
29
+ > "${cache_dir}/.session-cache"
30
+
31
+ printf '{}\n'
32
+ exit 0
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env bash
2
+ # tim-hermes-statusline.sh — Hermes TUI status bar (JSON stdout for hermes-cli patch)
3
+ # Project from nearest .tim-project walk-up only (tim statusline / resolve-project). No session cache.
4
+ # Install: symlink to ~/.hermes/agent-hooks/ + apply hermes-cli-tim-statusline.patch
5
+ set -euo pipefail
6
+
7
+ SCRIPT_PATH="${BASH_SOURCE[0]}"
8
+ while [[ -L "$SCRIPT_PATH" ]]; do
9
+ SCRIPT_LINK_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
10
+ SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
11
+ [[ "$SCRIPT_PATH" == /* ]] || SCRIPT_PATH="$SCRIPT_LINK_DIR/$SCRIPT_PATH"
12
+ done
13
+ SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
14
+ unset SCRIPT_PATH SCRIPT_LINK_DIR
15
+ # shellcheck source=lib/resolve-tim-cli.sh
16
+ source "$SCRIPT_DIR/lib/resolve-tim-cli.sh"
17
+
18
+ # CWD: explicit env, else PWD (Hermes hook cwd is not piped here)
19
+ CWD="${TIM_STATUSLINE_CWD:-${PWD:-$HOME}}"
20
+ [[ -z "$CWD" ]] && CWD="${HOME}"
21
+
22
+ out=$(run_tim_cli statusline --format hermes --cwd "$CWD" 2>/dev/null || true)
23
+ if [[ -z "$out" ]]; then
24
+ echo '{}'
25
+ else
26
+ echo "$out"
27
+ fi
28
+ exit 0
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env bash
2
+ # Back-compat wrapper — delegates to post-commit.sh
3
+ set -euo pipefail
4
+ SCRIPT_PATH="${BASH_SOURCE[0]}"
5
+ while [[ -L "$SCRIPT_PATH" ]]; do
6
+ SCRIPT_LINK_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
7
+ SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
8
+ [[ "$SCRIPT_PATH" == /* ]] || SCRIPT_PATH="$SCRIPT_LINK_DIR/$SCRIPT_PATH"
9
+ done
10
+ SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
11
+ unset SCRIPT_PATH SCRIPT_LINK_DIR
12
+ # shellcheck source=lib/resolve-tim-cli.sh
13
+ source "$SCRIPT_DIR/lib/resolve-tim-cli.sh"
14
+ exec "$TIM_HOOKS_SCRIPTS_DIR/post-commit.sh" "$@"
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env bash
2
+ # tim-session-start.sh — Generic TIM auto-load hook for CLI coding agents.
3
+ #
4
+ # Supports: Claude Code, Cursor CLI, Codex CLI, OpenCode (via plugin wrapper).
5
+ #
6
+ # Reads a harness-specific session-start payload from stdin, resolves the nearest
7
+ # .tim-project marker (walk-up from cwd), and emits the buildLoadDirective text
8
+ # wrapped in the JSON envelope expected by the calling harness.
9
+ #
10
+ # Requires: bash, jq, node (for tim CLI). Override TIM_CLI path via env var.
11
+ #
12
+ # Output formats (auto-detected from stdin payload shape):
13
+ # Claude Code → {hookSpecificOutput: {hookEventName: "SessionStart", additionalContext: "…"}}
14
+ # Cursor CLI → {additional_context: "…"}
15
+ # Hermes/Codex → {context: "…"} (JSON — plain text broke Hermes session binding, PITFALLS-45)
16
+ # Fallback → {additional_context: "…"} (Cursor-safe, also works as plain text)
17
+
18
+ set -euo pipefail
19
+
20
+ SCRIPT_PATH="${BASH_SOURCE[0]}"
21
+ while [[ -L "$SCRIPT_PATH" ]]; do
22
+ SCRIPT_LINK_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
23
+ SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
24
+ [[ "$SCRIPT_PATH" == /* ]] || SCRIPT_PATH="$SCRIPT_LINK_DIR/$SCRIPT_PATH"
25
+ done
26
+ SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
27
+ unset SCRIPT_PATH SCRIPT_LINK_DIR
28
+ # shellcheck source=lib/resolve-tim-cli.sh
29
+ source "$SCRIPT_DIR/lib/resolve-tim-cli.sh"
30
+ TIM_HOOKS_MARKER="${TIM_MARKER_MODULE:-${SCRIPT_DIR}/../dist/marker.js}"
31
+
32
+ # Read stdin once (some harnesses pass payload, some pass nothing)
33
+ payload="$(cat -)"
34
+
35
+ # --- Determine cwd ---
36
+ cwd=""
37
+
38
+ # Strategy 1: Extract from payload (Claude Code, Codex, Hermes send .cwd)
39
+ if [[ -n "$payload" ]]; then
40
+ cwd=$(printf '%s' "$payload" | jq -r '.cwd // empty' 2>/dev/null || true)
41
+ fi
42
+
43
+ # Strategy 2: Extract workspace path (some Cursor versions)
44
+ if [[ -z "$cwd" && -n "$payload" ]]; then
45
+ cwd=$(printf '%s' "$payload" | jq -r '.workspace // empty' 2>/dev/null || true)
46
+ fi
47
+
48
+ # Strategy 3: Fall back to current working directory
49
+ if [[ -z "$cwd" ]]; then
50
+ cwd=$(pwd)
51
+ fi
52
+
53
+ # Extract session_id from payload (for marker rotation, Fix F)
54
+ hook_session=$(printf '%s' "$payload" | jq -r '.session_id // empty' 2>/dev/null || true)
55
+
56
+ # --- Resolve project marker ---
57
+ directive=$(run_tim_cli resolve-project --walk-up --cwd "$cwd" --format directive 2>/dev/null || true)
58
+ if [[ -z "$directive" ]]; then
59
+ # No .tim-project marker found — silent skip (exit 0)
60
+ exit 0
61
+ fi
62
+
63
+ # ── Session rotation: update .tim-project with current session ──
64
+ # Prevents stale cron session IDs from persisting in the marker (PITFALLS-46).
65
+ # cwd/session are passed via env, never interpolated into the JS source —
66
+ # paths or session ids containing quotes/backslashes must not break rotation.
67
+ if [[ -n "$hook_session" && -f "$TIM_HOOKS_MARKER" ]]; then
68
+ TIM_HOOK_CWD="$cwd" TIM_HOOK_SESSION="$hook_session" TIM_MARKER_MODULE="$TIM_HOOKS_MARKER" \
69
+ node --input-type=module -e "
70
+ const { pathToFileURL } = await import('node:url');
71
+ const m = await import(pathToFileURL(process.env.TIM_MARKER_MODULE).href);
72
+ m.rotateMarkerSession(process.env.TIM_HOOK_CWD, process.env.TIM_HOOK_SESSION);
73
+ " 2>/dev/null || true
74
+ fi
75
+
76
+ # --- Detect harness and format output ---
77
+
78
+ # Claude Code sends hook_event_name in hook input. Keep accepting the older
79
+ # hookSpecificOutput-shaped payload used by existing integrations/tests.
80
+ if printf '%s' "$payload" | jq -e \
81
+ '(.hook_event_name == "SessionStart") or (.hookSpecificOutput // false)' >/dev/null 2>&1; then
82
+ # Claude Code format
83
+ exec jq -n --arg ctx "$directive" \
84
+ '{hookSpecificOutput: {hookEventName: "SessionStart", additionalContext: $ctx}}'
85
+ fi
86
+
87
+ # Cursor sends payload with .conversation_id or .additional_context
88
+ if printf '%s' "$payload" | jq -e '(.conversation_id // empty) or (.additional_context // empty)' >/dev/null 2>&1; then
89
+ # Cursor format
90
+ exec jq -n --arg ctx "$directive" \
91
+ '{additional_context: $ctx}'
92
+ fi
93
+
94
+ # Hermes / Codex — payload has .session_id but NOT .hookSpecificOutput or .conversation_id
95
+ if printf '%s' "$payload" | jq -e '.session_id // empty' >/dev/null 2>&1; then
96
+ # Hermes expects JSON context (PITFALLS-45: plain-text broke session binding)
97
+ exec jq -n --arg ctx "$directive" \
98
+ '{context: $ctx}'
99
+ fi
100
+
101
+ # Fallback: no recognizable payload (empty stdin) — emit Cursor-safe JSON
102
+ # This covers: Cursor without payload, manual testing, unknown harnesses
103
+ exec jq -n --arg ctx "$directive" \
104
+ '{additional_context: $ctx}'
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env bash
2
+ # tim-statusline.sh — debug helper: one-line TIM status (stdin JSON optional, like Claude Code)
3
+ # Hermes TUI bar: use tim-hermes-statusline.sh + hermes-cli-tim-statusline.patch instead.
4
+ set -euo pipefail
5
+
6
+ SCRIPT_PATH="${BASH_SOURCE[0]}"
7
+ while [[ -L "$SCRIPT_PATH" ]]; do
8
+ SCRIPT_LINK_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
9
+ SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
10
+ [[ "$SCRIPT_PATH" == /* ]] || SCRIPT_PATH="$SCRIPT_LINK_DIR/$SCRIPT_PATH"
11
+ done
12
+ SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
13
+ unset SCRIPT_PATH SCRIPT_LINK_DIR
14
+ # shellcheck source=lib/resolve-tim-cli.sh
15
+ source "$SCRIPT_DIR/lib/resolve-tim-cli.sh"
16
+ run_tim_cli statusline 2>/dev/null || true