gipity 1.0.390 → 1.0.391
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/dist/commands/claude.js +5 -1
- package/dist/commands/status.js +13 -4
- package/dist/setup.js +89 -4
- package/package.json +1 -1
package/dist/commands/claude.js
CHANGED
|
@@ -21,7 +21,7 @@ import { getAuth, saveAuth, clearAuth } from '../auth.js';
|
|
|
21
21
|
import { get, post, publicPost, ApiError, getAccountSlug } from '../api.js';
|
|
22
22
|
import { getConfig, saveConfigAt, clearConfigCache, getApiBaseOverride, DEFAULT_API_BASE, getConfigPath } from '../config.js';
|
|
23
23
|
import { sync } from '../sync.js';
|
|
24
|
-
import { slugify, setupClaudeHooks, setupClaudeMd, setupAgentsMd, setupGitignore, DEFAULT_SYNC_IGNORE, isSyncIgnored } from '../setup.js';
|
|
24
|
+
import { slugify, setupClaudeHooks, ensureGipityPluginInstalled, setupClaudeMd, setupAgentsMd, setupGitignore, DEFAULT_SYNC_IGNORE, isSyncIgnored } from '../setup.js';
|
|
25
25
|
import { buildProjectContextBlock as buildProjectContextBlockText, buildNewProjectPrompt, buildResumeWrap, buildFreshWrap, } from '../prompts.js';
|
|
26
26
|
import * as relayState from '../relay/state.js';
|
|
27
27
|
import { maybeOfferRelayOn, ensureDaemonRunning } from '../relay/onboarding.js';
|
|
@@ -601,6 +601,10 @@ export const claudeCommand = new Command('claude')
|
|
|
601
601
|
console.log(` Then: cd ${process.cwd()} && claude`);
|
|
602
602
|
return;
|
|
603
603
|
}
|
|
604
|
+
// Ensure the Gipity plugin is actually installed at user scope (not just
|
|
605
|
+
// enabled declaratively) so its capture + file-sync hooks load in this
|
|
606
|
+
// run's cwd. No-ops once the current version is installed; best-effort.
|
|
607
|
+
ensureGipityPluginInstalled();
|
|
604
608
|
// Resolve (or create) the backing Gipity conversation for this
|
|
605
609
|
// Claude Code run. The conv_guid is handed to the child (and thus
|
|
606
610
|
// every capture hook spawned by Claude Code) via env var so every
|
package/dist/commands/status.js
CHANGED
|
@@ -5,10 +5,14 @@ import { homedir } from 'os';
|
|
|
5
5
|
import { getAuth, sessionExpired } from '../auth.js';
|
|
6
6
|
import { getConfig, liveUrl } from '../config.js';
|
|
7
7
|
import { brand, success, warning, muted, error as clrError } from '../colors.js';
|
|
8
|
-
import { GIPITY_PLUGIN_ID, GIPITY_MARKETPLACE_NAME, setupClaudeHooks, ensureGipityPlugin } from '../setup.js';
|
|
9
|
-
/** Hooks ship in the Gipity Claude Code plugin now
|
|
10
|
-
* user-scope settings register the marketplace and
|
|
11
|
-
*
|
|
8
|
+
import { GIPITY_PLUGIN_ID, GIPITY_MARKETPLACE_NAME, setupClaudeHooks, ensureGipityPlugin, ensureGipityPluginInstalled, userScopePluginCurrent } from '../setup.js';
|
|
9
|
+
/** Hooks ship in the Gipity Claude Code plugin now. "Installed" means three
|
|
10
|
+
* things must all hold: the user-scope settings register the marketplace and
|
|
11
|
+
* enable the plugin (declarative), AND Claude Code actually has a user-scope
|
|
12
|
+
* install of the current version on disk. The last check matters because
|
|
13
|
+
* CC >=2.1.x does not materialize a user-scope install from enablement alone -
|
|
14
|
+
* without it the hooks never load and capture/file-sync silently die, so
|
|
15
|
+
* reporting "ok" on the declarative keys alone would be a false green. */
|
|
12
16
|
function checkGipityPlugin() {
|
|
13
17
|
const path = join(homedir(), '.claude', 'settings.json');
|
|
14
18
|
let settings = {};
|
|
@@ -23,6 +27,8 @@ function checkGipityPlugin() {
|
|
|
23
27
|
missing.push('marketplace');
|
|
24
28
|
if (settings?.enabledPlugins?.[GIPITY_PLUGIN_ID] !== true)
|
|
25
29
|
missing.push('plugin');
|
|
30
|
+
if (!userScopePluginCurrent())
|
|
31
|
+
missing.push('install');
|
|
26
32
|
return { missing, ok: missing.length === 0 };
|
|
27
33
|
}
|
|
28
34
|
export const statusCommand = new Command('status')
|
|
@@ -82,6 +88,9 @@ export const statusCommand = new Command('status')
|
|
|
82
88
|
// force: an explicit repair request overrides a previous disable.
|
|
83
89
|
ensureGipityPlugin(true);
|
|
84
90
|
setupClaudeHooks();
|
|
91
|
+
// Re-enabling the declarative keys isn't enough on CC >=2.1.x - also
|
|
92
|
+
// materialize the user-scope install so the hooks actually load.
|
|
93
|
+
ensureGipityPluginInstalled();
|
|
85
94
|
console.log(`${muted('Hooks:')} ${success('repaired - Gipity plugin re-enabled')}`);
|
|
86
95
|
}
|
|
87
96
|
else {
|
package/dist/setup.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { resolve, join, dirname } from 'path';
|
|
5
5
|
import { homedir } from 'os';
|
|
6
6
|
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
7
|
+
import { spawnSync } from 'child_process';
|
|
7
8
|
import { SKILLS_CONTENT, BUILD_VS_NON_BUILD_RULE, DEFINITION_OF_DONE } from './knowledge.js';
|
|
8
9
|
export { SKILLS_CONTENT };
|
|
9
10
|
/** Canonical list of workstation artifacts that are NOT part of the project.
|
|
@@ -100,13 +101,27 @@ export const PERMISSIONS_SETTINGS = {
|
|
|
100
101
|
// into each project's .claude/settings.json with absolute paths baked in -
|
|
101
102
|
// that left orphaned entries behind on uninstall (the CLI keeps no inventory
|
|
102
103
|
// of projects it touched) and could even land in the user-global settings
|
|
103
|
-
// when a gipity command ran from $HOME. The plugin replaces all of it
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
104
|
+
// when a gipity command ran from $HOME. The plugin replaces all of it: Claude
|
|
105
|
+
// Code resolves script paths via ${CLAUDE_PLUGIN_ROOT} and uninstall/disable
|
|
106
|
+
// removes every hook at once.
|
|
107
|
+
//
|
|
108
|
+
// Two steps are needed to make it load, split by testability and cost:
|
|
109
|
+
// - ensureGipityPlugin() - declarative: register the marketplace +
|
|
110
|
+
// enable the plugin in ~/.claude/settings.json. Pure file writes.
|
|
111
|
+
// - ensureGipityPluginInstalled() - imperative: actually install the plugin
|
|
112
|
+
// at USER scope via the `claude plugin` CLI. Required because CC >=2.1.x no
|
|
113
|
+
// longer materializes a user-scope install from enablement alone; without
|
|
114
|
+
// it the hooks load only inside whatever project happened to install the
|
|
115
|
+
// plugin (often nowhere), silently taking capture + file-sync down.
|
|
107
116
|
export const GIPITY_PLUGIN_ID = 'gipity@gipity';
|
|
108
117
|
export const GIPITY_MARKETPLACE_NAME = 'gipity';
|
|
109
118
|
export const GIPITY_MARKETPLACE_REPO = 'GipityAI/claude-plugin';
|
|
119
|
+
// The plugin version this CLI requires. Bump in lockstep with
|
|
120
|
+
// claude-plugin/.claude-plugin/plugin.json: Claude Code does NOT auto-upgrade
|
|
121
|
+
// an installed plugin when the marketplace advances - only an explicit
|
|
122
|
+
// `plugin install`/`update` does - so this constant is how a CLI upgrade tells
|
|
123
|
+
// ensureGipityPluginInstalled() to refresh a stale user-scope install.
|
|
124
|
+
export const GIPITY_PLUGIN_VERSION = '0.4.0';
|
|
110
125
|
/** True for hook commands the CLI itself wrote into settings.json in past
|
|
111
126
|
* versions. Matched by signature so migration strips exactly our own
|
|
112
127
|
* entries and never touches user-authored hooks. */
|
|
@@ -192,6 +207,76 @@ export function ensureGipityPlugin(force = false) {
|
|
|
192
207
|
mkdirSync(claudeDir, { recursive: true });
|
|
193
208
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
194
209
|
}
|
|
210
|
+
/** Dotted-numeric version compare: true when `have` >= `want` (e.g. "0.4.0"). */
|
|
211
|
+
function versionGte(have, want) {
|
|
212
|
+
const h = have.split('.').map((n) => parseInt(n, 10) || 0);
|
|
213
|
+
const w = want.split('.').map((n) => parseInt(n, 10) || 0);
|
|
214
|
+
for (let i = 0; i < Math.max(h.length, w.length); i++) {
|
|
215
|
+
const a = h[i] ?? 0;
|
|
216
|
+
const b = w[i] ?? 0;
|
|
217
|
+
if (a !== b)
|
|
218
|
+
return a > b;
|
|
219
|
+
}
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
/** True when Claude Code already records a USER-scope install of the Gipity
|
|
223
|
+
* plugin at >= the version this CLI needs - the common case, letting the
|
|
224
|
+
* caller skip the (slow) reinstall. Reads installed_plugins.json directly so
|
|
225
|
+
* the check costs no subprocess. Exported so `gipity status` can tell an
|
|
226
|
+
* actually-loaded plugin apart from one that's merely enabled-but-uninstalled
|
|
227
|
+
* (which would otherwise read as a false-green "hooks enabled"). */
|
|
228
|
+
export function userScopePluginCurrent() {
|
|
229
|
+
try {
|
|
230
|
+
const p = join(homedir(), '.claude', 'plugins', 'installed_plugins.json');
|
|
231
|
+
const data = JSON.parse(readFileSync(p, 'utf-8'));
|
|
232
|
+
const entries = data?.plugins?.[GIPITY_PLUGIN_ID];
|
|
233
|
+
if (!Array.isArray(entries))
|
|
234
|
+
return false;
|
|
235
|
+
return entries.some((e) => e?.scope === 'user' &&
|
|
236
|
+
typeof e?.version === 'string' &&
|
|
237
|
+
versionGte(e.version, GIPITY_PLUGIN_VERSION));
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function claudeOnPath() {
|
|
244
|
+
const probe = spawnSync(process.platform === 'win32' ? 'where' : 'which', ['claude'], {
|
|
245
|
+
encoding: 'utf-8',
|
|
246
|
+
});
|
|
247
|
+
return probe.status === 0 && !!probe.stdout?.trim();
|
|
248
|
+
}
|
|
249
|
+
/** Materialize the Gipity plugin at USER scope via Claude Code's own plugin
|
|
250
|
+
* CLI, so its hooks (session capture + file sync) load in EVERY directory.
|
|
251
|
+
*
|
|
252
|
+
* ensureGipityPlugin() only writes the declarative `enabledPlugins` /
|
|
253
|
+
* `extraKnownMarketplaces` keys. That was enough on older Claude Code, but
|
|
254
|
+
* CC >=2.1.x no longer materializes a user-scope install from an enablement
|
|
255
|
+
* entry alone: without an actual user-scope install the plugin loads only in
|
|
256
|
+
* whatever project happened to install it (often nowhere), so capture and
|
|
257
|
+
* file-sync silently go dark everywhere else. We drive the supported
|
|
258
|
+
* `claude plugin` commands rather than trust implicit resolution.
|
|
259
|
+
*
|
|
260
|
+
* Best-effort and non-fatal - a missing `claude` or a failed install must
|
|
261
|
+
* never break `gipity claude`. Skips entirely when the user-scope install is
|
|
262
|
+
* already current, so it shells out at most once per plugin-version bump. */
|
|
263
|
+
export function ensureGipityPluginInstalled() {
|
|
264
|
+
if (userScopePluginCurrent())
|
|
265
|
+
return;
|
|
266
|
+
if (!claudeOnPath())
|
|
267
|
+
return;
|
|
268
|
+
// Refresh the marketplace clone so `install` resolves the current version,
|
|
269
|
+
// then (re)install at user scope - idempotent, and upgrades an older or
|
|
270
|
+
// project-scoped install to the current one at user scope.
|
|
271
|
+
spawnSync('claude', ['plugin', 'marketplace', 'update', GIPITY_MARKETPLACE_NAME], {
|
|
272
|
+
stdio: 'ignore',
|
|
273
|
+
timeout: 120_000,
|
|
274
|
+
});
|
|
275
|
+
spawnSync('claude', ['plugin', 'install', GIPITY_PLUGIN_ID, '--scope', 'user'], {
|
|
276
|
+
stdio: 'ignore',
|
|
277
|
+
timeout: 120_000,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
195
280
|
export function setupClaudeHooks() {
|
|
196
281
|
// All hooks ship in the plugin - enable it at user scope (and clean up any
|
|
197
282
|
// legacy hook blocks in the user-global settings while we're there).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gipity",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.391",
|
|
4
4
|
"description": "The full-stack platform tuned for AI agents. Database, storage, auth, functions, deploy, and drop-in kits - all agent-tuned. Pair with Claude Code or use standalone.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"gipity": "dist/updater/shim.js",
|