@trailkeep/cli 0.4.0 → 0.5.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trailkeep",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Injects your private repo notes and the current branch's effort file at session start, plus the effort skill.",
5
5
  "author": { "name": "Mario Širić" },
6
6
  "repository": "https://github.com/msiric/trailkeep",
package/README.md CHANGED
@@ -42,7 +42,8 @@ Later, `trailkeep update` gets the latest version the same way you installed it
42
42
  | When | What happens automatically |
43
43
  |---|---|
44
44
  | Any session starts in any repo | Notes and the branch's effort file are injected. A one-line pointer mentions the decision log if it has entries. Leftovers from a session that didn't exit cleanly are logged first. |
45
- | Any session starts in a repo | A short capture rule tells the agent to record decisions, user rules and dead ends the moment they come up, with `trailkeep note`. It doesn't wait for anyone to decide the task "spans sessions". Turn it off with `TRAILKEEP_HINT=0`. |
45
+ | Any session starts in a repo | A short capture rule tells the agent to record decisions, user rules and dead ends the moment they come up, with `trailkeep note`, and to pick the scope: this branch, the whole repo (`--repo`) or every repo (`--all`). It doesn't wait for anyone to decide the task "spans sessions". Turn it off with `TRAILKEEP_HINT=0`. |
46
+ | You're on a branch with no notes yet | The last few decisions recorded on other branches are shown, each labelled with its branch, so repo-wide rules saved on one branch aren't lost on the next. Once the branch has its own notes, only those are shown. |
46
47
  | The agent works | It keeps the effort file current: plan ticks, a progress line per session, decisions and dead ends. That's the effort skill's job. |
47
48
  | Context gets compacted | The effort file is re-injected fresh. |
48
49
  | A session ends | New Decisions and Progress lines from every effort in the worktree go into the decision log, stamped with the commit, the branch's changed files, branch and session id. It takes under 0.1 s, well inside Codex's 3-second limit for this hook. Anything a killed session missed is picked up at the next start, in the background. |
package/bin/trailkeep CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  set -u
7
7
 
8
- VERSION="0.4.0"
8
+ VERSION="0.5.0"
9
9
  PKG="@trailkeep/cli"
10
10
  MARKER="managed by trailkeep"
11
11
 
@@ -230,7 +230,22 @@ default_branch() {
230
230
  # One standing instruction, so capture doesn't depend on the agent deciding a
231
231
  # task "spans sessions" (it can't know). Measured cost: about 110 tokens.
232
232
  capture_rule() {
233
- printf '%s\n' 'trailkeep: when something comes up that a later session must not lose (a decision and its reason, a rule or preference the user states, an approach that failed and why), record it right away: `trailkeep note "<what and why>"`. It is kept for this branch and shown at the start of the next session. Use `trailkeep note --repo` for a fact about the whole repo, or `--all` for a personal preference that applies in every repo.'
233
+ printf '%s\n' 'trailkeep: when something comes up that a later session must not lose (a decision and its reason, a rule or preference the user states, an approach that failed and why), record it right away with its reason. Pick the scope: `trailkeep note --repo "..."` for a rule about this codebase that holds on every branch, `trailkeep note "..."` for something specific to this branch'"'"'s task, `trailkeep note --all "..."` for a personal preference in every repo. Notes are shown at the start of the next session.'
234
+ }
235
+
236
+ # Decisions recorded on other branches, newest first: effort files in this
237
+ # worktree (their latest lines may not be in the log yet), then the log.
238
+ other_decisions() { # CURRENT_BRANCH KEY -> up to 5 lines "- (branch) text"
239
+ {
240
+ for f in $(ls -t "$(effort_dir)"/*.md 2>/dev/null); do
241
+ br=$(effort_branch "$f"); [ -n "$br" ] && [ "$br" != "$1" ] || continue
242
+ section "$f" "Decisions and dead ends" |
243
+ awk -v br="$br" -v tab="$TAB" 'NF { l = $0; sub(/^[[:space:]]*[-*][[:space:]]*/, "", l); a[++n] = br tab l } END { for (i = n; i > 0; i--) print a[i] }'
244
+ done
245
+ log_events "$2" | awk -F "$TAB" -v OFS="$TAB" -v b="$1" '($3 == "decision" || $3 == "dead-end") && $4 != b { print $4, $7 }'
246
+ } | awk -F "$TAB" '!seen[$2]++ && $2 !~ /^\[[ xX]\]/ {
247
+ t = $2; if (length(t) > 240) t = substr(t, 1, 237) "..."
248
+ printf "- (%s) %s\n", $1, t; if (++c >= 5) exit }'
234
249
  }
