@quantiya/codevibe 1.0.5 → 1.0.7

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 (2) hide show
  1. package/bin/codevibe +149 -17
  2. package/package.json +2 -2
package/bin/codevibe CHANGED
@@ -103,42 +103,174 @@ show_version() {
103
103
  }
104
104
 
105
105
  # ─── Update ──────────────────────────────────────────────────────────
106
+ #
107
+ # NOTE: Claude Code's plugin lifecycle has known bugs as of Claude Code 2.1.x:
108
+ # 1. `claude plugin update` lies — reports "already at latest version" based on
109
+ # the installed plugin's own package.json, never consults the marketplace
110
+ # manifest for the authoritative latest version.
111
+ # 2. `claude plugin install` doesn't refetch — if a cache directory for the
112
+ # plugin exists, it reuses it silently instead of downloading the version
113
+ # pinned in the marketplace manifest.
114
+ # 3. `claude plugin uninstall` doesn't delete the cached plugin directory —
115
+ # only removes the installed_plugins.json entry, leaving stale code on disk
116
+ # for the next install to silently reuse.
117
+ #
118
+ # This function works around all three by detecting when the installed version
119
+ # on disk doesn't match the version the marketplace says it should be, then
120
+ # manually clearing all stale cache paths before reinstalling and verifying.
121
+ #
122
+ # If Anthropic fixes these bugs, the cache-nuking path is a no-op (the version
123
+ # comparison will always match) and the code stays correct.
124
+
125
+ _read_marketplace_version() {
126
+ # Read the pinned source.version for codevibe-claude from the marketplace manifest.
127
+ # Echoes the version string, or empty on failure.
128
+ local manifest="$HOME/.claude/plugins/marketplaces/codevibe-marketplace/.claude-plugin/marketplace.json"
129
+ [ -f "$manifest" ] || return 0
130
+ node -p "
131
+ try {
132
+ const m = require('$manifest');
133
+ const p = (m.plugins || []).find(x => x.name === 'codevibe-claude');
134
+ (p && p.source && p.source.version) || '';
135
+ } catch (e) { '' }
136
+ " 2>/dev/null
137
+ }
138
+
139
+ _read_installed_version() {
140
+ # Read the installed version of codevibe-claude from installed_plugins.json.
141
+ # Echoes the version string, or empty if not installed.
142
+ local db="$HOME/.claude/plugins/installed_plugins.json"
143
+ [ -f "$db" ] || return 0
144
+ node -p "
145
+ try {
146
+ const ip = require('$db');
147
+ const e = (ip.plugins || {})['codevibe-claude@codevibe-marketplace'];
148
+ (e && e[0] && e[0].version) || '';
149
+ } catch (e) { '' }
150
+ " 2>/dev/null
151
+ }
152
+
153
+ _nuke_claude_plugin_cache() {
154
+ # Remove every path Claude Code's plugin loader might read stale code from.
155
+ rm -rf "$HOME/.claude/plugins/cache/codevibe-marketplace/codevibe-claude"
156
+ rm -rf "$HOME/.claude/plugins/npm-cache/node_modules/@quantiya/codevibe-claude-plugin"
157
+ rm -rf "$HOME/.claude/plugins/npm-cache/node_modules/codevibe-claude-plugin"
158
+ rm -f "$HOME/.claude/plugins/npm-cache/package-lock.json"
159
+ }
106
160
 
