@openthread/claude-code-plugin 0.1.3 → 0.1.4

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ot",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Share Claude Code conversations to OpenThread",
5
5
  "icon": "icon.svg",
6
6
  "author": {
package/bin/cli.sh CHANGED
@@ -3,6 +3,9 @@
3
3
  set -euo pipefail
4
4
 
5
5
  PLUGIN_NAME="openthread-share"
6
+ PLUGIN_ID="ot"
7
+ MARKETPLACE_NAME="local-plugins"
8
+ PLUGIN_KEY="${PLUGIN_ID}@${MARKETPLACE_NAME}"
6
9
  PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
7
10
  DEST_DIR="$HOME/.claude/plugins/$PLUGIN_NAME"
8
11
  SETTINGS_FILE="$HOME/.claude/settings.json"
@@ -18,12 +21,13 @@ usage() {
18
21
  }
19
22
 
20
23
  register_plugin() {
21
- # Register the plugin in ~/.claude/settings.json so Claude Code loads it
22
24
  python3 -c "
23
25
  import json, os
24
26
 
25
27
  settings_path = '$SETTINGS_FILE'
26
28
  dest_dir = '$DEST_DIR'
29
+ marketplace = '$MARKETPLACE_NAME'
30
+ plugin_key = '$PLUGIN_KEY'
27
31
 
28
32
  settings = {}
29
33
  if os.path.exists(settings_path):
@@ -33,46 +37,48 @@ if os.path.exists(settings_path):
33
37
  except:
34
38
  settings = {}
35
39
 
36
- if not isinstance(settings.get('enabledPlugins'), list):
37
- settings['enabledPlugins'] = []
38
-
39
- # Check if already registered
40
- already = any(
41
- p.get('source', {}).get('path') == dest_dir
42
- for p in settings['enabledPlugins']
43
- )
44
-
45
- if not already:
46
- settings['enabledPlugins'].append({
47
- 'source': {'type': 'local', 'path': dest_dir}
48
- })
49
- os.makedirs(os.path.dirname(settings_path), exist_ok=True)
50
- with open(settings_path, 'w') as f:
51
- json.dump(settings, f, indent=2)
52
- f.write('\n')
40
+ # Register as local marketplace
41
+ if 'extraKnownMarketplaces' not in settings:
42
+ settings['extraKnownMarketplaces'] = {}
43
+ settings['extraKnownMarketplaces'][marketplace] = {
44
+ 'source': {'source': 'directory', 'path': dest_dir}
45
+ }
46
+
47
+ # Enable the plugin (must be an object, not array)
48
+ if not isinstance(settings.get('enabledPlugins'), dict):
49
+ settings['enabledPlugins'] = {}
50
+ settings['enabledPlugins'][plugin_key] = True
51
+
52
+ os.makedirs(os.path.dirname(settings_path), exist_ok=True)
53
+ with open(settings_path, 'w') as f:
54
+ json.dump(settings, f, indent=2)
55
+ f.write('\n')
53
56
  "
54
57
  }
55
58
 
56
59
  deregister_plugin() {
57
- # Remove the plugin from ~/.claude/settings.json
58
60
  if [ -f "$SETTINGS_FILE" ]; then
59
61
  python3 -c "
60
62
  import json
61
63
 
62
64
  settings_path = '$SETTINGS_FILE'
63
- dest_dir = '$DEST_DIR'
65
+ marketplace = '$MARKETPLACE_NAME'
66
+ plugin_key = '$PLUGIN_KEY'
64
67
 
65
68
  with open(settings_path) as f:
66
69
  settings = json.load(f)
67
70
 
68
- if isinstance(settings.get('enabledPlugins'), list):
69
- settings['enabledPlugins'] = [
70
- p for p in settings['enabledPlugins']
71
- if p.get('source', {}).get('path') != dest_dir
72
- ]
73
- with open(settings_path, 'w') as f:
74
- json.dump(settings, f, indent=2)
75
- f.write('\n')
71
+ # Remove from enabledPlugins
72
+ if isinstance(settings.get('enabledPlugins'), dict):
73
+ settings['enabledPlugins'].pop(plugin_key, None)
74
+
75
+ # Remove marketplace
76
+ if isinstance(settings.get('extraKnownMarketplaces'), dict):
77
+ settings['extraKnownMarketplaces'].pop(marketplace, None)
78
+
79
+ with open(settings_path, 'w') as f:
80
+ json.dump(settings, f, indent=2)
81
+ f.write('\n')
76
82
  "
77
83
  fi
78
84
  }
@@ -97,7 +103,7 @@ install_plugin() {
97
103
  VERSION=$(python3 -c "import json; print(json.load(open('$DEST_DIR/.claude-plugin/plugin.json'))['version'])")
98
104
  echo "✓ OpenThread plugin v$VERSION installed to $DEST_DIR"
99
105
  echo " Registered in $SETTINGS_FILE"
100
- echo " Use /ot:share in Claude Code to share conversations."
106
+ echo " Restart Claude Code, then use /ot:share to share conversations."
101
107
  }
102
108
 
103
109
  uninstall_plugin() {
@@ -123,8 +129,8 @@ check_status() {
123
129
  import json
124
130
  with open('$SETTINGS_FILE') as f:
125
131
  s = json.load(f)
126
- plugins = s.get('enabledPlugins', [])
127
- print('true' if any(p.get('source',{}).get('path') == '$DEST_DIR' for p in plugins) else 'false')
132
+ plugins = s.get('enabledPlugins', {})
133
+ print('true' if isinstance(plugins, dict) and plugins.get('$PLUGIN_KEY') else 'false')
128
134
  " 2>/dev/null || echo "false")
129
135
  fi
130
136
 
@@ -136,7 +142,7 @@ print('true' if any(p.get('source',{}).get('path') == '$DEST_DIR' for p in plugi
136
142
  fi
137
143
 
138
144
  if [ "$registered" = "true" ]; then
139
- echo "✓ Registered: yes (in $SETTINGS_FILE)"
145
+ echo "✓ Registered: yes ($PLUGIN_KEY in $SETTINGS_FILE)"
140
146
  else
141
147
  echo "✗ Registered: no (Claude Code won't detect the plugin)"
142
148
  echo " Run: openthread-claude install"
@@ -49,13 +49,9 @@ try {
49
49
  }
50
50
 
51
51
  // Register plugin in ~/.claude/settings.json so Claude Code detects it
52
+ const MARKETPLACE_NAME = "local-plugins";
53
+ const PLUGIN_ID = "ot";
52
54
  const settingsPath = join(homedir(), ".claude", "settings.json");
53
- const pluginEntry = {
54
- source: {
55
- type: "local",
56
- path: pluginDest,
57
- },
58
- };
59
55
 
60
56
  let settings = {};
61
57
  if (existsSync(settingsPath)) {
@@ -66,19 +62,25 @@ try {
66
62
  }
67
63
  }
68
64
 
69
- if (!Array.isArray(settings.enabledPlugins)) {
70
- settings.enabledPlugins = [];
65
+ // Register as a local marketplace
66
+ if (!settings.extraKnownMarketplaces) {
67
+ settings.extraKnownMarketplaces = {};
71
68
  }
69
+ settings.extraKnownMarketplaces[MARKETPLACE_NAME] = {
70
+ source: {
71
+ source: "directory",
72
+ path: pluginDest,
73
+ },
74
+ };
72
75
 
73
- // Only add if not already registered
74
- const alreadyRegistered = settings.enabledPlugins.some(
75
- (p) => p.source && p.source.path === pluginDest
76
- );
77
- if (!alreadyRegistered) {
78
- settings.enabledPlugins.push(pluginEntry);
79
- mkdirSync(join(homedir(), ".claude"), { recursive: true });
80
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
76
+ // Enable the plugin
77
+ if (!settings.enabledPlugins || typeof settings.enabledPlugins !== "object" || Array.isArray(settings.enabledPlugins)) {
78
+ settings.enabledPlugins = {};
81
79
  }
80
+ settings.enabledPlugins[`${PLUGIN_ID}@${MARKETPLACE_NAME}`] = true;
81
+
82
+ mkdirSync(join(homedir(), ".claude"), { recursive: true });
83
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
82
84
 
83
85
  const version = JSON.parse(readFileSync(join(pluginSrc, "package.json"), "utf8")).version;
84
86
  console.log(`\x1b[32m✓\x1b[0m OpenThread plugin v${version} installed to ${pluginDest}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openthread/claude-code-plugin",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Share Claude Code conversations to OpenThread",
5
5
  "bin": {
6
6
  "openthread-claude": "bin/cli.sh"