claude-smart 0.2.44 → 0.2.45

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.
@@ -4,14 +4,14 @@
4
4
  "name": "Yi Lu"
5
5
  },
6
6
  "metadata": {
7
- "description": "claude-smart — self-improving Claude Code and Codex plugin via reflexio"
7
+ "description": "claude-smart — self-improving Claude Code and Codex plugin powered by Reflexio"
8
8
  },
9
9
  "plugins": [
10
10
  {
11
11
  "name": "claude-smart",
12
- "version": "0.2.44",
12
+ "version": "0.2.45",
13
13
  "source": "./plugin",
14
- "description": "Turns user corrections into project-specific and shared skills via reflexio — uses Claude Code or Codex as the LLM backend (no external API key required)"
14
+ "description": "Turns corrections into Preferences, Project-specific skills, and Shared skills — uses Claude Code or Codex as the LLM backend (no external API key required)"
15
15
  }
16
16
  ]
17
17
  }
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  <img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License">
14
14
  </a>
15
15
  <a href="plugin/pyproject.toml">
16
- <img src="https://img.shields.io/badge/version-0.2.44-green.svg" alt="Version">
16
+ <img src="https://img.shields.io/badge/version-0.2.45-green.svg" alt="Version">
17
17
  </a>
18
18
  <a href="plugin/pyproject.toml">