107
161
  do_update() {
108
162
  echo ""
109
163
  echo -e "${BOLD}${PURPLE}CodeVibe Update${NC}"
110
164
  echo ""
111
165
 
112
- # Show current versions
166
+ # Show current meta-package version
113
167
  if [ -f "$PACKAGE_DIR/package.json" ]; then
114
168
  CUR_VER=$(node -p "require('$PACKAGE_DIR/package.json').version" 2>/dev/null || echo "?")
115
- echo -e " ${DIM}Current version: $CUR_VER${NC}"
169
+ echo -e " ${DIM}Current meta-package: $CUR_VER${NC}"
116
170
  fi
117
171
  echo ""
118
172
 
119
- # Update meta-package (pulls latest core + all plugins)
173
+ # ─── Step 1: Update the global meta-package (pulls latest core + plugins) ──
120
174
  echo -e "${PURPLE}▸${NC} Updating @quantiya/codevibe..."
121
- npm install -g --force @quantiya/codevibe@latest 2>&1 | tail -1
122
- echo -e "${GREEN}✓${NC} CodeVibe updated"
175
+ # Capture output so we can check npm's exit status directly instead of the
176
+ # pipe's (tail's exit status would mask npm failures without `set -o pipefail`).
177
+ local npm_output
178
+ if ! npm_output=$(npm install -g --force @quantiya/codevibe@latest 2>&1); then
179
+ echo "$npm_output" | tail -10
180
+ echo ""
181
+ echo -e "${YELLOW}!${NC} Meta-package update failed. Check the output above, fix the issue, and retry 'codevibe update'."
182
+ return 1
183
+ fi
184
+ echo "$npm_output" | tail -3
185
+ echo -e "${GREEN}✓${NC} Meta-package updated"
123
186
 
124
- # Update Claude plugin in Claude Code
125
- if command -v claude >/dev/null 2>&1; then
187
+ # ─── Step 2: Update the Claude Code plugin ─────────────────────────────────
188
+ if ! command -v claude >/dev/null 2>&1; then
189
+ echo ""
190
+ echo -e "${YELLOW}!${NC} claude CLI not found — skipping Claude Code plugin update"
126
191
  echo ""
127
- echo -e "${PURPLE}▸${NC} Updating Claude Code plugin..."
192
+ echo -e "${BOLD}Updated versions:${NC}"
193
+ show_version
194
+ return 0
195
+ fi
128
196
 
129
- # Refresh marketplace
130
- if claude plugin marketplace update codevibe-marketplace 2>/dev/null; then
131
- echo -e "${GREEN}✓${NC} Marketplace refreshed"
132
- else
133
- echo -e "${YELLOW}!${NC} Marketplace refresh skipped"
197
+ echo ""
198
+ echo -e "${PURPLE}▸${NC} Updating Claude Code plugin..."
199
+
200
+ # Refresh the marketplace manifest so we see the latest pinned version.
201
+ # Errors here are non-fatal at this step — the previously-cached manifest may
202
+ # still be usable — but the EXPECTED_VERSION read below is the real gate.
203
+ if claude plugin marketplace update codevibe-marketplace; then
204
+ echo -e "${GREEN}✓${NC} Marketplace refreshed"
205
+ else
206
+ echo -e "${YELLOW}!${NC} Marketplace refresh failed (falling back to cached manifest)"
207
+ fi
208
+
209
+ local EXPECTED_VERSION
210
+ local INSTALLED_VERSION
211
+ EXPECTED_VERSION=$(_read_marketplace_version)
212
+ INSTALLED_VERSION=$(_read_installed_version)
213
+
214
+ # EXPECTED_VERSION is required — without it we have no ground truth to verify
215
+ # against, so the whole cache-bug workaround is blind. Fail loudly rather than
216
+ # claim success we can't prove.
217
+ if [ -z "$EXPECTED_VERSION" ]; then
218
+ echo ""
219
+ echo -e "${YELLOW}!${NC} Could not read expected version from marketplace manifest."
220
+ echo -e " ${DIM}Expected at: \$HOME/.claude/plugins/marketplaces/codevibe-marketplace/.claude-plugin/marketplace.json${NC}"
221
+ echo -e " ${DIM}This usually means the marketplace refresh failed or the manifest schema has drifted.${NC}"
222
+ echo -e " ${DIM}Try: claude plugin marketplace update codevibe-marketplace${NC}"
223
+ return 1
224
+ fi
225
+
226
+ echo -e " ${DIM}installed: ${INSTALLED_VERSION:-<none>} marketplace: ${EXPECTED_VERSION}${NC}"
227
+
228
+ # ─── Step 3: Decide if we need to force a cache-clearing reinstall ─────────
229
+ local NEEDS_REINSTALL=false
230
+ if [ -z "$INSTALLED_VERSION" ] || [ "$INSTALLED_VERSION" != "$EXPECTED_VERSION" ]; then
231
+ NEEDS_REINSTALL=true
232
+ if [ -n "$INSTALLED_VERSION" ]; then
233
+ echo -e "${YELLOW}!${NC} Cache is stale (${INSTALLED_VERSION} on disk, ${EXPECTED_VERSION} in marketplace)."
234
+ echo -e " ${DIM}Working around Claude Code plugin update bug...${NC}"
134
235
  fi
236
+ fi
237
+
238
+ if [ "$NEEDS_REINSTALL" = "true" ]; then
239
+ # Must uninstall + nuke cache BEFORE install. `claude plugin install` will
240
+ # silently reuse an existing cache dir even if the marketplace version changed.
241
+ claude plugin uninstall codevibe-claude@codevibe-marketplace >/dev/null 2>&1 || true
242
+ _nuke_claude_plugin_cache
135
243
 
136
- # Reinstall plugin (gets latest version from marketplace)
137
- if claude plugin install codevibe-claude@codevibe-marketplace 2>/dev/null; then
138
- echo -e "${GREEN}✓${NC} Claude plugin updated"
244
+ if claude plugin install codevibe-claude@codevibe-marketplace; then
245
+ echo -e "${GREEN}✓${NC} Claude plugin reinstalled"
139
246
  else
140
- echo -e "${YELLOW}!${NC} Claude plugin update skipped"
247
+ echo ""
248
+ echo -e "${YELLOW}!${NC} Claude plugin install failed — try running 'codevibe update' again"
249
+ return 1
141
250
  fi
251
+ else
252
+ # Version already matches. Still call install to make sure installed_plugins.json
253
+ # is in sync, but treat any error as non-fatal since we're not actually changing state.
254
+ claude plugin install codevibe-claude@codevibe-marketplace >/dev/null 2>&1 || true
255
+ echo -e "${GREEN}✓${NC} Claude plugin already at ${INSTALLED_VERSION}"
256
+ fi
257
+
258
+ # ─── Step 4: Verify the installed version is now what we expected ──────────
259
+ # EXPECTED_VERSION is guaranteed non-empty here (we bailed earlier otherwise),
260
+ # so the verification is unconditional.
261
+ INSTALLED_VERSION=$(_read_installed_version)
262
+ if [ "$INSTALLED_VERSION" != "$EXPECTED_VERSION" ]; then
263
+ echo ""
264
+ echo -e "${YELLOW}!${NC} WARNING: Installed version (${INSTALLED_VERSION:-<none>}) still doesn't match expected (${EXPECTED_VERSION})."
265
+ echo -e " ${DIM}Try: rm -rf ~/.claude/plugins/cache/codevibe-marketplace/codevibe-claude && codevibe update${NC}"
266
+ return 1
267
+ fi
268
+
269
+ # ─── Step 5: Tell the user about running sessions ──────────────────────────
270
+ if [ "$NEEDS_REINSTALL" = "true" ]; then
271
+ echo ""
272
+ echo -e "${YELLOW}!${NC} Running Claude Code sessions still have the OLD plugin server in memory."
273
+ echo -e " ${DIM}Exit and restart any active session to pick up the new plugin.${NC}"
142
274
  fi
143
275
 
144
276
  echo ""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "CodeVibe - Monitor and control AI coding agents (Claude Code, Gemini CLI, Codex CLI) from your mobile device",
5
5
  "bin": {
6
6
  "codevibe": "./bin/codevibe",
@@ -15,7 +15,7 @@
15
15
  ],
16
16
  "dependencies": {
17
17
  "@quantiya/codevibe-core": "^1.0.3",
18
- "@quantiya/codevibe-claude-plugin": "^1.0.9",
18
+ "@quantiya/codevibe-claude-plugin": "^1.0.10",
19
19
  "@quantiya/codevibe-gemini-plugin": "^1.0.5",
20
20
  "@quantiya/codevibe-codex-plugin": "^1.0.6"
21
21
  },