235
250
 
236
251
  build_context() {
@@ -246,25 +261,31 @@ build_context() {
246
261
 
247
262
  budget=$MAX_CHARS
248
263
  if [ -s "$GLOBAL_NOTES" ]; then
249
- piece "trailkeep: your notes for every repo" "$GLOBAL_NOTES" "$((budget / 4))"
264
+ piece "trailkeep: your preferences for every repo; apply them unless the user says otherwise" "$GLOBAL_NOTES" "$((budget / 4))"
250
265
  budget=$((budget - $(chars "$GLOBAL_NOTES")))
251
266
  [ "$budget" -lt $((MAX_CHARS / 2)) ] && budget=$((MAX_CHARS / 2))
252
267
  printf '\n'
253
268
  fi
254
269
  if [ "$has_notes" -eq 1 ]; then
255
- piece "trailkeep: private notes for this repository" "$notes" "$((budget / 3))"
270
+ piece "trailkeep: rules and notes for this repository; follow them unless the user says otherwise" "$notes" "$((budget / 3))"
256
271
  budget=$((budget - $(chars "$notes")))
257
272
  [ "$budget" -lt $((MAX_CHARS / 2)) ] && budget=$((MAX_CHARS / 2))
258
273
  printf '\n'
259
274
  fi
260
275
  if [ "$has_effort" -eq 1 ] && ! grep -q '^## Plan' "$effort"; then
261
- piece "trailkeep: notes for branch $b" "$effort" "$budget"
276
+ piece "trailkeep: decisions recorded for branch $b; follow them unless the user says otherwise" "$effort" "$budget"
262
277
  printf '\n'
263
278
  elif [ "$has_effort" -eq 1 ]; then
264
279
  printf 'trailkeep: this branch has an effort file. It is the source of truth for the current task. Keep it current as you work: tick Plan items and add one dated line under Progress before you stop.\n'
265
280
  piece "trailkeep: effort file for branch $b" "$effort" "$budget"
266
281
  printf '\n'
267
282
  fi
283
+ if [ "$has_effort" -eq 0 ] && [ -n "$effort" ]; then
284
+ od=$(other_decisions "$b" "$KEY" 2>/dev/null)
285
+ if [ -n "$od" ]; then
286
+ printf 'trailkeep: branch %s has no notes yet. Recent decisions from other branches of this repo, newest first. Rules about the codebase as a whole probably hold here too; ones tied to another branch'"'"'s task may not:\n%s\n\n' "$b" "$od"
287
+ fi
288
+ fi
268
289
  if [ "${TRAILKEEP_HINT:-1}" != 0 ] && [ -n "$effort" ]; then
269
290
  capture_rule
270
291
  fi
@@ -617,7 +638,8 @@ cmd_note() {
617
638
  -h|--help|help|"") die 'usage: trailkeep note [--repo|--all] "what and why"' ;;
618
639
  esac
619
640
  [ $# -ge 1 ] || die 'usage: trailkeep note [--repo|--all] "what and why"'
620
- text=$(printf '%s' "$*" | one_line)
641
+ # drop a date the agent wrote itself; the note gets today's date below
642
+ text=$(printf '%s' "$*" | one_line | sed 's/^[-* ]*[0-9]\{4\}-[0-9][0-9]-[0-9][0-9]:\{0,1\}[[:space:]]*//')
621
643
  [ -n "$text" ] || die "note: empty text"
622
644
  case $scope in
623
645
  branch)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trailkeep/cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Shared instructions, per-branch task context and a decision log for Claude Code, Codex CLI and GitHub Copilot CLI. POSIX sh + git.",
5
5
  "keywords": [
6
6
  "claude-code",