arkaos 2.61.0 → 2.62.0

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/VERSION CHANGED
@@ -1 +1 @@
1
- 2.61.0
1
+ 2.62.0
@@ -0,0 +1,86 @@
1
+ // Auto-install official Claude Code plugins on `npx arkaos install` and
2
+ // `npx arkaos@latest update` (PR43 v2.62.0).
3
+ //
4
+ // Behaviour:
5
+ // - No-op when runtime is not Claude Code
6
+ // - Idempotent: skips plugins already in
7
+ // ~/.claude/plugins/installed_plugins.json
8
+ // - Surfaces a one-line status per plugin (installed | already-present | failed)
9
+ // - Never raises — install failures are logged but don't break the installer
10
+ //
11
+ // Plugin list is intentionally short. Add new defaults here when the
12
+ // operator decides a plugin should ship as a standard ArkaOS dependency.
13
+
14
+ import { existsSync, readFileSync } from "node:fs";
15
+ import { execSync, spawnSync } from "node:child_process";
16
+ import { homedir } from "node:os";
17
+ import { join } from "node:path";
18
+
19
+ // Each entry is "name@marketplace" matching the `claude plugin install`
20
+ // CLI argument format.
21
+ export const DEFAULT_CLAUDE_PLUGINS = [
22
+ "frontend-design@claude-plugins-official",
23
+ ];
24
+
25
+ const _INSTALLED_REGISTRY = join(
26
+ homedir(), ".claude", "plugins", "installed_plugins.json",
27
+ );
28
+
29
+ export function installDefaultClaudePlugins({
30
+ runtime = "claude-code",
31
+ plugins = DEFAULT_CLAUDE_PLUGINS,
32
+ home = homedir(),
33
+ } = {}) {
34
+ if (runtime !== "claude-code") {
35
+ return { skipped: "runtime-not-claude-code", results: [] };
36
+ }
37
+ if (!isClaudeCliAvailable()) {
38
+ return { skipped: "claude-cli-not-found", results: [] };
39
+ }
40
+ const alreadyInstalled = readInstalledRegistry(home);
41
+ const results = plugins.map((p) =>
42
+ installOne(p, alreadyInstalled),
43
+ );
44
+ return { skipped: null, results };
45
+ }
46
+
47
+ function isClaudeCliAvailable() {
48
+ try {
49
+ execSync("claude --version", { stdio: "pipe", timeout: 5000 });
50
+ return true;
51
+ } catch {
52
+ return false;
53
+ }
54
+ }
55
+
56
+ function readInstalledRegistry(home) {
57
+ const path = join(home, ".claude", "plugins", "installed_plugins.json");
58
+ if (!existsSync(path)) {
59
+ return new Set();
60
+ }
61
+ try {
62
+ const data = JSON.parse(readFileSync(path, "utf-8"));
63
+ return new Set(Object.keys(data.plugins || {}));
64
+ } catch {
65
+ return new Set();
66
+ }
67
+ }
68
+
69
+ function installOne(plugin, alreadyInstalled) {
70
+ if (alreadyInstalled.has(plugin)) {
71
+ return { plugin, action: "already-present" };
72
+ }
73
+ // Use spawnSync so we can capture exit code without throwing on non-zero.
74
+ // Pass --silent equivalents if available; otherwise default verbosity is OK
75
+ // — the installer is interactive at install time.
76
+ const out = spawnSync("claude", ["plugin", "install", plugin], {
77
+ timeout: 60_000,
78
+ stdio: ["ignore", "pipe", "pipe"],
79
+ encoding: "utf-8",
80
+ });
81
+ if (out.error || out.status !== 0) {
82
+ const msg = (out.stderr || out.error?.message || "unknown").trim().slice(0, 200);
83
+ return { plugin, action: "failed", reason: msg };
84
+ }
85
+ return { plugin, action: "installed" };
86
+ }
@@ -311,6 +311,27 @@ export async function install({ runtime, path, force, skipSystem, withOllama })
311
311
  console.log(` Warning: could not scaffold user-data (${err.message})`);
312
312
  }
313
313
 
314
+ // PR43 v2.62.0 — auto-install default Claude Code plugins. Only runs
315
+ // when runtime is Claude Code AND the `claude` CLI is available.
316
+ // Idempotent: skips plugins already in installed_plugins.json.
317
+ try {
318
+ const { installDefaultClaudePlugins } = await import("./claude-plugins.js");
319
+ const pluginResult = installDefaultClaudePlugins({ runtime });
320
+ if (!pluginResult.skipped) {
321
+ for (const r of pluginResult.results) {
322
+ if (r.action === "installed") {
323
+ console.log(` ${r.plugin} installed.`);
324
+ } else if (r.action === "already-present") {
325
+ console.log(` ${r.plugin} already installed (skipped).`);
326
+ } else if (r.action === "failed") {
327
+ console.log(` ${r.plugin} install failed (${r.reason}).`);
328
+ }
329
+ }
330
+ }
331
+ } catch (err) {
332
+ console.log(` Warning: could not install default Claude plugins (${err.message})`);
333
+ }
334
+
314
335
  const manifest = {
315
336
  version: VERSION,
316
337
  runtime,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkaos",
3
- "version": "2.61.0",
3
+ "version": "2.62.0",
4
4
  "description": "The Operating System for AI Agent Teams",
5
5
  "type": "module",
6
6
  "bin": {
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "arkaos-core"
3
- version = "2.61.0"
3
+ version = "2.62.0"
4
4
  description = "Core engine for ArkaOS — The Operating System for AI Agent Teams"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}