@passioncode-ai/passioncode 0.2.46 → 0.2.48
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/CHANGELOG.md +22 -0
- package/README.md +1 -1
- package/SECURITY.md +2 -1
- package/lib/doctor.js +26 -4
- package/lib/launcher.js +34 -5
- package/lib/releases.js +3 -2
- package/lib/setup.js +2 -1
- package/lib/windows-apps.js +74 -0
- package/package.json +1 -1
- package/payload/.claude-plugin/marketplace.json +1 -1
- package/payload/manifest.json +4 -4
- package/payload/plugins/passioncode/.claude-plugin/plugin.json +1 -1
- package/payload/plugins/passioncode/skills/setting-up-passioncode/SKILL.md +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.48 - 2026-10-28
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- `doctor` on Windows no longer tells you to run `setup --with <app>` for an MCP entry whose app is
|
|
8
|
+
not installed: `setup` installs apps only on macOS, so the fix names the app's download page (or
|
|
9
|
+
removing the entry). The `setting-up-passioncode` skill says the same (PC-88).
|
|
10
|
+
|
|
11
|
+
## 0.2.47 - 2026-10-28
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **`update` on Windows moves `current` to the new release** (PC-85, the Windows acceptance of 2026-10-28): Windows
|
|
16
|
+
refuses a rename over a directory link (`EPERM ... rename 'current.<pid>.lnk' -> 'current'`), so an update stopped
|
|
17
|
+
halfway, kept the old release and left a `current.<pid>.lnk` per attempt. There the old link is now removed first
|
|
18
|
+
(the link itself, never what it points at) and put back if the rename fails again; the temporary link never outlives
|
|
19
|
+
the call, and the ones a failed update left are removed by the next one.
|
|
20
|
+
- **`doctor` checks the apps on Windows** (PC-86): it reads each app's uninstall entry (`reg query`, the name and
|
|
21
|
+
version its installer wrote) or finds it in `%LOCALAPPDATA%\Programs\<name>`, `%LOCALAPPDATA%\<name>` or Program
|
|
22
|
+
Files, and says which version is installed and whether a newer one is out, instead of "app checks run on macOS".
|
|
23
|
+
Setup still installs apps on macOS only.
|
|
24
|
+
|
|
3
25
|
## 0.2.46 - 2026-10-28
|
|
4
26
|
|
|
5
27
|
### Changed
|
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ secret into a product's own hidden prompt, starting Docker for Fabric, and resta
|
|
|
47
47
|
one question per app; `--yes` accepts the plan, `--with`/`--without <ids>` choose apps
|
|
48
48
|
(`switchboard`, `dashboards`, `observatory`, `inbox`, `fabric`), `--no-apps` sets up the skills
|
|
49
49
|
and MCP only, `--dry-run` shows the plan. Apps are installed on macOS; on other systems setup
|
|
50
|
-
names each download page. Skills only: `npx @passioncode-ai/passioncode@latest update`.
|
|
50
|
+
names each download page, and on Windows `doctor` reads which version of each app is installed. Skills only: `npx @passioncode-ai/passioncode@latest update`.
|
|
51
51
|
2. **Configure:** nothing to set, no account and no key. Background updates are on by default;
|
|
52
52
|
`npx @passioncode-ai/passioncode@latest config set update.auto off` turns them off. Each app's
|
|
53
53
|
own onboarding (sign-ins, Fabric Inbox's server, Observatory's projects) is listed by `setup`.
|
package/SECURITY.md
CHANGED
|
@@ -32,7 +32,8 @@ returns a nonzero exit code. See the [CLI recovery contract](docs/reference/cli.
|
|
|
32
32
|
`doctor` reads: `~/.claude.json`, `~/.codex/config.toml`, `~/.gemini/settings.json`,
|
|
33
33
|
`~/.kimi-code/mcp.json` (entry names, commands and arguments; environment values are passed to
|
|
34
34
|
the server it starts and never printed), the Fabric service descriptors (never their token
|
|
35
|
-
files), the apps' `Info.plist
|
|
35
|
+
files), the apps' `Info.plist` (on Windows, the apps' uninstall entries through `reg query` and their install folders),
|
|
36
|
+
and the GitHub releases API. It starts each registered stdio MCP
|
|
36
37
|
server for one proving call and stops it (never Fabric's, which enrols a session as it starts), and writes only `~/.passioncode/doctor.json` and a
|
|
37
38
|
release cache.
|
|
38
39
|
|
package/lib/doctor.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* `passioncode doctor`: reads the whole PassionCode.ai setup of this machine and names, for every
|
|
4
4
|
* check, its state, the exact fix and what setup may repair (ADR-0004). It changes nothing: the only
|
|
5
5
|
* processes it starts are the registered stdio MCP servers for one proving call each (never Fabric's,
|
|
6
|
-
* which enrols a session when it starts), stopped when the call returns
|
|
6
|
+
* which enrols a session when it starts), stopped when the call returns, and on Windows three
|
|
7
|
+
* read-only `reg query` calls for the apps' uninstall entries (PC-86). `doctor --fix` is setup's
|
|
7
8
|
* repair half (lib/setup.js), not this module.
|
|
8
9
|
*/
|
|
9
10
|
const fs = require('fs');
|
|
@@ -12,6 +13,7 @@ const path = require('path');
|
|
|
12
13
|
const L = require('./launcher');
|
|
13
14
|
const catalog = require('./catalog');
|
|
14
15
|
const releases = require('./releases');
|
|
16
|
+
const W = require('./windows-apps');
|
|
15
17
|
const { probe } = require('./mcp-probe');
|
|
16
18
|
|
|
17
19
|
const PKG = (() => { try { return require('../package.json').version; } catch (_) { return '0.0.0'; } })();
|
|
@@ -123,12 +125,32 @@ async function collect({ home, platform, claude, online }) {
|
|
|
123
125
|
const cacheFile = path.join(p.state, 'releases-cache.json');
|
|
124
126
|
const probes = new Map();
|
|
125
127
|
let docker = null;
|
|
128
|
+
let windowsEntries = null; // the uninstall entries, read once (three `reg query` calls)
|
|
126
129
|
for (const pr of catalog.PRODUCTS) {
|
|
127
130
|
const at = catalog.appPath(pr);
|
|
128
131
|
const installed = platform === 'darwin' && fs.existsSync(at);
|
|
129
132
|
const label = `${pr.name}${pr.preview ? ' (early preview)' : ''}`;
|
|
130
|
-
if (platform
|
|
131
|
-
|
|
133
|
+
if (platform === 'win32') {
|
|
134
|
+
// PC-86: presence and version from the installer's own records; setup installs nothing here.
|
|
135
|
+
if (!windowsEntries) {
|
|
136
|
+
windowsEntries = W.readUninstallEntries(releases.run);
|
|
137
|
+
for (const u of windowsEntries.unread) add({ id: `apps.registry.${u.hive.split('\\')[0].toLowerCase()}${u.hive.includes('WOW6432Node') ? '-wow64' : ''}`, area: 'apps', state: 'warn', detail: `could not read ${u.hive} (${u.why}); an app installed for every user may show as not installed` });
|
|
138
|
+
}
|
|
139
|
+
const found = W.findWindowsApp(pr, { entries: windowsEntries.entries, home });
|
|
140
|
+
if (!found) {
|
|
141
|
+
add({ id: `app.${pr.id}`, area: 'apps', product: pr.id, state: 'info', detail: `${label}: not installed`, fix: `download it from ${pr.page}` });
|
|
142
|
+
} else {
|
|
143
|
+
let latest = null, latestErr = null;
|
|
144
|
+
if (online) { try { latest = await releases.latestRelease(pr, { cacheFile }); } catch (error) { latestErr = error.message; } }
|
|
145
|
+
const outdated = latest && found.version && newer(latest.version, found.version);
|
|
146
|
+
add({
|
|
147
|
+
id: `app.${pr.id}`, area: 'apps', product: pr.id, state: outdated || (!latest && online) ? 'warn' : 'ok',
|
|
148
|
+
detail: `${label} ${found.version || '(version unknown)'}${found.at ? ` in ${found.at}` : ''}${latest ? (outdated ? `; ${latest.version} is out` : found.version ? ' (latest)' : `; the latest is ${latest.version}`) : online ? `; latest unknown (${latestErr})` : '; latest not checked (--offline)'}`,
|
|
149
|
+
fix: outdated ? `install ${latest.version} from ${pr.page} (or accept the update ${pr.name} offers)` : null,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
} else if (platform !== 'darwin') {
|
|
153
|
+
add({ id: `app.${pr.id}`, area: 'apps', product: pr.id, state: 'info', detail: `${label}: app checks run on macOS and Windows; on this system download it from ${pr.page}` });
|
|
132
154
|
} else if (!installed) {
|
|
133
155
|
add({ id: `app.${pr.id}`, area: 'apps', product: pr.id, state: 'info', detail: `${label}: not installed`, fix: `${NPX} setup --with ${pr.id}` });
|
|
134
156
|
} else {
|
|
@@ -179,7 +201,7 @@ async function collect({ home, platform, claude, online }) {
|
|
|
179
201
|
continue;
|
|
180
202
|
}
|
|
181
203
|
if (path.isAbsolute(entry.command) && !fs.existsSync(entry.command)) {
|
|
182
|
-
add({ id, area: 'mcp', product: pr.id, state: 'fail', detail: `${agent.name}: ${m.name} points at ${entry.command}, which does not exist`, fix: installed ? `remove that entry from ${agent.name}, then ${NPX} doctor --fix` : `${NPX} setup --with ${pr.id}` });
|
|
204
|
+
add({ id, area: 'mcp', product: pr.id, state: 'fail', detail: `${agent.name}: ${m.name} points at ${entry.command}, which does not exist`, fix: installed ? `remove that entry from ${agent.name}, then ${NPX} doctor --fix` : platform === 'darwin' ? `${NPX} setup --with ${pr.id}` : `download ${pr.name} from ${pr.page}, or remove that entry from ${agent.name}` }); // PC-88: setup installs apps only on macOS
|
|
183
205
|
continue;
|
|
184
206
|
}
|
|
185
207
|
if (pr.mcp.spawn === false) {
|
package/lib/launcher.js
CHANGED
|
@@ -65,13 +65,42 @@ function readState(file, { tolerant = false } = {}) {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
/**
|
|
69
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Replace a symlink atomically (create beside it, rename over it). Windows refuses any rename over
|
|
70
|
+
* a directory link (EPERM, PC-85), so there the old link is removed first: unlink takes the link
|
|
71
|
+
* itself, never what it points at, and the old link is put back if the rename fails again. The
|
|
72
|
+
* temporary link never outlives the call, and the ones an earlier failed update left are removed.
|
|
73
|
+
* On Windows the swap is therefore not atomic: between the unlink and the rename `at` is absent,
|
|
74
|
+
* and a run killed there leaves no `current` until the next update (status reports it missing).
|
|
75
|
+
*/
|
|
76
|
+
function symlinkAtomic(target, at, { platform = process.platform, rename = fs.renameSync, unlink = fs.unlinkSync } = {}) {
|
|
70
77
|
fs.mkdirSync(path.dirname(at), { recursive: true });
|
|
71
78
|
const tmp = `${at}.${process.pid}.lnk`;
|
|
72
|
-
try { fs.unlinkSync(tmp); } catch (_) { /* none */ }
|
|
79
|
+
const dropTmp = () => { try { fs.unlinkSync(tmp); } catch (_) { /* none */ } };
|
|
80
|
+
dropTmp();
|
|
73
81
|
fs.symlinkSync(target, tmp);
|
|
74
|
-
|
|
82
|
+
try {
|
|
83
|
+
rename(tmp, at);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
const old = lstat(at);
|
|
86
|
+
if (platform !== 'win32' || !['EPERM', 'EACCES', 'EEXIST'].includes(error.code) || !old || !old.isSymbolicLink()) { dropTmp(); throw error; }
|
|
87
|
+
const previous = linkTarget(at);
|
|
88
|
+
try { unlink(at); } catch (unlinkError) { dropTmp(); throw unlinkError; }
|
|
89
|
+
try { rename(tmp, at); } catch (again) {
|
|
90
|
+
dropTmp();
|
|
91
|
+
try { fs.symlinkSync(previous, at); } catch (back) { throw new Error(`${again.message}; and putting back ${at} → ${previous} failed (${back.message})`); }
|
|
92
|
+
throw again;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (platform !== 'win32') return; // only a refused rename on Windows ever left one (PC-85)
|
|
96
|
+
const base = path.basename(at);
|
|
97
|
+
let siblings = [];
|
|
98
|
+
try { siblings = fs.readdirSync(path.dirname(at)); } catch (_) { /* nothing to sweep */ }
|
|
99
|
+
for (const name of siblings) {
|
|
100
|
+
if (!name.startsWith(`${base}.`) || !/^\.\d+\.lnk$/.test(name.slice(base.length))) continue;
|
|
101
|
+
const left = path.join(path.dirname(at), name);
|
|
102
|
+
if (lstat(left)?.isSymbolicLink()) { try { fs.unlinkSync(left); } catch (_) { /* the next update sweeps it */ } }
|
|
103
|
+
}
|
|
75
104
|
}
|
|
76
105
|
|
|
77
106
|
// --- one update at a time (lifecycle contract LC-03) ---------------------------------------
|
|
@@ -854,5 +883,5 @@ module.exports = {
|
|
|
854
883
|
restore: (opts = {}) => withUpdateLock(opts.home, () => restore(opts)),
|
|
855
884
|
uninstall: (opts = {}) => withUpdateLock(opts.home, () => uninstall(opts)),
|
|
856
885
|
status, setConfig, paths, CHANNELS, MARKETPLACE, payloadManifest, marketplaceAddArg,
|
|
857
|
-
acquireUpdateLock, UpdateRunning, staleReleases, claudeRunner, bundledMcpServers, mcpFileTargets, readSettings, tomlTableRange, tomlTableCommand, tomlTableArgs, tomlMentions,
|
|
886
|
+
acquireUpdateLock, UpdateRunning, staleReleases, symlinkAtomic, claudeRunner, bundledMcpServers, mcpFileTargets, readSettings, tomlTableRange, tomlTableCommand, tomlTableArgs, tomlMentions,
|
|
858
887
|
};
|
package/lib/releases.js
CHANGED
|
@@ -16,9 +16,10 @@ const catalog = require('./catalog');
|
|
|
16
16
|
const API = () => (process.env.PASSIONCODE_GITHUB_API || 'https://api.github.com').replace(/\/$/, '');
|
|
17
17
|
const CACHE_TTL_MS = 30 * 60 * 1000;
|
|
18
18
|
|
|
19
|
-
function run(cmd, args, { timeout = 60000, input } = {}) {
|
|
20
|
-
const r = spawnSync(cmd, args, { encoding: 'utf8', timeout, input });
|
|
19
|
+
function run(cmd, args, { timeout = 60000, input, maxBuffer = 1024 * 1024 } = {}) {
|
|
20
|
+
const r = spawnSync(cmd, args, { encoding: 'utf8', timeout, input, maxBuffer });
|
|
21
21
|
if (r.error && r.error.code === 'ENOENT') return { code: 127, out: '', err: `${cmd} not found` };
|
|
22
|
+
if (r.error && r.error.code === 'ENOBUFS') return { code: 1, out: '', err: `${cmd} wrote more than ${maxBuffer} bytes` };
|
|
22
23
|
if (r.error && r.error.code === 'ETIMEDOUT') return { code: 124, out: r.stdout || '', err: `${cmd} timed out after ${Math.round(timeout / 1000)} s` };
|
|
23
24
|
return { code: r.status === null ? 1 : r.status, out: r.stdout || '', err: r.stderr || '' };
|
|
24
25
|
}
|
package/lib/setup.js
CHANGED
|
@@ -76,7 +76,8 @@ async function setup({
|
|
|
76
76
|
const claude = L.claudeRunner();
|
|
77
77
|
const before = D.sortChecks(await D.collect({ home, platform, claude, online }));
|
|
78
78
|
const fresh = !before.some((c) => c.id === 'skills.installed' && c.state !== 'fail')
|
|
79
|
-
|
|
79
|
+
// An app doctor found (ok or warn: on Windows from the installer's records, PC-86) makes it existing.
|
|
80
|
+
&& !before.some((c) => /^app\.[^.]+$/.test(c.id) && (c.state === 'ok' || c.state === 'warn'));
|
|
80
81
|
const items = plan(before, { platform, withIds, withoutIds, noApps, repairOnly });
|
|
81
82
|
const result = {
|
|
82
83
|
version: D.PKG, platform, mode: fresh ? 'new' : 'existing', at: new Date().toISOString(), plan: items,
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Where a PassionCode.ai app is installed on Windows and which version it is, read without
|
|
4
|
+
* starting it (PC-86): the uninstall entry its installer wrote (electron-builder and Tauri both
|
|
5
|
+
* write DisplayName and DisplayVersion; Tauri also InstallLocation), else the folder a per-user
|
|
6
|
+
* installer uses (%LOCALAPPDATA%\Programs\<name> for electron-builder, %LOCALAPPDATA%\<name> for
|
|
7
|
+
* Tauri) or a per-machine one under Program Files, with the program in it.
|
|
8
|
+
*/
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
const HIVES = [
|
|
13
|
+
'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall',
|
|
14
|
+
'HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall',
|
|
15
|
+
'HKLM\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall',
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
/** `reg query <hive> /s` output → [{ key, DisplayName, DisplayVersion, InstallLocation, UninstallString }]. */
|
|
19
|
+
function parseUninstall(text) {
|
|
20
|
+
const entries = [];
|
|
21
|
+
let entry = null;
|
|
22
|
+
for (const line of String(text || '').split(/\r?\n/)) {
|
|
23
|
+
if (/^HKEY_/.test(line)) { entry = { key: line.trim() }; entries.push(entry); continue; }
|
|
24
|
+
const m = /^\s+(\S+)\s+REG_(?:SZ|EXPAND_SZ)\s+(.*)$/.exec(line);
|
|
25
|
+
if (m && entry) entry[m[1]] = m[2].trim();
|
|
26
|
+
}
|
|
27
|
+
return entries.filter((e) => e.DisplayName);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Every uninstall entry on this machine, and the hives `reg` could not read (a missing hive is
|
|
32
|
+
* normal: HKLM's WOW6432Node exists only on 64-bit Windows), so a reader can say an app it did not
|
|
33
|
+
* find may still be there.
|
|
34
|
+
*/
|
|
35
|
+
function readUninstallEntries(run) {
|
|
36
|
+
const entries = [], unread = [];
|
|
37
|
+
for (const hive of HIVES) {
|
|
38
|
+
const r = run('reg', ['query', hive, '/s'], { timeout: 15000, maxBuffer: 32 * 1024 * 1024 });
|
|
39
|
+
if (r.code === 0) entries.push(...parseUninstall(r.out));
|
|
40
|
+
else if (!/unable to find/i.test(`${r.err || ''}${r.out || ''}`)) unread.push({ hive, why: (r.err || r.out || `exit ${r.code}`).trim().split(/\r?\n/)[0] });
|
|
41
|
+
}
|
|
42
|
+
return { entries, unread };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** electron-builder names its entry "<name> <version>", Tauri "<name>"; "Fabric" never matches "Fabric Inbox". */
|
|
46
|
+
function names(entry, name) {
|
|
47
|
+
return entry.DisplayName === name || (!!entry.DisplayVersion && entry.DisplayName === `${name} ${entry.DisplayVersion}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** The install folder an entry names, or null: an MSI entry's `MsiExec.exe /X{...}` names none. */
|
|
51
|
+
function folderOf(entry) {
|
|
52
|
+
if (entry.InstallLocation) return entry.InstallLocation.replace(/^"|"$/g, '').replace(/\\$/, '');
|
|
53
|
+
const m = /^"([^"]+)"|^(\S+\.exe)/i.exec(entry.UninstallString || '');
|
|
54
|
+
const exe = m && (m[1] || m[2]);
|
|
55
|
+
if (!exe || !exe.includes('\\') || /(^|\\)msiexec\.exe$/i.test(exe)) return null;
|
|
56
|
+
return exe.slice(0, exe.lastIndexOf('\\'));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function folders(name, { env, home }) {
|
|
60
|
+
const local = env.LOCALAPPDATA || path.join(home, 'AppData', 'Local');
|
|
61
|
+
return [path.join(local, 'Programs', name), path.join(local, name), env.ProgramFiles && path.join(env.ProgramFiles, name)].filter(Boolean);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function hasProgram(dir) { try { return fs.readdirSync(dir).some((n) => /\.exe$/i.test(n)); } catch (_) { return false; } }
|
|
65
|
+
|
|
66
|
+
/** { at, version, source: 'registry' | 'folder' } or null when the app is not installed. */
|
|
67
|
+
function findWindowsApp(product, { entries, env = process.env, home }) {
|
|
68
|
+
const dir = folders(product.name, { env, home }).find(hasProgram);
|
|
69
|
+
const hit = entries.find((e) => names(e, product.name));
|
|
70
|
+
if (hit) return { at: folderOf(hit) || dir || null, version: hit.DisplayVersion || null, source: 'registry' };
|
|
71
|
+
return dir ? { at: dir, version: null, source: 'folder' } : null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = { parseUninstall, readUninstallEntries, findWindowsApp, HIVES };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/passioncode",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.48",
|
|
4
4
|
"description": "Set up PassionCode.ai on a computer with one command — the apps from their verified releases, their MCP servers for every coding agent and the PassionCode.ai skills — and check and repair it with the same command or `doctor`.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"passioncode": "bin/passioncode.js"
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"name": "passioncode",
|
|
36
36
|
"displayName": "PassionCode.ai",
|
|
37
37
|
"source": "./plugins/passioncode",
|
|
38
|
-
"version": "0.2.
|
|
38
|
+
"version": "0.2.48",
|
|
39
39
|
"description": "Set up and check PassionCode.ai on a computer with one command (setting-up-passioncode), the organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check that keeps the PassionCode.ai set current.",
|
|
40
40
|
"author": {
|
|
41
41
|
"name": "PassionCode.ai",
|
package/payload/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"family": "passioncode",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.48",
|
|
4
4
|
"release": true,
|
|
5
5
|
"members": [
|
|
6
6
|
{
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
"name": "passioncode",
|
|
63
63
|
"displayName": "PassionCode.ai",
|
|
64
64
|
"repo": "passioncode-ai/passioncode",
|
|
65
|
-
"ref": "v0.2.
|
|
65
|
+
"ref": "v0.2.48",
|
|
66
66
|
"commit": null,
|
|
67
|
-
"version": "0.2.
|
|
67
|
+
"version": "0.2.48",
|
|
68
68
|
"via": "this repository",
|
|
69
69
|
"skills": [
|
|
70
70
|
"setting-up-passioncode",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
],
|
|
73
73
|
"legacyPluginIds": [],
|
|
74
74
|
"legacyMarketplaces": [],
|
|
75
|
-
"contentHash": "sha256:
|
|
75
|
+
"contentHash": "sha256:18c44b353312024f0735136631c2df0ac416bb8f3881406958e5aed0e710375a",
|
|
76
76
|
"description": "Set up and check PassionCode.ai on a computer with one command (setting-up-passioncode), the organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check that keeps the PassionCode.ai set current.",
|
|
77
77
|
"author": {
|
|
78
78
|
"name": "PassionCode.ai",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "passioncode",
|
|
4
4
|
"displayName": "PassionCode.ai",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.48",
|
|
6
6
|
"description": "Set up and check PassionCode.ai on a computer with one command (setting-up-passioncode), the organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check at session start that keeps the PassionCode.ai skill set current.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "PassionCode.ai",
|
|
@@ -97,7 +97,8 @@ Reply in the person's language, briefly:
|
|
|
97
97
|
- **The command fails to start** (npm error, registry down): report the error with its exit code
|
|
98
98
|
and stop. Do not fall back to manual installs.
|
|
99
99
|
- **Not macOS**: the result names each app's download page; the person installs apps from there,
|
|
100
|
-
then runs `setup` again for the MCP servers.
|
|
100
|
+
then runs `setup` again for the MCP servers. On Windows `doctor` reads which apps are installed
|
|
101
|
+
and their versions; a fix that names a download page is the person's install, not a command.
|
|
101
102
|
|
|
102
103
|
## Gotchas
|
|
103
104
|
|