claude-smart 0.1.14 → 0.1.16
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.
- package/README.md +12 -9
- package/bin/claude-smart.js +65 -25
- package/package.json +2 -2
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.1.
|
|
16
|
+
<img src="https://img.shields.io/badge/version-0.1.16-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">
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
</p>
|
|
38
38
|
|
|
39
39
|
<p align="center">
|
|
40
|
-
It learns both corrections and successful execution patterns—so Claude Code avoids repeating mistakes and reuses what works.
|
|
40
|
+
It learns both corrections and successful execution patterns—so Claude Code avoids repeating mistakes and reuses what works. Playbook rules travel with you across every project; per-project profiles capture how you like to work on each repo.
|
|
41
41
|
</p>
|
|
42
42
|
|
|
43
43
|
<p align="center">
|
|
@@ -69,7 +69,7 @@ Four ways this changes what Claude Code can do for you:
|
|
|
69
69
|
|
|
70
70
|
Instead of re-exploring, Claude starts from the proven path—reducing planning steps, latency, and token usage.
|
|
71
71
|
|
|
72
|
-
- 🌐 **
|
|
72
|
+
- 🌐 **Global playbook, project-scoped profiles:** Session memory disappears with the conversation. The playbook persists *globally* — rules learned in one repo are available in every repo you work in — while user profiles stay scoped to the current project so per-repo preferences don't leak across projects.
|
|
73
73
|
|
|
74
74
|
- 🪶 **Better context without prompt bloat:** Distilled, deduplicated playbooks stay in dozens of tokens—not thousands—even as the project grows.
|
|
75
75
|
|
|
@@ -105,6 +105,7 @@ claude plugin uninstall claude-smart@reflexioai
|
|
|
105
105
|
Local data under `~/.reflexio/` and `~/.claude-smart/` is left in place — remove manually if desired.
|
|
106
106
|
|
|
107
107
|
Developing the plugin itself? See [DEVELOPER.md](./DEVELOPER.md#developing-locally).
|
|
108
|
+
> **Not supported:** Claude Code Cowork and claude.ai/code web — they run in a remote sandbox, so the local backend/dashboard and `~/.reflexio/` aren't reachable.
|
|
108
109
|
|
|
109
110
|
---
|
|
110
111
|
|
|
@@ -123,7 +124,7 @@ Developing the plugin itself? See [DEVELOPER.md](./DEVELOPER.md#developing-local
|
|
|
123
124
|
|
|
124
125
|
## Dashboard
|
|
125
126
|
|
|
126
|
-
A web UI for browsing session histories, inspecting user profiles, and editing
|
|
127
|
+
A web UI for browsing session histories, inspecting user profiles, and editing playbook rules. The dashboard auto-starts alongside the backend, so you can open **http://localhost:3001** directly. Or run `/claude-smart:dashboard` in Claude Code to launch dashboard in browser.
|
|
127
128
|
|
|
128
129
|
<p align="center">
|
|
129
130
|
<img src="assets/profile_dashboard.png" alt="Profile dashboard" width="49%">
|
|
@@ -136,8 +137,8 @@ A web UI for browsing session histories, inspecting user profiles, and editing p
|
|
|
136
137
|
|
|
137
138
|
claude-smart builds two artifacts as you work and injects them into Claude at the start of every new session:
|
|
138
139
|
|
|
139
|
-
- **User profile**
|
|
140
|
-
- **
|
|
140
|
+
- **User profile** (project-scoped) — preferences about how you work in this specific repo (stack, role, small quirks). *e.g.* "uses pnpm, not npm"; "prefers terse answers"; "backend engineer — explain frontend with backend analogues."
|
|
141
|
+
- **Playbook** (global, cross-project) — durable, generalized rules accumulated across every session, shared across every project you use claude-smart in. Each rule says when it applies and why, so a rule learned in one repo only fires in the contexts where it's relevant. *e.g.* "always pass `--run` to `npm test` — watch mode hangs CI"; "use real Postgres for integration tests — mocks once hid a broken migration."
|
|
141
142
|
|
|
142
143
|
Playbooks clean themselves up: correct the same thing twice and they merge; change your mind and the old one is archived.
|
|
143
144
|
|
|
@@ -146,8 +147,10 @@ Under the hood: hooks watch your turns, tool calls, and Claude's replies, auto-f
|
|
|
146
147
|
**Citations (`cs-cite`).** At the end of a reply, Claude may run:
|
|
147
148
|
|
|
148
149
|
```
|
|
149
|
-
⏺ Bash(cs-cite p1-
|
|
150
|
-
⎿
|
|
150
|
+
⏺ Bash(cs-cite r1-252,p1-5aed)
|
|
151
|
+
⎿ (No output)
|
|
152
|
+
|
|
153
|
+
⏺ ✨ 2 claude-smart learnings applied
|
|
151
154
|
```
|
|
152
155
|
|
|
153
156
|
That signals a profile entry (`p…`) or playbook rule (`r…`) materially shaped the reply. Open the interaction's detail page in the [dashboard](#dashboard) to see the exact cited item.
|
|
@@ -161,7 +164,7 @@ See [ARCHITECTURE.md](./ARCHITECTURE.md) for hooks, data flow, and reflexio deta
|
|
|
161
164
|
| Command | What it does |
|
|
162
165
|
| --- | --- |
|
|
163
166
|
| `/dashboard` | Open the dashboard in your browser, auto-starting the reflexio backend and dashboard services if they aren't already running. |
|
|
164
|
-
| `/show` | Print the current
|
|
167
|
+
| `/show` | Print the current (global) playbook plus the current project's user profiles (same markdown that `SessionStart` injects). Use it to audit what playbooks and preferences Claude is being told to follow. |
|
|
165
168
|
| `/learn` | Force reflexio to run extraction *now* on the current session's unpublished interactions. Without this, extraction runs at the end of the session or on reflexio's batch interval. |
|
|
166
169
|
| `/tag [note]` | Tag the most recent turn as a correction, for cases the automatic heuristic missed. The note becomes the correction description the extractor sees. |
|
|
167
170
|
| `/restart` | Restart the reflexio backend and dashboard to pick up new changes (e.g. after upgrading the plugin or editing local reflexio code). |
|
package/bin/claude-smart.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
"use strict";
|
|
11
11
|
|
|
12
|
-
const { execFileSync, execSync } = require("child_process");
|
|
12
|
+
const { execFileSync, execSync, spawn } = require("child_process");
|
|
13
13
|
const { appendFileSync, existsSync, mkdirSync, readFileSync } = require("fs");
|
|
14
14
|
const { homedir } = require("os");
|
|
15
15
|
const { dirname, join } = require("path");
|
|
@@ -18,6 +18,45 @@ const DEFAULT_MARKETPLACE_SOURCE = "ReflexioAI/claude-smart";
|
|
|
18
18
|
const PLUGIN_SPEC = "claude-smart@reflexioai";
|
|
19
19
|
const REFLEXIO_ENV_PATH = join(homedir(), ".reflexio", ".env");
|
|
20
20
|
|
|
21
|
+
function runClaude(args, { spinnerLabel } = {}) {
|
|
22
|
+
const useSpinner = Boolean(spinnerLabel) && process.stdout.isTTY && !process.env.CI;
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
const child = spawn("claude", args, {
|
|
25
|
+
stdio: useSpinner ? ["inherit", "pipe", "pipe"] : "inherit",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
let spinnerActive = false;
|
|
29
|
+
let timer = null;
|
|
30
|
+
if (useSpinner) {
|
|
31
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
32
|
+
let i = 0;
|
|
33
|
+
spinnerActive = true;
|
|
34
|
+
const render = () => {
|
|
35
|
+
process.stdout.write(`\r${frames[i = (i + 1) % frames.length]} ${spinnerLabel}`);
|
|
36
|
+
};
|
|
37
|
+
render();
|
|
38
|
+
timer = setInterval(render, 80);
|
|
39
|
+
|
|
40
|
+
const clear = () => {
|
|
41
|
+
if (!spinnerActive) return;
|
|
42
|
+
spinnerActive = false;
|
|
43
|
+
clearInterval(timer);
|
|
44
|
+
process.stdout.write("\r\x1b[2K");
|
|
45
|
+
};
|
|
46
|
+
const passthrough = (stream) => (chunk) => {
|
|
47
|
+
clear();
|
|
48
|
+
stream.write(chunk);
|
|
49
|
+
};
|
|
50
|
+
child.stdout.on("data", passthrough(process.stdout));
|
|
51
|
+
child.stderr.on("data", passthrough(process.stderr));
|
|
52
|
+
child.on("exit", clear);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
child.on("exit", (code) => resolve(typeof code === "number" ? code : 1));
|
|
56
|
+
child.on("error", () => resolve(1));
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
21
60
|
function hasClaudeCli() {
|
|
22
61
|
const probe = process.platform === "win32" ? "where claude" : "command -v claude";
|
|
23
62
|
try {
|
|
@@ -79,7 +118,7 @@ function parseSource(args) {
|
|
|
79
118
|
return value;
|
|
80
119
|
}
|
|
81
120
|
|
|
82
|
-
function runUpdate() {
|
|
121
|
+
async function runUpdate() {
|
|
83
122
|
if (!hasClaudeCli()) {
|
|
84
123
|
process.stderr.write(
|
|
85
124
|
"error: 'claude' CLI not found on PATH. " +
|
|
@@ -88,10 +127,10 @@ function runUpdate() {
|
|
|
88
127
|
process.exit(1);
|
|
89
128
|
}
|
|
90
129
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
130
|
+
const code = await runClaude(["plugin", "update", PLUGIN_SPEC], {
|
|
131
|
+
spinnerLabel: "Checking for claude-smart updates…",
|
|
132
|
+
});
|
|
133
|
+
if (code !== 0) {
|
|
95
134
|
process.stderr.write(`error: \`claude plugin update ${PLUGIN_SPEC}\` failed (exit ${code})\n`);
|
|
96
135
|
process.exit(code);
|
|
97
136
|
}
|
|
@@ -99,7 +138,7 @@ function runUpdate() {
|
|
|
99
138
|
process.stdout.write("\nclaude-smart updated. Restart Claude Code to apply.\n");
|
|
100
139
|
}
|
|
101
140
|
|
|
102
|
-
function runUninstall() {
|
|
141
|
+
async function runUninstall() {
|
|
103
142
|
if (!hasClaudeCli()) {
|
|
104
143
|
process.stderr.write(
|
|
105
144
|
"error: 'claude' CLI not found on PATH. " +
|
|
@@ -108,10 +147,10 @@ function runUninstall() {
|
|
|
108
147
|
process.exit(1);
|
|
109
148
|
}
|
|
110
149
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
150
|
+
const code = await runClaude(["plugin", "uninstall", PLUGIN_SPEC], {
|
|
151
|
+
spinnerLabel: "Uninstalling claude-smart…",
|
|
152
|
+
});
|
|
153
|
+
if (code !== 0) {
|
|
115
154
|
process.stderr.write(
|
|
116
155
|
`error: \`claude plugin uninstall ${PLUGIN_SPEC}\` failed (exit ${code})\n`,
|
|
117
156
|
);
|
|
@@ -128,7 +167,7 @@ function runUninstall() {
|
|
|
128
167
|
);
|
|
129
168
|
}
|
|
130
169
|
|
|
131
|
-
function runInstall(args) {
|
|
170
|
+
async function runInstall(args) {
|
|
132
171
|
if (!hasClaudeCli()) {
|
|
133
172
|
process.stderr.write(
|
|
134
173
|
"error: 'claude' CLI not found on PATH. " +
|
|
@@ -139,17 +178,15 @@ function runInstall(args) {
|
|
|
139
178
|
|
|
140
179
|
const source = parseSource(args);
|
|
141
180
|
const steps = [
|
|
142
|
-
["plugin", "marketplace", "add", source],
|
|
143
|
-
["plugin", "install", PLUGIN_SPEC],
|
|
181
|
+
{ args: ["plugin", "marketplace", "add", source], label: "Adding marketplace…" },
|
|
182
|
+
{ args: ["plugin", "install", PLUGIN_SPEC], label: "Installing claude-smart…" },
|
|
144
183
|
];
|
|
145
184
|
|
|
146
|
-
for (const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
} catch (err) {
|
|
150
|
-
const code = typeof err.status === "number" ? err.status : 1;
|
|
185
|
+
for (const step of steps) {
|
|
186
|
+
const code = await runClaude(step.args, { spinnerLabel: step.label });
|
|
187
|
+
if (code !== 0) {
|
|
151
188
|
process.stderr.write(
|
|
152
|
-
`error: \`claude ${
|
|
189
|
+
`error: \`claude ${step.args.join(" ")}\` failed (exit ${code})\n`,
|
|
153
190
|
);
|
|
154
191
|
process.exit(code);
|
|
155
192
|
}
|
|
@@ -173,7 +210,7 @@ function runInstall(args) {
|
|
|
173
210
|
);
|
|
174
211
|
}
|
|
175
212
|
|
|
176
|
-
function main() {
|
|
213
|
+
async function main() {
|
|
177
214
|
const args = process.argv.slice(2);
|
|
178
215
|
const cmd = args[0] || "install";
|
|
179
216
|
|
|
@@ -183,17 +220,17 @@ function main() {
|
|
|
183
220
|
}
|
|
184
221
|
|
|
185
222
|
if (cmd === "install") {
|
|
186
|
-
runInstall(args.slice(1));
|
|
223
|
+
await runInstall(args.slice(1));
|
|
187
224
|
return;
|
|
188
225
|
}
|
|
189
226
|
|
|
190
227
|
if (cmd === "update") {
|
|
191
|
-
runUpdate();
|
|
228
|
+
await runUpdate();
|
|
192
229
|
return;
|
|
193
230
|
}
|
|
194
231
|
|
|
195
232
|
if (cmd === "uninstall") {
|
|
196
|
-
runUninstall();
|
|
233
|
+
await runUninstall();
|
|
197
234
|
return;
|
|
198
235
|
}
|
|
199
236
|
|
|
@@ -203,4 +240,7 @@ function main() {
|
|
|
203
240
|
process.exit(1);
|
|
204
241
|
}
|
|
205
242
|
|
|
206
|
-
main()
|
|
243
|
+
main().catch((err) => {
|
|
244
|
+
process.stderr.write(`claude-smart: ${err && err.message ? err.message : err}\n`);
|
|
245
|
+
process.exit(1);
|
|
246
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-smart",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Self-improving Claude Code plugin — learns from corrections via reflexio",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -31,6 +31,6 @@
|
|
|
31
31
|
"LICENSE"
|
|
32
32
|
],
|
|
33
33
|
"engines": {
|
|
34
|
-
"node": ">=
|
|
34
|
+
"node": ">=20.9.0"
|
|
35
35
|
}
|
|
36
36
|
}
|