claude-smart 0.2.23 → 0.2.25
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/.agents/plugins/marketplace.json +20 -0
- package/README.md +76 -28
- package/bin/claude-smart.js +355 -11
- package/package.json +11 -1
- package/plugin/.claude-plugin/plugin.json +17 -0
- package/plugin/.codex-plugin/plugin.json +35 -0
- package/plugin/LICENSE +202 -0
- package/plugin/README.md +37 -0
- package/plugin/bin/cs-cite +77 -0
- package/plugin/commands/clear-all.md +8 -0
- package/plugin/commands/dashboard.md +8 -0
- package/plugin/commands/learn.md +12 -0
- package/plugin/commands/restart.md +8 -0
- package/plugin/commands/show.md +8 -0
- package/plugin/dashboard/AGENTS.md +6 -0
- package/plugin/dashboard/app/api/claude-settings/route.ts +19 -0
- package/plugin/dashboard/app/api/config/route.ts +16 -0
- package/plugin/dashboard/app/api/health/route.ts +10 -0
- package/plugin/dashboard/app/api/reflexio/[...path]/route.ts +63 -0
- package/plugin/dashboard/app/api/sessions/[id]/route.ts +28 -0
- package/plugin/dashboard/app/api/sessions/route.ts +14 -0
- package/plugin/dashboard/app/configure/env/page.tsx +318 -0
- package/plugin/dashboard/app/configure/layout.tsx +47 -0
- package/plugin/dashboard/app/configure/page.tsx +5 -0
- package/plugin/dashboard/app/configure/server/page.tsx +258 -0
- package/plugin/dashboard/app/dashboard/page.tsx +227 -0
- package/plugin/dashboard/app/globals.css +129 -0
- package/plugin/dashboard/app/icon.png +0 -0
- package/plugin/dashboard/app/layout.tsx +40 -0
- package/plugin/dashboard/app/page.tsx +5 -0
- package/plugin/dashboard/app/preferences/[id]/page.tsx +531 -0
- package/plugin/dashboard/app/preferences/page.tsx +126 -0
- package/plugin/dashboard/app/providers.tsx +12 -0
- package/plugin/dashboard/app/sessions/[sessionId]/page.tsx +321 -0
- package/plugin/dashboard/app/sessions/page.tsx +186 -0
- package/plugin/dashboard/app/skills/page.tsx +362 -0
- package/plugin/dashboard/app/skills/project/[id]/page.tsx +597 -0
- package/plugin/dashboard/app/skills/shared/[id]/page.tsx +830 -0
- package/plugin/dashboard/components/common/delete-all-button.tsx +45 -0
- package/plugin/dashboard/components/common/empty-state.tsx +34 -0
- package/plugin/dashboard/components/common/learnings-badge.tsx +34 -0
- package/plugin/dashboard/components/common/page-header.tsx +34 -0
- package/plugin/dashboard/components/common/page-tabs.tsx +115 -0
- package/plugin/dashboard/components/common/stat-card.tsx +38 -0
- package/plugin/dashboard/components/layout/nav-items.ts +22 -0
- package/plugin/dashboard/components/layout/sidebar.tsx +45 -0
- package/plugin/dashboard/components/layout/top-bar.tsx +64 -0
- package/plugin/dashboard/components/stall-banner.tsx +53 -0
- package/plugin/dashboard/components/ui/badge.tsx +52 -0
- package/plugin/dashboard/components/ui/button.tsx +60 -0
- package/plugin/dashboard/components/ui/collapsible.tsx +21 -0
- package/plugin/dashboard/components/ui/input.tsx +20 -0
- package/plugin/dashboard/components/ui/label.tsx +20 -0
- package/plugin/dashboard/components/ui/scroll-area.tsx +55 -0
- package/plugin/dashboard/components/ui/select.tsx +201 -0
- package/plugin/dashboard/components/ui/separator.tsx +25 -0
- package/plugin/dashboard/components/ui/sheet.tsx +135 -0
- package/plugin/dashboard/components/ui/switch.tsx +32 -0
- package/plugin/dashboard/components.json +25 -0
- package/plugin/dashboard/eslint.config.mjs +16 -0
- package/plugin/dashboard/hooks/use-settings.tsx +88 -0
- package/plugin/dashboard/hooks/use-stall-state.ts +59 -0
- package/plugin/dashboard/lib/claude-settings-file.ts +114 -0
- package/plugin/dashboard/lib/config-file.ts +131 -0
- package/plugin/dashboard/lib/format.ts +58 -0
- package/plugin/dashboard/lib/reflexio-client.ts +238 -0
- package/plugin/dashboard/lib/reflexio-url.ts +17 -0
- package/plugin/dashboard/lib/session-reader.ts +245 -0
- package/plugin/dashboard/lib/status.ts +24 -0
- package/plugin/dashboard/lib/types.ts +145 -0
- package/plugin/dashboard/lib/utils.ts +6 -0
- package/plugin/dashboard/next.config.ts +7 -0
- package/plugin/dashboard/package-lock.json +10275 -0
- package/plugin/dashboard/package.json +37 -0
- package/plugin/dashboard/postcss.config.mjs +7 -0
- package/plugin/dashboard/public/claude-smart-icon.png +0 -0
- package/plugin/dashboard/tsconfig.json +34 -0
- package/plugin/hooks/codex-hooks.json +67 -0
- package/plugin/hooks/hooks.json +111 -0
- package/plugin/pyproject.toml +49 -0
- package/plugin/scripts/_codex_env.sh +27 -0
- package/plugin/scripts/_lib.sh +325 -0
- package/plugin/scripts/backend-service.sh +208 -0
- package/plugin/scripts/cli.sh +40 -0
- package/plugin/scripts/dashboard-build.sh +139 -0
- package/plugin/scripts/dashboard-open.sh +107 -0
- package/plugin/scripts/dashboard-service.sh +195 -0
- package/plugin/scripts/ensure-plugin-root.sh +84 -0
- package/plugin/scripts/hook_entry.sh +70 -0
- package/plugin/scripts/smart-install.sh +411 -0
- package/plugin/src/claude_smart/__init__.py +3 -0
- package/plugin/src/claude_smart/cli.py +1342 -0
- package/plugin/src/claude_smart/context_format.py +277 -0
- package/plugin/src/claude_smart/context_inject.py +92 -0
- package/plugin/src/claude_smart/cs_cite.py +236 -0
- package/plugin/src/claude_smart/events/__init__.py +1 -0
- package/plugin/src/claude_smart/events/post_tool.py +148 -0
- package/plugin/src/claude_smart/events/pre_tool.py +52 -0
- package/plugin/src/claude_smart/events/session_end.py +20 -0
- package/plugin/src/claude_smart/events/session_start.py +119 -0
- package/plugin/src/claude_smart/events/stop.py +393 -0
- package/plugin/src/claude_smart/events/user_prompt.py +73 -0
- package/plugin/src/claude_smart/hook.py +114 -0
- package/plugin/src/claude_smart/ids.py +56 -0
- package/plugin/src/claude_smart/internal_call.py +89 -0
- package/plugin/src/claude_smart/optimizer_assistant.py +203 -0
- package/plugin/src/claude_smart/publish.py +71 -0
- package/plugin/src/claude_smart/query_compose.py +51 -0
- package/plugin/src/claude_smart/reflexio_adapter.py +403 -0
- package/plugin/src/claude_smart/runtime.py +52 -0
- package/plugin/src/claude_smart/stall_banner.py +61 -0
- package/plugin/src/claude_smart/state.py +276 -0
- package/plugin/uv.lock +3720 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "reflexioai",
|
|
3
|
+
"interface": {
|
|
4
|
+
"displayName": "ReflexioAI"
|
|
5
|
+
},
|
|
6
|
+
"plugins": [
|
|
7
|
+
{
|
|
8
|
+
"name": "claude-smart",
|
|
9
|
+
"source": {
|
|
10
|
+
"source": "local",
|
|
11
|
+
"path": "./plugin"
|
|
12
|
+
},
|
|
13
|
+
"policy": {
|
|
14
|
+
"installation": "AVAILABLE",
|
|
15
|
+
"authentication": "ON_INSTALL"
|
|
16
|
+
},
|
|
17
|
+
"category": "Productivity"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
package/README.md
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
claude-smart
|
|
7
7
|
</h1>
|
|
8
8
|
|
|
9
|
-
<h4 align="center">
|
|
9
|
+
<h4 align="center">A local learning plugin for <a href="https://claude.com/claude-code" target="_blank">Claude Code</a> and Codex that turns corrections into durable rules your coding assistant follows in future sessions.</h4>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
12
|
<a href="LICENSE">
|
|
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.
|
|
16
|
+
<img src="https://img.shields.io/badge/version-0.2.25-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">
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
<img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg" alt="Node">
|
|
23
23
|
</a>
|
|
24
24
|
<a href="#quick-start">
|
|
25
|
-
<img src="https://img.shields.io/badge/
|
|
25
|
+
<img src="https://img.shields.io/badge/hosts-Claude%20Code%20%2B%20Codex-purple.svg" alt="Hosts">
|
|
26
26
|
</a>
|
|
27
27
|
<a href="https://discord.gg/Jbft3jPn">
|
|
28
28
|
<img src="https://img.shields.io/badge/Discord-Join%20Chat-5865F2?logo=discord&logoColor=white" alt="Discord">
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
<p align="center">
|
|
33
33
|
<a href="#quick-start">Quick Start</a> •
|
|
34
34
|
<a href="#how-it-works">How It Works</a> •
|
|
35
|
-
<a href="#
|
|
35
|
+
<a href="#commands">Commands</a> •
|
|
36
36
|
<a href="#dashboard">Dashboard</a> •
|
|
37
37
|
<a href="#configuration">Configuration</a> •
|
|
38
38
|
<a href="TROUBLESHOOTING.md">Troubleshooting</a> •
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
</p>
|
|
41
41
|
|
|
42
42
|
<p align="center">
|
|
43
|
-
It learns both corrections and successful execution patterns—so
|
|
43
|
+
It learns both corrections and successful execution patterns—so your coding assistant avoids repeating mistakes and reuses what works. Project-specific skills capture repo-local rules, and shared skills roll up durable patterns for reuse across projects.
|
|
44
44
|
</p>
|
|
45
45
|
|
|
46
46
|
<p align="center">
|
|
@@ -55,7 +55,7 @@ Most memory solutions are still mostly informative—Claude remembers what happe
|
|
|
55
55
|
|
|
56
56
|
`claude-smart` focuses on learning instead.
|
|
57
57
|
|
|
58
|
-
Four ways this changes what
|
|
58
|
+
Four ways this changes what your coding assistant can do for you:
|
|
59
59
|
|
|
60
60
|
- 💡 **Stop repeating the same mistakes:** Produces actionable skills Claude can follow next time; memory only records what happened.
|
|
61
61
|
|
|
@@ -78,6 +78,8 @@ Four ways this changes what Claude Code can do for you:
|
|
|
78
78
|
|
|
79
79
|
## Quick Start
|
|
80
80
|
|
|
81
|
+
### Claude Code
|
|
82
|
+
|
|
81
83
|
```bash
|
|
82
84
|
claude plugin marketplace add ReflexioAI/claude-smart
|
|
83
85
|
claude plugin install claude-smart@reflexioai
|
|
@@ -108,10 +110,50 @@ Or, if you already have Node.js or uv:
|
|
|
108
110
|
npx claude-smart uninstall # or: uvx claude-smart uninstall
|
|
109
111
|
```
|
|
110
112
|
|
|
111
|
-
|
|
113
|
+
### Codex
|
|
114
|
+
|
|
115
|
+
You need the `codex` CLI on `PATH` and Node.js available for `npx`:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npx claude-smart install --host codex
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The helper registers the bundled **ReflexioAI** marketplace with Codex, enables
|
|
122
|
+
Codex's `plugin_hooks` feature, installs `claude-smart` into Codex's local
|
|
123
|
+
plugin cache, and enables it in `~/.codex/config.toml`. Hooks are not active in
|
|
124
|
+
already-running Codex windows; after the command finishes:
|
|
125
|
+
|
|
126
|
+
1. Fully quit and reopen Codex in your project so hooks reload.
|
|
127
|
+
2. Run `/plugins` only if you want to verify `claude-smart` shows as installed
|
|
128
|
+
from the **ReflexioAI** marketplace.
|
|
129
|
+
|
|
130
|
+
If you install or toggle `claude-smart` manually from `/plugins`, still run
|
|
131
|
+
`npx claude-smart install --host codex` once afterward so `plugin_hooks` is
|
|
132
|
+
enabled and the cache/config are prepared.
|
|
133
|
+
|
|
134
|
+
Do not create a `~/plugins/claude-smart` symlink for a normal `npx` install;
|
|
135
|
+
that symlink is only for plugin development from a cloned checkout.
|
|
136
|
+
|
|
137
|
+
Installing from a clone is only for plugin development; see
|
|
138
|
+
[DEVELOPER.md](./DEVELOPER.md#developing-locally).
|
|
139
|
+
|
|
140
|
+
Codex and Claude Code intentionally share the same `CLAUDE_SMART_*` environment
|
|
141
|
+
variables, `~/.reflexio/` data, `~/.claude-smart/` session buffers, backend,
|
|
142
|
+
dashboard, and learned skills/preferences.
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
To uninstall:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npx claude-smart uninstall --host codex
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
This removes the Codex marketplace registration, installed plugin config, and
|
|
152
|
+
Codex plugin cache. Local data under `~/.reflexio/` and `~/.claude-smart/` is
|
|
153
|
+
left in place — remove manually if desired. Restart Codex after uninstalling.
|
|
112
154
|
|
|
113
155
|
Developing the plugin itself? See [DEVELOPER.md](./DEVELOPER.md#developing-locally).
|
|
114
|
-
> **Not supported:** Claude Code Cowork
|
|
156
|
+
> **Not supported:** Claude Code Cowork, claude.ai/code web, or remote Codex environments without local plugin hooks — they run outside your local machine, so the local backend/dashboard and `~/.reflexio/` aren't reachable.
|
|
115
157
|
|
|
116
158
|
---
|
|
117
159
|
|
|
@@ -124,13 +166,13 @@ Developing the plugin itself? See [DEVELOPER.md](./DEVELOPER.md#developing-local
|
|
|
124
166
|
- 🔌 **No external API call** — semantic search runs on an in-process ONNX embedder (all-MiniLM-L6-v2), and all data (preferences, skills, interaction buffers) is stored locally on your machine (`~/.reflexio/` and `~/.claude-smart/`).
|
|
125
167
|
- 🔎 **Hybrid search** — Skills and preferences are indexed with vector + BM25 search for fast, robust retrieval.
|
|
126
168
|
- 🧪 **Offline resilience** — If the reflexio backend is down, hooks buffer to disk; the next successful publish drains them.
|
|
127
|
-
- 🧰 **Manual correction marker** — `/claude-smart:learn` flags the last turn as a correction so the extractor weights it heavily.
|
|
169
|
+
- 🧰 **Manual correction marker** — `/claude-smart:learn` in Claude Code, or `bash ~/.reflexio/plugin-root/scripts/cli.sh learn` in Codex, flags the last turn as a correction so the extractor weights it heavily.
|
|
128
170
|
|
|
129
171
|
---
|
|
130
172
|
|
|
131
173
|
## Dashboard
|
|
132
174
|
|
|
133
|
-
A web UI for browsing session histories, inspecting preferences, and editing project-specific and shared skills. 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.
|
|
175
|
+
A web UI for browsing session histories, inspecting preferences, and editing project-specific and shared skills. 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. In Codex, run `bash ~/.reflexio/plugin-root/scripts/dashboard-open.sh`.
|
|
134
176
|
|
|
135
177
|
<p align="center">
|
|
136
178
|
<img src="assets/preferences_dashboard.png" alt="Preferences dashboard" width="49%">
|
|
@@ -141,7 +183,7 @@ A web UI for browsing session histories, inspecting preferences, and editing pro
|
|
|
141
183
|
|
|
142
184
|
## How It Works
|
|
143
185
|
|
|
144
|
-
claude-smart builds three artifacts as you work and injects the relevant ones into Claude:
|
|
186
|
+
claude-smart builds three artifacts as you work and injects the relevant ones into Claude Code or Codex:
|
|
145
187
|
|
|
146
188
|
- **Preferences** (project-scoped) — 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."
|
|
147
189
|
- **Project-specific skills** — durable rules with triggers and rationales learned from corrections in a project. *e.g.* "always pass `--run` to `npm test` — watch mode hangs CI."
|
|
@@ -149,32 +191,36 @@ claude-smart builds three artifacts as you work and injects the relevant ones in
|
|
|
149
191
|
|
|
150
192
|
Skills clean themselves up: correct the same thing twice and they merge; change your mind and the old one is archived.
|
|
151
193
|
|
|
152
|
-
Under the hood: hooks watch your turns, tool calls, and
|
|
194
|
+
Under the hood: hooks watch your turns, tool calls, and assistant replies, auto-flagging corrections (or anything you flag with `/claude-smart:learn`). At session end (or on `/claude-smart:learn`), [reflexio](https://github.com/ReflexioAI/reflexio) — the self-improving engine that powers claude-smart — extracts preferences and project-specific skills, then rolls durable patterns into shared skills. On each new user prompt, claude-smart searches for matching context and injects only the relevant hits. Run `/claude-smart:show` or the equivalent CLI command to audit the current learned state. Everything runs on your machine.
|
|
153
195
|
|
|
154
|
-
**Citations
|
|
196
|
+
**Citations.** At the end of a reply, the assistant may append a short marker:
|
|
155
197
|
|
|
156
198
|
```
|
|
157
|
-
|
|
158
|
-
⎿ (No output)
|
|
159
|
-
|
|
160
|
-
⏺ ✨ 2 claude-smart learnings applied
|
|
199
|
+
✨ 2 claude-smart learnings applied [cs:s1-252,p1-5aed]
|
|
161
200
|
```
|
|
162
201
|
|
|
163
|
-
That signals a preference (`p…`) or skill (`s…`) materially shaped the reply.
|
|
202
|
+
That signals a preference (`p…`) or skill (`s…`) materially shaped the reply.
|
|
203
|
+
Standalone wrappers like `✨abc123✨` are not claude-smart citations and will not
|
|
204
|
+
link back to dashboard entries. Open the interaction's detail page in the
|
|
205
|
+
[dashboard](#dashboard) to see the exact cited item.
|
|
164
206
|
|
|
165
207
|
See [ARCHITECTURE.md](./ARCHITECTURE.md) for hooks, data flow, and reflexio details.
|
|
166
208
|
|
|
167
209
|
---
|
|
168
210
|
|
|
169
|
-
##
|
|
211
|
+
## Commands
|
|
170
212
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
|
176
|
-
|
|
|
177
|
-
| `/
|
|
213
|
+
Claude Code installs these as plugin slash commands. Codex does not currently
|
|
214
|
+
support these plugin-provided slash commands, so run the equivalent shell command
|
|
215
|
+
directly, or ask Codex to run it.
|
|
216
|
+
|
|
217
|
+
| Claude Code | Codex / shell | What it does |
|
|
218
|
+
| --- | --- | --- |
|
|
219
|
+
| `/claude-smart:dashboard` | `bash ~/.reflexio/plugin-root/scripts/dashboard-open.sh` | Open the dashboard in your browser, auto-starting the reflexio backend and dashboard services if they aren't already running. |
|
|
220
|
+
| `/claude-smart:show` | `bash ~/.reflexio/plugin-root/scripts/cli.sh show` | Print current project-specific skills, shared skills, and the current project's preferences so you can audit learned state manually. |
|
|
221
|
+
| `/claude-smart:learn [note]` | `bash ~/.reflexio/plugin-root/scripts/cli.sh learn --note "optional note"` | Flag the most recent turn as a correction (for cases the automatic heuristic missed) and force reflexio to run extraction *now* on the session's unpublished interactions. The optional note becomes the correction description the extractor sees. |
|
|
222
|
+
| `/claude-smart:restart` | `bash ~/.reflexio/plugin-root/scripts/cli.sh restart` | Restart the reflexio backend and dashboard to pick up new changes (e.g. after upgrading the plugin or editing local reflexio code). |
|
|
223
|
+
| `/claude-smart:clear-all` | `bash ~/.reflexio/plugin-root/scripts/cli.sh clear-all --yes` | **Destructive.** Delete *all* reflexio interactions, preferences, and skills. Use when you want to wipe learned state and start fresh. |
|
|
178
224
|
|
|
179
225
|
---
|
|
180
226
|
|
|
@@ -189,7 +235,9 @@ Advanced users can tune claude-smart via environment variables — see [DEVELOPE
|
|
|
189
235
|
| `~/.reflexio/data/reflexio.db` | Source of truth for learned preferences, skills, interactions, full-text indexes, and embedding tables (plus `.db-shm` / `.db-wal` WAL sidecars). Inspect with `sqlite3`. |
|
|
190
236
|
| `~/.reflexio/.env` | Provider config — `CLAUDE_SMART_USE_LOCAL_CLI`, `CLAUDE_SMART_USE_LOCAL_EMBEDDING`, any optional API keys. |
|
|
191
237
|
| `.claude/settings.local.json` or `~/.claude/settings.json` | Claude Code hook environment, such as `CLAUDE_SMART_ENABLE_OPTIMIZER`; use project-local settings for one repo or user settings for all projects. |
|
|
192
|
-
| `~/.
|
|
238
|
+
| `~/.codex/config.toml` | Codex feature flags, including `plugin_hooks = true` after `claude-smart install --host codex`. |
|
|
239
|
+
| `~/.codex/plugins/cache/reflexioai/claude-smart/<version>/` | Codex's cached install of the `claude-smart` plugin from the `ReflexioAI` marketplace. |
|
|
240
|
+
| `~/.reflexio/plugin-root` | Self-healed symlink to the active plugin dir (managed by `ensure-plugin-root.sh` — written on install, refreshed each `SessionStart`). Claude Code slash commands and Codex shell-command helpers resolve through it, so don't delete it; if you do, the next session will recreate it. |
|
|
193
241
|
| `~/.claude-smart/sessions/{session_id}.jsonl` | Per-session buffer. User turns, assistant turns, tool invocations, `{"published_up_to": N}` watermarks. Safe to inspect and safe to delete — everything past the latest watermark has already been written to reflexio's DB. |
|
|
194
242
|
| `~/.cache/chroma/onnx_models/all-MiniLM-L6-v2/` | Cached ONNX weights (~86 MB, downloaded once). Delete to force a re-download. |
|
|
195
243
|
|
|
@@ -211,4 +259,4 @@ See the [LICENSE](LICENSE) file for details.
|
|
|
211
259
|
|
|
212
260
|
---
|
|
213
261
|
|
|
214
|
-
**Built on** [reflexio](https://github.com/ReflexioAI/reflexio) · **Runs on** [Claude Code](https://claude.com/claude-code) · **Written in** Python 3.12+
|
|
262
|
+
**Built on** [reflexio](https://github.com/ReflexioAI/reflexio) · **Runs on** [Claude Code](https://claude.com/claude-code) and Codex · **Written in** Python 3.12+
|
package/bin/claude-smart.js
CHANGED
|
@@ -1,22 +1,75 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* npx claude-smart install — thin wrapper around the native
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* npx claude-smart install — thin wrapper around the native host plugin
|
|
4
|
+
* CLIs. For Claude Code it registers the GitHub marketplace and installs the
|
|
5
|
+
* plugin. For Codex it copies the bundled local marketplace, registers it,
|
|
6
|
+
* and enables plugin hooks. Both paths seed ~/.reflexio/.env with the two
|
|
7
|
+
* local-provider flags so reflexio can route generation through local tools
|
|
8
|
+
* with no API key.
|
|
7
9
|
*
|
|
8
10
|
* Keep this file dependency-free — it runs via `npx` with no install step.
|
|
9
11
|
*/
|
|
10
12
|
"use strict";
|
|
11
13
|
|
|
12
|
-
const {
|
|
13
|
-
const {
|
|
14
|
+
const { execSync, spawn } = require("child_process");
|
|
15
|
+
const {
|
|
16
|
+
appendFileSync,
|
|
17
|
+
cpSync,
|
|
18
|
+
existsSync,
|
|
19
|
+
mkdirSync,
|
|
20
|
+
readFileSync,
|
|
21
|
+
rmSync,
|
|
22
|
+
writeFileSync,
|
|
23
|
+
} = require("fs");
|
|
14
24
|
const { homedir } = require("os");
|
|
15
25
|
const { dirname, join } = require("path");
|
|
16
26
|
|
|
17
27
|
const DEFAULT_MARKETPLACE_SOURCE = "ReflexioAI/claude-smart";
|
|
18
28
|
const PLUGIN_SPEC = "claude-smart@reflexioai";
|
|
29
|
+
const CODEX_MARKETPLACE_NAME = "reflexioai";
|
|
30
|
+
const CODEX_MARKETPLACE_DISPLAY_NAME = "ReflexioAI";
|
|
31
|
+
const CODEX_PLUGIN_ID = `claude-smart@${CODEX_MARKETPLACE_NAME}`;
|
|
19
32
|
const REFLEXIO_ENV_PATH = join(homedir(), ".reflexio", ".env");
|
|
33
|
+
const CODEX_CONFIG_PATH = join(homedir(), ".codex", "config.toml");
|
|
34
|
+
const PACKAGE_ROOT = dirname(dirname(__filename));
|
|
35
|
+
const CODEX_MARKETPLACE_DIR = join(
|
|
36
|
+
homedir(),
|
|
37
|
+
".claude",
|
|
38
|
+
"plugins",
|
|
39
|
+
"marketplaces",
|
|
40
|
+
CODEX_MARKETPLACE_NAME,
|
|
41
|
+
);
|
|
42
|
+
const CODEX_MARKETPLACE_PLUGIN_PATH = join("plugins", "claude-smart");
|
|
43
|
+
const CODEX_PLUGIN_CACHE_DIR = join(
|
|
44
|
+
homedir(),
|
|
45
|
+
".codex",
|
|
46
|
+
"plugins",
|
|
47
|
+
"cache",
|
|
48
|
+
CODEX_MARKETPLACE_NAME,
|
|
49
|
+
"claude-smart",
|
|
50
|
+
);
|
|
51
|
+
const CODEX_REQUIRED_FILES = [
|
|
52
|
+
".agents/plugins/marketplace.json",
|
|
53
|
+
"plugin/.codex-plugin/plugin.json",
|
|
54
|
+
"plugin/hooks/codex-hooks.json",
|
|
55
|
+
"plugin/scripts/_codex_env.sh",
|
|
56
|
+
];
|
|
57
|
+
const CODEX_CLI_TIMEOUT_MS = 30_000;
|
|
58
|
+
const COPYTREE_IGNORE_NAMES = new Set([
|
|
59
|
+
"__pycache__",
|
|
60
|
+
".venv",
|
|
61
|
+
".pytest_cache",
|
|
62
|
+
".ruff_cache",
|
|
63
|
+
"node_modules",
|
|
64
|
+
".next",
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
function shouldCopyPath(src) {
|
|
68
|
+
const base = src.split(/[\\/]/).pop() || "";
|
|
69
|
+
if (COPYTREE_IGNORE_NAMES.has(base)) return false;
|
|
70
|
+
if (base.endsWith(".pyc") || base.endsWith(".pyo")) return false;
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
20
73
|
|
|
21
74
|
function runClaude(args, { spinnerLabel } = {}) {
|
|
22
75
|
const useSpinner = Boolean(spinnerLabel) && process.stdout.isTTY && !process.env.CI;
|
|
@@ -80,7 +133,11 @@ function runClaude(args, { spinnerLabel } = {}) {
|
|
|
80
133
|
}
|
|
81
134
|
|
|
82
135
|
function hasClaudeCli() {
|
|
83
|
-
|
|
136
|
+
return hasCli("claude");
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function hasCli(name) {
|
|
140
|
+
const probe = process.platform === "win32" ? `where ${name}` : `command -v ${name}`;
|
|
84
141
|
try {
|
|
85
142
|
execSync(probe, { stdio: "ignore" });
|
|
86
143
|
return true;
|
|
@@ -89,6 +146,30 @@ function hasClaudeCli() {
|
|
|
89
146
|
}
|
|
90
147
|
}
|
|
91
148
|
|
|
149
|
+
function runCodex(args) {
|
|
150
|
+
return new Promise((resolve) => {
|
|
151
|
+
const child = spawn("codex", args, {
|
|
152
|
+
stdio: "inherit",
|
|
153
|
+
timeout: CODEX_CLI_TIMEOUT_MS,
|
|
154
|
+
killSignal: "SIGTERM",
|
|
155
|
+
});
|
|
156
|
+
let timedOut = false;
|
|
157
|
+
child.on("exit", (code, signal) => {
|
|
158
|
+
if (signal === "SIGTERM" && code === null) {
|
|
159
|
+
timedOut = true;
|
|
160
|
+
process.stderr.write(
|
|
161
|
+
`error: codex ${args.join(" ")} timed out after ${CODEX_CLI_TIMEOUT_MS / 1000}s\n`,
|
|
162
|
+
);
|
|
163
|
+
resolve(124);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (timedOut) return;
|
|
167
|
+
resolve(typeof code === "number" ? code : 1);
|
|
168
|
+
});
|
|
169
|
+
child.on("error", () => resolve(1));
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
92
173
|
function seedReflexioEnv() {
|
|
93
174
|
mkdirSync(dirname(REFLEXIO_ENV_PATH), { recursive: true });
|
|
94
175
|
const existing = existsSync(REFLEXIO_ENV_PATH)
|
|
@@ -106,19 +187,28 @@ function seedReflexioEnv() {
|
|
|
106
187
|
function printHelp() {
|
|
107
188
|
process.stdout.write(
|
|
108
189
|
[
|
|
109
|
-
"claude-smart — install helper for
|
|
190
|
+
"claude-smart — install helper for Claude Code and Codex",
|
|
110
191
|
"",
|
|
111
192
|
"Usage:",
|
|
112
193
|
" npx claude-smart install Install the plugin into Claude Code",
|
|
194
|
+
" npx claude-smart install --host codex Register the plugin marketplace for Codex",
|
|
113
195
|
" npx claude-smart install --source <owner/repo> Override the marketplace source",
|
|
196
|
+
" npx claude-smart uninstall --host codex Remove the Codex marketplace registration",
|
|
114
197
|
" npx claude-smart --help Show this help",
|
|
115
198
|
"",
|
|
116
|
-
"
|
|
199
|
+
"Claude Code install:",
|
|
117
200
|
" 1. claude plugin marketplace add <source>",
|
|
118
201
|
` 2. claude plugin install ${PLUGIN_SPEC}`,
|
|
119
202
|
" 3. Appends CLAUDE_SMART_USE_LOCAL_CLI=1 and CLAUDE_SMART_USE_LOCAL_EMBEDDING=1",
|
|
120
203
|
" to ~/.reflexio/.env (idempotent).",
|
|
121
204
|
"",
|
|
205
|
+
"Codex install:",
|
|
206
|
+
` 1. Copies the bundled marketplace to ${CODEX_MARKETPLACE_DIR}`,
|
|
207
|
+
" 2. codex plugin marketplace add <copied marketplace>",
|
|
208
|
+
" 3. codex features enable plugin_hooks",
|
|
209
|
+
" 4. Installs claude-smart into Codex's plugin cache and enables it",
|
|
210
|
+
" 5. Restart Codex.",
|
|
211
|
+
"",
|
|
122
212
|
"Update:",
|
|
123
213
|
" npx claude-smart update Update to the latest version",
|
|
124
214
|
"",
|
|
@@ -140,6 +230,165 @@ function parseSource(args) {
|
|
|
140
230
|
return value;
|
|
141
231
|
}
|
|
142
232
|
|
|
233
|
+
function parseHost(args) {
|
|
234
|
+
const idx = args.indexOf("--host");
|
|
235
|
+
if (idx === -1) return "claude-code";
|
|
236
|
+
const value = args[idx + 1];
|
|
237
|
+
if (!value) {
|
|
238
|
+
process.stderr.write("error: --host requires a value: claude-code or codex\n");
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
if (value !== "claude-code" && value !== "codex") {
|
|
242
|
+
process.stderr.write("error: --host must be claude-code or codex\n");
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function copyCodexMarketplace() {
|
|
249
|
+
for (const rel of CODEX_REQUIRED_FILES) {
|
|
250
|
+
const path = join(PACKAGE_ROOT, rel);
|
|
251
|
+
if (!existsSync(path)) {
|
|
252
|
+
process.stderr.write(
|
|
253
|
+
`error: published package is missing ${rel}; reinstall claude-smart or use a newer release\n`,
|
|
254
|
+
);
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
rmSync(CODEX_MARKETPLACE_DIR, { recursive: true, force: true });
|
|
260
|
+
mkdirSync(join(CODEX_MARKETPLACE_DIR, ".agents", "plugins"), { recursive: true });
|
|
261
|
+
mkdirSync(join(CODEX_MARKETPLACE_DIR, "plugins"), { recursive: true });
|
|
262
|
+
|
|
263
|
+
writeFileSync(
|
|
264
|
+
join(CODEX_MARKETPLACE_DIR, ".agents", "plugins", "marketplace.json"),
|
|
265
|
+
JSON.stringify(
|
|
266
|
+
{
|
|
267
|
+
name: CODEX_MARKETPLACE_NAME,
|
|
268
|
+
interface: { displayName: CODEX_MARKETPLACE_DISPLAY_NAME },
|
|
269
|
+
plugins: [
|
|
270
|
+
{
|
|
271
|
+
name: "claude-smart",
|
|
272
|
+
source: {
|
|
273
|
+
source: "local",
|
|
274
|
+
path: `./${CODEX_MARKETPLACE_PLUGIN_PATH}`,
|
|
275
|
+
},
|
|
276
|
+
policy: {
|
|
277
|
+
installation: "AVAILABLE",
|
|
278
|
+
authentication: "ON_INSTALL",
|
|
279
|
+
},
|
|
280
|
+
category: "Productivity",
|
|
281
|
+
},
|
|
282
|
+
],
|
|
283
|
+
},
|
|
284
|
+
null,
|
|
285
|
+
2,
|
|
286
|
+
) + "\n",
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
cpSync(join(PACKAGE_ROOT, "plugin"), join(CODEX_MARKETPLACE_DIR, CODEX_MARKETPLACE_PLUGIN_PATH), {
|
|
290
|
+
recursive: true,
|
|
291
|
+
force: true,
|
|
292
|
+
verbatimSymlinks: false,
|
|
293
|
+
filter: shouldCopyPath,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
for (const rel of ["README.md", "LICENSE", "package.json"]) {
|
|
297
|
+
const src = join(PACKAGE_ROOT, rel);
|
|
298
|
+
if (existsSync(src)) {
|
|
299
|
+
cpSync(src, join(CODEX_MARKETPLACE_DIR, rel), {
|
|
300
|
+
recursive: true,
|
|
301
|
+
force: true,
|
|
302
|
+
verbatimSymlinks: false,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return CODEX_MARKETPLACE_DIR;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function removeTomlSections(path, { exact, prefixes = [] }) {
|
|
310
|
+
if (!existsSync(path)) return true;
|
|
311
|
+
const text = readFileSync(path, "utf8");
|
|
312
|
+
if (!text) return true;
|
|
313
|
+
|
|
314
|
+
let changed = false;
|
|
315
|
+
let dropping = false;
|
|
316
|
+
const lines = text.split(/(?<=\n)/);
|
|
317
|
+
const kept = [];
|
|
318
|
+
for (const line of lines) {
|
|
319
|
+
const match = line.match(/^\s*\[([^\]]+)\]\s*(?:#.*)?$/);
|
|
320
|
+
if (match) {
|
|
321
|
+
const name = match[1].trim();
|
|
322
|
+
dropping = exact.has(name) || prefixes.some((prefix) => name.startsWith(prefix));
|
|
323
|
+
changed = changed || dropping;
|
|
324
|
+
}
|
|
325
|
+
if (!dropping) kept.push(line);
|
|
326
|
+
}
|
|
327
|
+
if (changed) writeFileSync(path, kept.join(""));
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function cleanupCodexInstallState() {
|
|
332
|
+
removeTomlSections(CODEX_CONFIG_PATH, {
|
|
333
|
+
exact: new Set([
|
|
334
|
+
`plugins."${CODEX_PLUGIN_ID}"`,
|
|
335
|
+
`marketplaces.${CODEX_MARKETPLACE_NAME}`,
|
|
336
|
+
]),
|
|
337
|
+
prefixes: [`hooks.state."${CODEX_PLUGIN_ID}:`],
|
|
338
|
+
});
|
|
339
|
+
rmSync(CODEX_MARKETPLACE_DIR, { recursive: true, force: true });
|
|
340
|
+
rmSync(CODEX_PLUGIN_CACHE_DIR, { recursive: true, force: true });
|
|
341
|
+
try {
|
|
342
|
+
rmSync(dirname(CODEX_PLUGIN_CACHE_DIR), { recursive: false, force: true });
|
|
343
|
+
} catch {
|
|
344
|
+
// Leave the marketplace cache parent if Codex has other entries there.
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function setCodexPluginEnabled() {
|
|
349
|
+
const sectionName = `plugins."${CODEX_PLUGIN_ID}"`;
|
|
350
|
+
removeTomlSections(CODEX_CONFIG_PATH, { exact: new Set([sectionName]) });
|
|
351
|
+
const existing = existsSync(CODEX_CONFIG_PATH)
|
|
352
|
+
? readFileSync(CODEX_CONFIG_PATH, "utf8")
|
|
353
|
+
: "";
|
|
354
|
+
let next = existing;
|
|
355
|
+
if (next && !next.endsWith("\n")) next += "\n";
|
|
356
|
+
if (next.trim()) next += "\n";
|
|
357
|
+
next += `[${sectionName}]\nenabled = true\n`;
|
|
358
|
+
mkdirSync(dirname(CODEX_CONFIG_PATH), { recursive: true });
|
|
359
|
+
writeFileSync(CODEX_CONFIG_PATH, next);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function codexPluginVersion(pluginRoot) {
|
|
363
|
+
try {
|
|
364
|
+
const manifest = JSON.parse(
|
|
365
|
+
readFileSync(join(pluginRoot, ".codex-plugin", "plugin.json"), "utf8"),
|
|
366
|
+
);
|
|
367
|
+
return typeof manifest.version === "string" && manifest.version
|
|
368
|
+
? manifest.version
|
|
369
|
+
: null;
|
|
370
|
+
} catch {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function installCodexPluginCache(pluginRoot) {
|
|
376
|
+
const version = codexPluginVersion(pluginRoot);
|
|
377
|
+
if (!version) {
|
|
378
|
+
throw new Error(`missing version in ${join(pluginRoot, ".codex-plugin", "plugin.json")}`);
|
|
379
|
+
}
|
|
380
|
+
const cacheDir = join(CODEX_PLUGIN_CACHE_DIR, version);
|
|
381
|
+
rmSync(cacheDir, { recursive: true, force: true });
|
|
382
|
+
mkdirSync(dirname(cacheDir), { recursive: true });
|
|
383
|
+
cpSync(pluginRoot, cacheDir, {
|
|
384
|
+
recursive: true,
|
|
385
|
+
force: true,
|
|
386
|
+
verbatimSymlinks: false,
|
|
387
|
+
});
|
|
388
|
+
setCodexPluginEnabled();
|
|
389
|
+
return cacheDir;
|
|
390
|
+
}
|
|
391
|
+
|
|
143
392
|
async function runUpdate() {
|
|
144
393
|
if (!hasClaudeCli()) {
|
|
145
394
|
process.stderr.write(
|
|
@@ -160,7 +409,12 @@ async function runUpdate() {
|
|
|
160
409
|
process.stdout.write("\nclaude-smart updated. Restart Claude Code to apply.\n");
|
|
161
410
|
}
|
|
162
411
|
|
|
163
|
-
async function runUninstall() {
|
|
412
|
+
async function runUninstall(args) {
|
|
413
|
+
if (parseHost(args) === "codex") {
|
|
414
|
+
await runUninstallCodex();
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
|
|
164
418
|
if (!hasClaudeCli()) {
|
|
165
419
|
process.stderr.write(
|
|
166
420
|
"error: 'claude' CLI not found on PATH. " +
|
|
@@ -190,6 +444,11 @@ async function runUninstall() {
|
|
|
190
444
|
}
|
|
191
445
|
|
|
192
446
|
async function runInstall(args) {
|
|
447
|
+
if (parseHost(args) === "codex") {
|
|
448
|
+
await runInstallCodex();
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
193
452
|
if (!hasClaudeCli()) {
|
|
194
453
|
process.stderr.write(
|
|
195
454
|
"error: 'claude' CLI not found on PATH. " +
|
|
@@ -232,6 +491,91 @@ async function runInstall(args) {
|
|
|
232
491
|
);
|
|
233
492
|
}
|
|
234
493
|
|
|
494
|
+
async function runInstallCodex() {
|
|
495
|
+
if (!hasCli("codex")) {
|
|
496
|
+
process.stderr.write("error: 'codex' CLI not found on PATH. Install Codex first.\n");
|
|
497
|
+
process.exit(1);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const marketplaceRoot = copyCodexMarketplace();
|
|
501
|
+
process.stdout.write(`Prepared Codex marketplace at ${marketplaceRoot}.\n`);
|
|
502
|
+
|
|
503
|
+
let code = await runCodex(["plugin", "marketplace", "add", marketplaceRoot]);
|
|
504
|
+
if (code !== 0) {
|
|
505
|
+
process.stderr.write(
|
|
506
|
+
`warning: \`codex plugin marketplace add ${marketplaceRoot}\` failed; retrying after removing ${CODEX_MARKETPLACE_NAME}.\n`,
|
|
507
|
+
);
|
|
508
|
+
await runCodex(["plugin", "marketplace", "remove", CODEX_MARKETPLACE_NAME]);
|
|
509
|
+
code = await runCodex(["plugin", "marketplace", "add", marketplaceRoot]);
|
|
510
|
+
}
|
|
511
|
+
if (code !== 0) {
|
|
512
|
+
process.stderr.write(
|
|
513
|
+
`error: could not register Codex marketplace. Run manually: codex plugin marketplace add ${marketplaceRoot}\n`,
|
|
514
|
+
);
|
|
515
|
+
process.exit(code);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
code = await runCodex(["features", "enable", "plugin_hooks"]);
|
|
519
|
+
if (code !== 0) {
|
|
520
|
+
process.stderr.write("error: could not enable Codex plugin_hooks feature.\n");
|
|
521
|
+
process.exit(code);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
let cacheDir = null;
|
|
525
|
+
try {
|
|
526
|
+
cacheDir = installCodexPluginCache(join(marketplaceRoot, CODEX_MARKETPLACE_PLUGIN_PATH));
|
|
527
|
+
process.stdout.write(`Installed Codex plugin cache at ${cacheDir}.\n`);
|
|
528
|
+
} catch (err) {
|
|
529
|
+
process.stderr.write(
|
|
530
|
+
`error: automatic Codex plugin install failed: ${err && err.message ? err.message : err}\n`,
|
|
531
|
+
);
|
|
532
|
+
process.stderr.write(
|
|
533
|
+
`Open Codex, run /plugins, and install claude-smart from the ${CODEX_MARKETPLACE_DISPLAY_NAME} marketplace manually.\n`,
|
|
534
|
+
);
|
|
535
|
+
process.exit(1);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const added = seedReflexioEnv();
|
|
539
|
+
if (added.length > 0) {
|
|
540
|
+
process.stdout.write(`Seeded ${REFLEXIO_ENV_PATH} with ${added.join(", ")}.\n`);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
process.stdout.write(
|
|
544
|
+
[
|
|
545
|
+
"",
|
|
546
|
+
"claude-smart Codex support is installed.",
|
|
547
|
+
`Restart Codex so the installed plugin and hooks reload. /plugins should show claude-smart as installed from the ${CODEX_MARKETPLACE_DISPLAY_NAME} marketplace.`,
|
|
548
|
+
"Local data is shared with Claude Code under ~/.reflexio/ and ~/.claude-smart/.",
|
|
549
|
+
"",
|
|
550
|
+
].join("\n"),
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
async function runUninstallCodex() {
|
|
555
|
+
if (!hasCli("codex")) {
|
|
556
|
+
process.stdout.write("Codex CLI not found; skipping marketplace removal.\n");
|
|
557
|
+
cleanupCodexInstallState();
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const code = await runCodex(["plugin", "marketplace", "remove", CODEX_MARKETPLACE_NAME]);
|
|
562
|
+
if (code !== 0) {
|
|
563
|
+
process.stderr.write(
|
|
564
|
+
`warning: Codex marketplace removal failed; remove manually with: codex plugin marketplace remove ${CODEX_MARKETPLACE_NAME}\n`,
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
cleanupCodexInstallState();
|
|
568
|
+
|
|
569
|
+
process.stdout.write(
|
|
570
|
+
[
|
|
571
|
+
"",
|
|
572
|
+
"claude-smart Codex plugin and marketplace state removed. Restart Codex to apply.",
|
|
573
|
+
"Codex's global plugin_hooks feature and local data under ~/.reflexio/ and ~/.claude-smart/ were left in place.",
|
|
574
|
+
"",
|
|
575
|
+
].join("\n"),
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
|
|
235
579
|
async function main() {
|
|
236
580
|
const args = process.argv.slice(2);
|
|
237
581
|
const cmd = args[0] || "install";
|
|
@@ -252,7 +596,7 @@ async function main() {
|
|
|
252
596
|
}
|
|
253
597
|
|
|
254
598
|
if (cmd === "uninstall") {
|
|
255
|
-
await runUninstall();
|
|
599
|
+
await runUninstall(args.slice(1));
|
|
256
600
|
return;
|
|
257
601
|
}
|
|
258
602
|
|