19
19
  <img src="https://img.shields.io/badge/python-%3E%3D3.12-brightgreen.svg" alt="Python">
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "claude-smart",
3
- "version": "0.2.44",
4
- "description": "Self-improving Claude Code and Codex plugin turns corrections into durable skills via reflexio",
3
+ "version": "0.2.45",
4
+ "description": "Self-improving Claude Code and Codex plugin that turns corrections into Preferences, Project-specific skills, and Shared skills",
5
5
  "keywords": [
6
6
  "claude",
7
7
  "claude-code",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "claude-smart",
3
- "version": "0.2.44",
4
- "description": "Self-improving Claude Code and Codex plugin turns corrections into durable skills via reflexio",
3
+ "version": "0.2.45",
4
+ "description": "Self-improving Claude Code and Codex plugin that turns corrections into Preferences, Project-specific skills, and Shared skills",
5
5
  "author": {
6
6
  "name": "Yi Lu"
7
7
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-smart",
3
- "version": "0.2.44",
3
+ "version": "0.2.45",
4
4
  "description": "Self-improving coding assistant plugin — learns from corrections across sessions via reflexio",
5
5
  "author": {
6
6
  "name": "Yi Lu"
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "claude-smart"
3
- version = "0.2.44"
4
- description = "Self-improving Claude Code and Codex plugin turns corrections into durable skills via reflexio"
3
+ version = "0.2.45"
4
+ description = "Self-improving Claude Code and Codex plugin that turns corrections into Preferences, Project-specific skills, and Shared skills"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
7
7
  dependencies = [
@@ -3,11 +3,53 @@
3
3
  # Claude Code hooks run with a minimal non-interactive PATH that often omits
4
4
  # nvm/asdf/brew shims where `npm`, `uv`, etc. live. Pull the user's login-shell
5
5
  # PATH the same way claude-mem does so hook-spawned scripts find them without
6
- # the user having to mutate their global PATH. Best-effort failures silent.
6
+ # the user having to mutate their global PATH. Best-effort and bounded: shell
7
+ # profile startup can be slow or stuck on Windows, so this must never outlive a
8
+ # hook's timeout budget.
9
+ claude_smart_login_path_timeout_seconds() {
10
+ local _VALUE
11
+ _VALUE="${CLAUDE_SMART_LOGIN_PATH_TIMEOUT_SECONDS:-2}"
12
+ case "$_VALUE" in
13
+ ''|*[!0-9]*) printf '%s\n' "2" ;;
14
+ *) printf '%s\n' "$_VALUE" ;;
15
+ esac
16
+ }
17
+
18
+ claude_smart_capture_login_path() {
19
+ local _TIMEOUT _TMP _PID _WAITED _LINE
20
+ _TIMEOUT="$(claude_smart_login_path_timeout_seconds)"
21
+ [ "$_TIMEOUT" -gt 0 ] || return 1
22
+
23
+ _TMP="${TMPDIR:-/tmp}/claude-smart-login-path.$$"
24
+ rm -f "$_TMP" 2>/dev/null || true
25
+ "$SHELL" -lc 'printf %s "$PATH"' >"$_TMP" 2>/dev/null &
26
+ _PID=$!
27
+ _WAITED=0
28
+ while kill -0 "$_PID" 2>/dev/null; do
29
+ if [ "$_WAITED" -ge "$_TIMEOUT" ]; then
30
+ kill "$_PID" 2>/dev/null || true
31
+ wait "$_PID" 2>/dev/null || true
32
+ rm -f "$_TMP" 2>/dev/null || true
33
+ return 1
34
+ fi
35
+ sleep 1
36
+ _WAITED=$((_WAITED + 1))
37
+ done
38
+ if wait "$_PID" 2>/dev/null; then
39
+ while IFS= read -r _LINE || [ -n "$_LINE" ]; do
40
+ printf '%s' "$_LINE"
41
+ done <"$_TMP"
42
+ rm -f "$_TMP" 2>/dev/null || true
43
+ return 0
44
+ fi
45
+ rm -f "$_TMP" 2>/dev/null || true
46
+ return 1
47
+ }
48
+
7
49
  claude_smart_source_login_path() {
8
50
  local _SHELL_PATH
9
51
  if [ -n "${SHELL:-}" ] && [ -x "$SHELL" ]; then
10
- if _SHELL_PATH="$("$SHELL" -lc 'printf %s "$PATH"' 2>/dev/null)"; then
52
+ if _SHELL_PATH="$(claude_smart_capture_login_path)"; then
11
53
  [ -n "$_SHELL_PATH" ] && export PATH="$_SHELL_PATH:$PATH"
12
54
  fi
13
55
  fi
@@ -116,30 +158,24 @@ claude_smart_dashboard_unavailable_marker() {
116
158
  }
117
159
 
118
160
  claude_smart_node_recovery_hint() {
119
- cat <<'EOF'
120
- Recovery:
121
- 1. Restart Claude Code to let claude-smart retry its private Node.js install.
122
- 2. If the retry is blocked by your network or OS policy, install Node.js 20.9+ manually:
123
- EOF
161
+ printf '%s\n' \
162
+ "Recovery:" \
163
+ " 1. Restart Claude Code to let claude-smart retry its private Node.js install." \
164
+ " 2. If the retry is blocked by your network or OS policy, install Node.js 20.9+ manually:"
124
165
  if claude_smart_is_windows; then
125
- cat <<'EOF'
126
- - winget install OpenJS.NodeJS.LTS
127
- - or download the LTS installer from https://nodejs.org/
128
- EOF
166
+ printf '%s\n' \
167
+ " - winget install OpenJS.NodeJS.LTS" \
168
+ " - or download the LTS installer from https://nodejs.org/"
129
169
  elif [ "$(uname -s 2>/dev/null)" = "Darwin" ]; then
130
- cat <<'EOF'
131
- - brew install node
132
- - or download the LTS installer from https://nodejs.org/
133
- EOF
170
+ printf '%s\n' \
171
+ " - brew install node" \
172
+ " - or download the LTS installer from https://nodejs.org/"
134
173
  else
135
- cat <<'EOF'
136
- - use your distro package manager for nodejs/npm
137
- - or download the LTS archive from https://nodejs.org/
138
- EOF
174
+ printf '%s\n' \
175
+ " - use your distro package manager for nodejs/npm" \
176
+ " - or download the LTS archive from https://nodejs.org/"
139
177
  fi
140
- cat <<'EOF'
141
- 3. Run /claude-smart:restart, then /claude-smart:dashboard.
142
- EOF
178
+ printf '%s\n' " 3. Run /claude-smart:restart, then /claude-smart:dashboard."
143
179
  }
144
180
 
145
181
  claude_smart_write_dashboard_unavailable() {
@@ -527,14 +563,22 @@ claude_smart_append_capped_log() {
527
563
  # POSIX: setsid → python3 os.setsid → nohup (in that order of strength).
528
564
  # Windows: nohup alone — Git Bash has no setsid, no process groups, and
529
565
  # `os.setsid()` is POSIX-only; nohup ignores SIGHUP which is enough to
530
- # survive the parent console closing. The python3 fallback is gated on a
531
- # real-interpreter probe (-V) so the Windows App Execution Alias stub
532
- # doesn't get invoked. Caller is responsible for redirecting stdout/stderr;
533
- # we do not impose a log destination here. Stdin is closed so the child
534
- # cannot inherit a tty. Use `$!` after this call to capture the pid.
566
+ # survive the parent console closing. On Windows, stdout/stderr are also
567
+ # closed here so hook-runner pipes cannot be kept alive by long-lived
568
+ # background children after the hook script exits unless the caller explicitly
569
+ # opts into preserving stdout/stderr for a file redirection. The python3
570
+ # fallback is gated on a real-interpreter probe (-V) so the Windows App
571
+ # Execution Alias stub doesn't get invoked. POSIX callers are responsible for
572
+ # redirecting stdout/stderr; we do not impose a log destination there. Stdin is
573
+ # closed so the child cannot inherit a tty. Use `$!` after this call to capture
574
+ # the pid.
535
575
  claude_smart_spawn_detached() {
536
576
  if claude_smart_is_windows; then
537
- nohup "$@" < /dev/null &
577
+ if [ "${CLAUDE_SMART_SPAWN_KEEP_OUTPUT:-}" = "1" ]; then
578
+ nohup "$@" < /dev/null &
579
+ else
580
+ nohup "$@" < /dev/null > /dev/null 2>&1 &
581
+ fi
538
582
  return 0
539
583
  fi
540
584
  if command -v setsid >/dev/null 2>&1; then
@@ -20,11 +20,13 @@ set -eu
20
20
  HERE="$(cd "$(dirname "$0")" && pwd)"
21
21
  # shellcheck source=_lib.sh
22
22
  . "$HERE/_lib.sh"
23
- claude_smart_source_login_path
23
+ CMD="${1:-start}"
24
+ if [ "$CMD" != "session-end" ]; then
25
+ claude_smart_source_login_path
26
+ fi
24
27
  claude_smart_prepend_astral_bins
25
28
  claude_smart_source_reflexio_env
26
29
 
27
- CMD="${1:-start}"
28
30
  PORT=8071
29
31
  EMBEDDING_PORT="${EMBEDDING_PORT:-8072}"
30
32
  # Pass through to `reflexio services start/stop` so the spawned backend
@@ -262,7 +264,7 @@ case "$CMD" in
262
264
  if ! command -v uv >/dev/null 2>&1; then
263
265
  if [ "${CLAUDE_SMART_BOOTSTRAPPING:-}" != "1" ] && [ -x "$PLUGIN_ROOT/scripts/smart-install.sh" ]; then
264
266
  claude_smart_append_capped_log "$LOG_FILE" "$LOG_MAX_BYTES" "[claude-smart] backend: uv not on PATH; starting installer in background"
265
- claude_smart_spawn_detached env CLAUDE_SMART_BOOTSTRAPPING=1 \
267
+ CLAUDE_SMART_SPAWN_KEEP_OUTPUT=1 claude_smart_spawn_detached env CLAUDE_SMART_BOOTSTRAPPING=1 \
266
268
  bash "$PLUGIN_ROOT/scripts/smart-install.sh" \
267
269
  >>"$STATE_DIR/install.log" 2>&1 || true
268
270
  fi
@@ -21,11 +21,13 @@ set -eu
21
21
  HERE="$(cd "$(dirname "$0")" && pwd)"
22
22
  # shellcheck source=_lib.sh
23
23
  . "$HERE/_lib.sh"
24
- claude_smart_source_login_path
24
+ CMD="${1:-start}"
25
+ if [ "$CMD" != "session-end" ]; then
26
+ claude_smart_source_login_path
27
+ fi
25
28
  claude_smart_prepend_node_bins
26
29
  claude_smart_source_reflexio_env
27
30
 
28
- CMD="${1:-start}"
29
31
  PORT=3001
30
32
 
31
33
  PLUGIN_ROOT="$(cd "$HERE/.." && pwd)"
@@ -192,7 +194,7 @@ case "$CMD" in
192
194
  if [ -z "$NPM_BIN" ] || ! "$NPM_BIN" --version >/dev/null 2>&1; then
193
195
  if [ "${CLAUDE_SMART_BOOTSTRAPPING:-}" != "1" ] && [ -x "$PLUGIN_ROOT/scripts/smart-install.sh" ]; then
194
196
  echo "[claude-smart] dashboard: npm is not on PATH; starting installer in background" >>"$LOG_FILE"
195
- claude_smart_spawn_detached env CLAUDE_SMART_BOOTSTRAPPING=1 \
197
+ CLAUDE_SMART_SPAWN_KEEP_OUTPUT=1 claude_smart_spawn_detached env CLAUDE_SMART_BOOTSTRAPPING=1 \
196
198
  bash "$PLUGIN_ROOT/scripts/smart-install.sh" \
197
199
  >>"$STATE_DIR/install.log" 2>&1 || true
198
200
  fi
@@ -214,7 +216,7 @@ case "$CMD" in
214
216
  BUILD_PID_FILE="$STATE_DIR/dashboard-build.pid"
215
217
  if ! claude_smart_pid_alive_file "$BUILD_PID_FILE"; then
216
218
  echo "[claude-smart] dashboard: .next missing — starting background build (~1-2 min)" >>"$LOG_FILE"
217
- claude_smart_spawn_detached bash "$HERE/dashboard-build.sh" >>"$LOG_FILE" 2>&1
219
+ CLAUDE_SMART_SPAWN_KEEP_OUTPUT=1 claude_smart_spawn_detached bash "$HERE/dashboard-build.sh" >>"$LOG_FILE" 2>&1
218
220
  fi
219
221
  emit_ok; exit 0
220
222
  fi
@@ -229,7 +231,7 @@ case "$CMD" in
229
231
  # Caller-side `>>file 2>&1` redirection is honoured before the child
230
232
  # detaches, so per-OS log paths stay identical.
231
233
  export CLAUDE_SMART_DASHBOARD_WORKSPACE="$WORKSPACE_CWD"
232
- claude_smart_spawn_detached "$NPM_BIN" run start >>"$LOG_FILE" 2>&1
234
+ CLAUDE_SMART_SPAWN_KEEP_OUTPUT=1 claude_smart_spawn_detached "$NPM_BIN" run start >>"$LOG_FILE" 2>&1
233
235
  dash_pid=$!
234
236
  # Record the spawned pid, not a pgid sampled with ps. On POSIX,
235
237
  # setsid/python os.setsid make this pid the new process group leader;
@@ -96,7 +96,7 @@ if ! command -v uv >/dev/null 2>&1; then
96
96
  fi
97
97
  if [ -x "$PLUGIN_ROOT/scripts/smart-install.sh" ]; then
98
98
  mkdir -p "$STATE_DIR"
99
- claude_smart_spawn_detached env CLAUDE_SMART_BOOTSTRAPPING=1 \
99
+ CLAUDE_SMART_SPAWN_KEEP_OUTPUT=1 claude_smart_spawn_detached env CLAUDE_SMART_BOOTSTRAPPING=1 \
100
100
  bash "$PLUGIN_ROOT/scripts/smart-install.sh" \
101
101
  >>"$STATE_DIR/install.log" 2>&1 || true
102
102
  fi
@@ -123,7 +123,7 @@ ensure_hook_package_importable() {
123
123
  printf '%s\n' "[claude-smart] hook: claude_smart.hook is not importable; retrying install in background"
124
124
  date 2>/dev/null || true
125
125
  } >>"$STATE_DIR/install.log" 2>&1
126
- claude_smart_spawn_detached env CLAUDE_SMART_BOOTSTRAPPING=1 \
126
+ CLAUDE_SMART_SPAWN_KEEP_OUTPUT=1 claude_smart_spawn_detached env CLAUDE_SMART_BOOTSTRAPPING=1 \
127
127
  bash "$PLUGIN_ROOT/scripts/smart-install.sh" \
128
128
  >>"$STATE_DIR/install.log" 2>&1 || true
129
129
 
package/plugin/uv.lock CHANGED
@@ -476,7 +476,7 @@ wheels = [
476
476
 
477
477
  [[package]]
478
478
  name = "claude-smart"
479
- version = "0.2.44"
479
+ version = "0.2.45"
480
480
  source = { editable = "." }
481
481
  dependencies = [
482
482
  { name = "chromadb" },