@openthread/claude-code-plugin 0.1.5 → 0.1.8
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/.claude-plugin/plugin.json +2 -2
- package/README.md +111 -17
- package/bin/__tests__/settings-writer.test.js +122 -0
- package/bin/cli.sh +5 -28
- package/bin/lib/settings-writer.js +108 -0
- package/bin/postinstall.js +59 -25
- package/commands/export.md +22 -0
- package/commands/import.md +26 -0
- package/commands/search.md +15 -0
- package/commands/share.md +24 -3
- package/package.json +23 -5
- package/scripts/auth.sh +21 -3
- package/scripts/lib/__init__.py +1 -0
- package/scripts/lib/export_client.py +666 -0
- package/scripts/lib/import_client.py +510 -0
- package/scripts/lib/jsonl.py +88 -0
- package/scripts/lib/keychain.js +59 -0
- package/scripts/lib/mask.py +669 -0
- package/scripts/lib/sanitize.py +92 -0
- package/scripts/lib/search_client.py +218 -0
- package/scripts/lib/thread_to_md.py +156 -0
- package/scripts/share.sh +230 -47
- package/scripts/token.sh +215 -23
- package/skills/export-thread/SKILL.md +166 -0
- package/skills/import-thread/SKILL.md +171 -0
- package/skills/search-threads/SKILL.md +103 -0
- package/skills/share-thread/SKILL.md +25 -43
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openthread/claude-code-plugin",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Share Claude Code conversations to OpenThread",
|
|
3
|
+
"version": "0.1.8",
|
|
4
|
+
"description": "Share Claude Code conversations to OpenThread — the StackOverflow for AI agents. One command to publish any session to the community platform for the agentic AI era.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"openthread-claude": "bin/cli.sh"
|
|
7
7
|
},
|
|
@@ -13,11 +13,16 @@
|
|
|
13
13
|
"scripts/auth.sh",
|
|
14
14
|
"scripts/share.sh",
|
|
15
15
|
"scripts/token.sh",
|
|
16
|
+
"scripts/lib/",
|
|
16
17
|
"icon.svg"
|
|
17
18
|
],
|
|
18
19
|
"scripts": {
|
|
19
20
|
"prepack": "node -e \"const fs=require('fs');const v=JSON.parse(fs.readFileSync('package.json','utf8')).version;const p=JSON.parse(fs.readFileSync('.claude-plugin/plugin.json','utf8'));p.version=v;fs.writeFileSync('.claude-plugin/plugin.json',JSON.stringify(p,null,2)+'\\n')\"",
|
|
20
|
-
"postinstall": "node bin/postinstall.js"
|
|
21
|
+
"postinstall": "node bin/postinstall.js",
|
|
22
|
+
"test": "node bin/__tests__/settings-writer.test.js"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"keytar": "^7.9.0"
|
|
21
26
|
},
|
|
22
27
|
"keywords": [
|
|
23
28
|
"claude-code",
|
|
@@ -25,8 +30,21 @@
|
|
|
25
30
|
"openthread",
|
|
26
31
|
"plugin",
|
|
27
32
|
"ai",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
33
|
+
"ai-agents",
|
|
34
|
+
"agentic-ai",
|
|
35
|
+
"ai-conversation",
|
|
36
|
+
"ai-conversations",
|
|
37
|
+
"ai-thread",
|
|
38
|
+
"ai-thread-sharing",
|
|
39
|
+
"share-claude",
|
|
40
|
+
"share-conversation",
|
|
41
|
+
"claude-share",
|
|
42
|
+
"ai-community",
|
|
43
|
+
"stackoverflow-for-ai",
|
|
44
|
+
"claude-code-plugin",
|
|
45
|
+
"anthropic",
|
|
46
|
+
"prompt-sharing",
|
|
47
|
+
"ai-social"
|
|
30
48
|
],
|
|
31
49
|
"author": "OpenThread",
|
|
32
50
|
"license": "MIT"
|
package/scripts/auth.sh
CHANGED
|
@@ -30,9 +30,13 @@ main() {
|
|
|
30
30
|
|
|
31
31
|
generate_pkce
|
|
32
32
|
|
|
33
|
+
# Generate state parameter for CSRF protection
|
|
34
|
+
STATE=$(openssl rand -hex 16)
|
|
35
|
+
|
|
33
36
|
# Create a temp file for server output
|
|
34
37
|
AUTH_OUTPUT=$(mktemp)
|
|
35
|
-
|
|
38
|
+
STATE_OUTPUT=$(mktemp)
|
|
39
|
+
trap 'rm -f "$AUTH_OUTPUT" "$STATE_OUTPUT"' EXIT
|
|
36
40
|
|
|
37
41
|
# Start local callback server, capturing output
|
|
38
42
|
python3 -c "
|
|
@@ -46,12 +50,16 @@ class Handler(http.server.BaseHTTPRequestHandler):
|
|
|
46
50
|
|
|
47
51
|
if parsed.path == '/callback' and 'code' in params:
|
|
48
52
|
code = params['code'][0]
|
|
53
|
+
state = params.get('state', [None])[0]
|
|
49
54
|
self.send_response(200)
|
|
50
55
|
self.send_header('Content-Type', 'text/html')
|
|
51
56
|
self.end_headers()
|
|
52
57
|
self.wfile.write(b'<html><body><h2>Authorization successful!</h2><p>You can close this tab and return to Claude Code.</p><script>window.close()</script></body></html>')
|
|
53
58
|
with open('$AUTH_OUTPUT', 'w') as f:
|
|
54
59
|
f.write(code)
|
|
60
|
+
if state:
|
|
61
|
+
with open('$STATE_OUTPUT', 'w') as f:
|
|
62
|
+
f.write(state)
|
|
55
63
|
else:
|
|
56
64
|
self.send_response(404)
|
|
57
65
|
self.end_headers()
|
|
@@ -79,7 +87,7 @@ except OSError as e:
|
|
|
79
87
|
fi
|
|
80
88
|
|
|
81
89
|
# Build authorization URL and open browser
|
|
82
|
-
AUTH_URL="${WEB_BASE}/extension/callback?code_challenge=${CODE_CHALLENGE}&extension_id=${EXTENSION_ID}&redirect_uri=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${REDIRECT_URI}', safe=''))")"
|
|
90
|
+
AUTH_URL="${WEB_BASE}/extension/callback?code_challenge=${CODE_CHALLENGE}&extension_id=${EXTENSION_ID}&redirect_uri=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${REDIRECT_URI}', safe=''))")&state=${STATE}"
|
|
83
91
|
|
|
84
92
|
echo "Opening browser for authorization..." >&2
|
|
85
93
|
|
|
@@ -115,6 +123,15 @@ except OSError as e:
|
|
|
115
123
|
return $?
|
|
116
124
|
fi
|
|
117
125
|
|
|
126
|
+
# Verify state parameter to prevent CSRF
|
|
127
|
+
if [ -s "$STATE_OUTPUT" ]; then
|
|
128
|
+
RECEIVED_STATE=$(cat "$STATE_OUTPUT")
|
|
129
|
+
if [ "$RECEIVED_STATE" != "$STATE" ]; then
|
|
130
|
+
echo "ERROR: State parameter mismatch — auth may have been tampered with." >&2
|
|
131
|
+
return 1
|
|
132
|
+
fi
|
|
133
|
+
fi
|
|
134
|
+
|
|
118
135
|
# Exchange the code for tokens
|
|
119
136
|
exchange_code "$AUTH_CODE"
|
|
120
137
|
}
|
|
@@ -154,7 +171,8 @@ exchange_code() {
|
|
|
154
171
|
-d "{
|
|
155
172
|
\"code\": \"${auth_code}\",
|
|
156
173
|
\"codeVerifier\": \"${CODE_VERIFIER}\",
|
|
157
|
-
\"extensionId\": \"${EXTENSION_ID}\"
|
|
174
|
+
\"extensionId\": \"${EXTENSION_ID}\",
|
|
175
|
+
\"redirectUri\": \"${REDIRECT_URI}\"
|
|
158
176
|
}")
|
|
159
177
|
|
|
160
178
|
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Shared Python helpers for the OpenThread Claude Code plugin."""
|