@cjvana/claude-auto 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -10,7 +10,20 @@ Claude researches your codebase, picks the highest-value work (open issues, bugs
10
10
  npm install -g @cjvana/claude-auto
11
11
  ```
12
12
 
13
- This registers `claude-auto` as a Claude Code plugin. The `/claude-auto:setup` slash command becomes available in Claude Code sessions.
13
+ The postinstall script automatically registers `claude-auto` as a Claude Code plugin via a local marketplace. After install, restart Claude Code and `/claude-auto:setup` will be available.
14
+
15
+ **If auto-registration fails**, register manually:
16
+
17
+ ```bash
18
+ claude plugin marketplace add ~/.claude-auto-marketplace
19
+ claude plugin install claude-auto@claude-auto-local
20
+ ```
21
+
22
+ Or load per-session without installing:
23
+
24
+ ```bash
25
+ claude --plugin-dir $(npm root -g)/@cjvana/claude-auto
26
+ ```
14
27
 
15
28
  ### Requirements
16
29
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cjvana/claude-auto",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Autonomous Claude Code cron jobs for continuous codebase improvement",
5
5
  "type": "module",
6
6
  "engines": {
@@ -1,65 +1,106 @@
1
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
1
+ import { execFileSync } from "node:child_process";
2
+ import { mkdirSync, writeFileSync, existsSync, symlinkSync, readlinkSync } from "node:fs";
2
3
  import { join } from "node:path";
3
4
  import { homedir } from "node:os";
4
5
 
5
- const CLAUDE_DIR = join(homedir(), ".claude");
6
- const PLUGINS_DIR = join(CLAUDE_DIR, "plugins");
7
- const INSTALLED_FILE = join(PLUGINS_DIR, "installed_plugins.json");
8
- const SETTINGS_FILE = join(CLAUDE_DIR, "settings.json");
9
- const PLUGIN_ID = "claude-auto";
10
-
11
- // The plugin root is the package install location (where .claude-plugin/ lives)
12
6
  const pluginRoot = join(import.meta.dirname, "..");
13
- const now = new Date().toISOString();
7
+ const marketplaceDir = join(homedir(), ".claude-auto-marketplace");
8
+ const marketplacePluginDir = join(marketplaceDir, "plugins");
9
+ const marketplaceManifest = join(marketplaceDir, ".claude-plugin", "marketplace.json");
10
+ const symlinkPath = join(marketplacePluginDir, "claude-auto");
14
11
 
15
12
  try {
16
- mkdirSync(PLUGINS_DIR, { recursive: true });
17
-
18
- // 1. Register in installed_plugins.json
19
- let installed = { version: 2, plugins: {} };
20
- if (existsSync(INSTALLED_FILE)) {
21
- try {
22
- installed = JSON.parse(readFileSync(INSTALLED_FILE, "utf-8"));
23
- } catch {
24
- // Corrupted file — start fresh
25
- }
26
- }
27
-
28
- installed.plugins = installed.plugins || {};
29
- installed.plugins[PLUGIN_ID] = [
30
- {
31
- scope: "user",
32
- installPath: pluginRoot,
33
- version: "0.1.0",
34
- installedAt: now,
35
- lastUpdated: now,
36
- isLocal: true,
37
- },
38
- ];
13
+ // 1. Create local marketplace structure
14
+ mkdirSync(join(marketplaceDir, ".claude-plugin"), { recursive: true });
15
+ mkdirSync(marketplacePluginDir, { recursive: true });
39
16
 
40
- writeFileSync(INSTALLED_FILE, JSON.stringify(installed, null, 2) + "\n");
17
+ writeFileSync(
18
+ marketplaceManifest,
19
+ JSON.stringify(
20
+ {
21
+ name: "claude-auto-local",
22
+ description: "Local marketplace for claude-auto plugin",
23
+ owner: { name: "claude-auto", email: "noreply@claude-auto.dev" },
24
+ plugins: [
25
+ {
26
+ name: "claude-auto",
27
+ description:
28
+ "Autonomous Claude Code cron jobs for continuous codebase improvement",
29
+ source: "./plugins/claude-auto",
30
+ category: "productivity",
31
+ },
32
+ ],
33
+ },
34
+ null,
35
+ 2,
36
+ ) + "\n",
37
+ );
41
38
 
42
- // 2. Enable in settings.json
43
- mkdirSync(CLAUDE_DIR, { recursive: true });
44
- let settings = {};
45
- if (existsSync(SETTINGS_FILE)) {
46
- try {
47
- settings = JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
48
- } catch {
49
- // Corrupted file — start fresh
39
+ // 2. Symlink plugin into marketplace (remove stale link first)
40
+ try {
41
+ if (existsSync(symlinkPath)) {
42
+ const current = readlinkSync(symlinkPath);
43
+ if (current !== pluginRoot) {
44
+ // Stale symlink — remove and recreate
45
+ const { unlinkSync } = await import("node:fs");
46
+ unlinkSync(symlinkPath);
47
+ symlinkSync(pluginRoot, symlinkPath);
48
+ }
49
+ } else {
50
+ symlinkSync(pluginRoot, symlinkPath);
50
51
  }
52
+ } catch {
53
+ // Symlink failed — try direct path in marketplace.json instead
54
+ writeFileSync(
55
+ marketplaceManifest,
56
+ JSON.stringify(
57
+ {
58
+ name: "claude-auto-local",
59
+ description: "Local marketplace for claude-auto plugin",
60
+ owner: { name: "claude-auto", email: "noreply@claude-auto.dev" },
61
+ plugins: [
62
+ {
63
+ name: "claude-auto",
64
+ description:
65
+ "Autonomous Claude Code cron jobs for continuous codebase improvement",
66
+ source: pluginRoot,
67
+ category: "productivity",
68
+ },
69
+ ],
70
+ },
71
+ null,
72
+ 2,
73
+ ) + "\n",
74
+ );
51
75
  }
52
76
 
53
- settings.enabledPlugins = settings.enabledPlugins || {};
54
- settings.enabledPlugins[PLUGIN_ID] = true;
55
-
56
- writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2) + "\n");
77
+ // 3. Register marketplace + install plugin via Claude CLI
78
+ try {
79
+ execFileSync("claude", ["plugin", "marketplace", "add", marketplaceDir], {
80
+ stdio: "pipe",
81
+ timeout: 15000,
82
+ });
83
+ } catch {
84
+ // Marketplace may already be registered — that's fine
85
+ }
57
86
 
58
- console.log("claude-auto: Registered as Claude Code plugin");
59
- console.log(
60
- "claude-auto: Slash commands available — /claude-auto:setup, /claude-auto:list, etc.",
61
- );
87
+ try {
88
+ execFileSync("claude", ["plugin", "install", "claude-auto@claude-auto-local"], {
89
+ stdio: "inherit",
90
+ timeout: 15000,
91
+ });
92
+ console.log("claude-auto: Plugin installed successfully");
93
+ console.log(
94
+ "claude-auto: Slash commands available — /claude-auto:setup, /claude-auto:list, etc.",
95
+ );
96
+ } catch {
97
+ console.warn("claude-auto: Could not auto-install plugin via Claude CLI.");
98
+ console.warn("claude-auto: Register manually:");
99
+ console.warn(` claude plugin marketplace add ${marketplaceDir}`);
100
+ console.warn(" claude plugin install claude-auto@claude-auto-local");
101
+ }
62
102
  } catch (err) {
63
- console.warn("claude-auto: Could not auto-register plugin:", err.message);
64
- console.warn("claude-auto: Register manually see README for instructions.");
103
+ console.warn("claude-auto: Plugin registration failed:", err.message);
104
+ console.warn("claude-auto: Use --plugin-dir for per-session loading:");
105
+ console.warn(` claude --plugin-dir ${pluginRoot}`);
65
106
  }
@@ -1,33 +1,20 @@
1
- import { readFileSync, writeFileSync, existsSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { homedir } from "node:os";
4
-
5
- const CLAUDE_DIR = join(homedir(), ".claude");
6
- const PLUGINS_DIR = join(CLAUDE_DIR, "plugins");
7
- const INSTALLED_FILE = join(PLUGINS_DIR, "installed_plugins.json");
8
- const SETTINGS_FILE = join(CLAUDE_DIR, "settings.json");
9
- const PLUGIN_ID = "claude-auto";
1
+ import { execFileSync } from "node:child_process";
10
2
 
11
3
  try {
12
- // 1. Remove from installed_plugins.json
13
- if (existsSync(INSTALLED_FILE)) {
14
- const installed = JSON.parse(readFileSync(INSTALLED_FILE, "utf-8"));
15
- if (installed.plugins && installed.plugins[PLUGIN_ID]) {
16
- delete installed.plugins[PLUGIN_ID];
17
- writeFileSync(INSTALLED_FILE, JSON.stringify(installed, null, 2) + "\n");
18
- }
19
- }
20
-
21
- // 2. Remove from settings.json enabledPlugins
22
- if (existsSync(SETTINGS_FILE)) {
23
- const settings = JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
24
- if (settings.enabledPlugins && settings.enabledPlugins[PLUGIN_ID]) {
25
- delete settings.enabledPlugins[PLUGIN_ID];
26
- writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2) + "\n");
27
- }
28
- }
4
+ execFileSync("claude", ["plugin", "uninstall", "claude-auto@claude-auto-local"], {
5
+ stdio: "pipe",
6
+ timeout: 15000,
7
+ });
8
+ console.log("claude-auto: Plugin uninstalled");
9
+ } catch {
10
+ // Best-effort — don't fail npm uninstall
11
+ }
29
12
 
30
- console.log("claude-auto: Plugin unregistered");
13
+ try {
14
+ execFileSync("claude", ["plugin", "marketplace", "remove", "claude-auto-local"], {
15
+ stdio: "pipe",
16
+ timeout: 15000,
17
+ });
31
18
  } catch {
32
- // Best-effort: don't fail npm uninstall if cleanup fails
19
+ // Marketplace removal is optional
33
20
  }