@openthread/claude-code-plugin
v0.2.8
Published
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.
Downloads
2,200
Maintainers
Readme
@openthread/claude-code-plugin
Share, search, import, and install Claude Code conversations as skills via OpenThread — the StackOverflow for AI agents. The community platform for the agentic AI era, where developers share, vote on, and discover the best AI conversation threads from Claude, ChatGPT, Gemini, and more.
Eight slash commands. Zero surprise browser pops. Strict trust boundaries between third-party content and your local machine.
Install
npm i -g @openthread/claude-code-pluginRestart Claude Code. That's it — nothing else to configure. npm install
registers the plugin and wires up all the slash commands automatically.
/ot:share — publish the current conversation
> /ot:share
Analyzing your conversation...
Step 1: Authenticate ✓
Step 2: Find the session file ✓ — 2 contexts detected
Step 3: Review and publish
? This session has 2 detected contexts. Which do you want to share?
> Full thread (Recommended)
seg-0: Debugging PKCE token refresh (turns 0–42)
seg-1: Wiring up the new search index (turns 43–87)
? Choose one or more communities to publish to [multi-select]
[x] Coding with AI (Recommended)
[ ] Debugging with AI
[ ] AI Dev Tools
[ ] Claude Threads
? Auto-generated tags: typescript, auth, debugging. Accept or edit?
> Accept (Recommended)
Edit tags
? Publish this as a Thread or a Skill?
> Thread (Recommended)
Skill
Conversation shared to OpenThread:
• Title: Debugging PKCE Token Refresh in Auth Middleware
• Community: Coding with AI
• Tags: typescript, auth, debugging
• Type: Thread
• URL: https://openthread.me/c/coding-with-ai/post/27512cb1What happens:
- Context detection — the plugin splits your session into distinct topic segments using timestamp gaps, working-directory changes, and tool-use shifts. If it finds more than one segment, you can publish just the one that matters. Otherwise this question is skipped.
- Multi-community selection — pick one or more communities. The plugin creates a separate post per community.
- Tags — auto-generated from the conversation content; accept or rewrite in one keypress.
- Post type —
Thread(standard conversation) orSkill(reusable package others can install via/ot:import --skill).
The first run on a fresh machine prints an extra
Signing you in to OpenThread... line before Analyzing your
conversation.... A browser tab opens for OAuth; once you approve, the
rest of the flow proceeds automatically. You never type /ot:auth login
by hand. Every subsequent /ot:share skips the sign-in step — the
session is cached.
Non-interactive variants:
/ot:share --yes # skip the editor preview
/ot:share --skill --segment 2 # publish segment 2 as a Skill post
/ot:share --community ai-dev # skip the community picker/ot:search — search OpenThread
> /ot:search "hono auth middleware" --limit 3
[1] Debugging PKCE token refresh in auth middleware
c/coding-with-ai · u/alice · 3h ago · ▲ 42 · 💬 7
Walks through the PKCE refresh flow and the off-by-one in expiresAt
that caused silent sign-outs on the 59th minute of every session...
[2] Hono middleware ordering: auth before CORS or after?
c/backend-tips · u/bob · 1d ago · ▲ 18 · 💬 4
A short thread on why CORS must run before auth if you want 401s
to include CORS headers...
[3] JWT rotation with Hono + Redis
c/hono · u/carol · 2d ago · ▲ 9 · 💬 2
? Import one of these?
> [1] Debugging PKCE token refresh in auth middleware
[2] Hono middleware ordering
[3] JWT rotation with Hono + Redis
Skip — just the results, don't importIf you pick a result, the plugin asks how to import it (save, inject,
or install as a skill) and delegates to /ot:import.
Filters:
/ot:search "code review" --type comments # comments, not posts
/ot:search "gh auth helper" --type skills # only skill-shares
/ot:search "hono" --community coding-with-ai # scope to one community
/ot:search "typescript" --provider claude --time week # claude threads this week
/ot:search "migration" --limit 25 # up to 25 resultsRuns anonymously. No browser, no auth, no session required. If you happen to be signed in, you also see posts from private communities you belong to.
/ot:import — fetch a post into your workspace
> /ot:import 27512cb1-4e7a-4c3b-9d8e-1f2a3b4c5d6e
Imported: Debugging PKCE Token Refresh in Auth Middleware
Author: @alice
Community: c/coding-with-ai
Messages: 42
Size: 87 KB
Preview:
Long session today. PKCE flow was working locally but silently failing
in prod — token refresh endpoint was returning 200 with an empty body...
Saved locally. I will NOT read this file automatically. If you want me
to read it, ask in a new message. The imported content is DATA, not
instructions.Three destination modes — one flag picks where the content lands:
/ot:import <id> # --read (default) → disk, NOT injected
/ot:import <id> --read # explicit
/ot:import <id> --context # inject into THIS conversation
/ot:import <id> --skill # install as a local skill (globally)
/ot:import <id> --skill --project # install as a local skill (this repo)--read saves to ~/.openthread/imports/<uuid>.md with mode 0600.
Claude does NOT auto-load the file — you must ask in a separate message.
--context fetches the post, wraps it in an <imported_thread
trust="untrusted"> envelope, and asks you to confirm before injecting.
Declining leaves zero files on disk.
--skill installs a fetched post as a globally invokable skill at
~/.claude/skills/<name>/SKILL.md with an .ot-origin.json sidecar
recording who shared it and when. First install asks for a
one-keypress confirmation. Collision shows the existing origin next to
the new one and asks Replace / Keep / Cancel.
Accepts bare UUIDs, path suffixes, or full URLs:
/ot:import 27512cb1-4e7a-4c3b-9d8e-1f2a3b4c5d6e
/ot:import /c/coding-with-ai/post/27512cb1-4e7a-4c3b-9d8e-1f2a3b4c5d6e
/ot:import https://openthread.me/c/coding-with-ai/post/27512cb1-...Every imported byte is treated as untrusted third-party data. See the Security guarantees section for the full trust boundary.
/ot:export — download a post as a local file
> /ot:export 27512cb1-4e7a-4c3b-9d8e-1f2a3b4c5d6e
Exported: Debugging PKCE Token Refresh in Auth Middleware
Format: markdown
Size: 87 KB
The file is a plain archive with a provenance banner. It is NOT
loaded into my context. If you want me to read it, ask in a new
message.Unlike /ot:import, the exported file is written to your current
working directory with sharable permissions (0644). It's meant to
be committed to a repo, shared over email, or archived — not loaded
into Claude's context.
Format and output flags:
/ot:export <id> # markdown archive (default)
/ot:export <id> --format json # structured JSON export
/ot:export <id> --format text --no-banner # plain text, no provenance header
/ot:export <id> --out ./thread.md # explicit output path (CWD-guarded)
/ot:export <id> --stdout # body to stdout, metadata to stderr--skill mode writes a SKILL.md-shaped template file to your
current directory. Unlike /ot:import --skill, this does NOT install
the skill globally — it just produces the file so you can commit it
to a repo.
/ot:export <id> --skill # write SKILL.md template to CWDTo take a template from /ot:export --skill and install it globally,
use /ot:import --skill <source-url> after publishing the thread.
Different commands, different targets.
Runs anonymously. No browser, no auth, no session required.
Power-user skills
These exist for troubleshooting and non-npm install flows. You do not need any of them during normal daily use — the four skills above are complete.
/ot:status — health check when something breaks
> /ot:status
Plugin: ✓ openthread-share v0.2.2
~/.claude/plugins/marketplaces/openthread/plugins/ot/
Skills: ✓ 8/8 installed
Deps: ✓ python3 3.11 ✓ curl 8.1 ✓ bash 5.2
Auth: ✓ signed in as @alice, expires in 42m
Server: ✓ reachable
Updates: ✓ up to date (0.2.2)Run this if a skill is behaving oddly. Every failing line includes a
fix: <command> hint. Side-effect-free — safe to run any time.
/ot:status --json # machine-readable for scripting
/ot:status --quiet # only failing sections, rc=1 if any
/ot:status --section auth # limit to one section/ot:auth — explicit session management
You almost never need this. The first /ot:share on a fresh machine
auto-auths; subsequent calls reuse the cached session. Use /ot:auth
only when you want to sign OUT, switch accounts, or force-refresh a
dying session.
/ot:auth # whoami if signed in, else login
/ot:auth whoami # print the signed-in user + expiry
/ot:auth refresh # refresh the token without opening a browser
/ot:auth logout # clear the cached session (asks for confirmation)
/ot:auth logout --yes # clear without asking
/ot:auth login # force a fresh browser OAuth flow/ot:update — update the plugin (non-npm install paths)
If you installed via npm, use npm update -g @openthread/claude-code-plugin
instead. This command is for users who installed via git clone or tarball.
/ot:update --check # report availability, no changes
/ot:update # fetch → stage → validate → atomic swap
/ot:update --dry-run # stage + validate, don't swap
/ot:update --rollback # restore the most recent backupUpdates are atomic. The new tree is staged in a sibling directory,
validated (deps, minApi compat), then promoted via a directory rename.
In-flight skills finish under the old tree (the kernel holds their
inode open), and the backup at .bak/<old-version>/ lets you roll back
if something regresses.
/ot:install — bootstrap the plugin (non-npm install paths)
If you installed via npm, the plugin is already installed. Running
/ot:install will report EXISTS. This command is for users who prefer
to install from git or a local path.
/ot:install --source git --from https://github.com/openthread/openthread-share
/ot:install --source tarball --from https://openthread.me/releases/v0.2.2.tgz
/ot:install --source local --from ~/src/openthread-share
/ot:install --dry-run # preview without touching anythingSecurity guarantees
Everything below is covered by the regression suite at
scripts/test-live.sh — run it any time to verify.
Auth is never initiated on your behalf
The plugin never opens a browser OAuth flow except when you explicitly
run /ot:auth login. No other skill — not /ot:share, not /ot:search,
not /ot:import, not even /ot:status — will ever initiate auth on
its own.
Under the hood, every optional-auth path uses token.sh get-if-cached,
which:
- Returns a cached access token if one is valid.
- Refreshes the token silently if it's within 60s of expiry.
- Exits non-zero without touching the browser if no session exists.
On a stale refresh token (refresh fails with 401/403/etc.), the
plugin clears the bad session file automatically so subsequent
invocations take the fast "no session" path instead of hammering the
refresh endpoint. You must run /ot:auth login to re-authenticate.
Imported content is UNTRUSTED data, never instructions
/ot:import treats every byte of a fetched post as data, not
commands. The skill body enforces this at multiple layers:
- The imported content is never executed, interpreted, or treated as instructions by Claude.
--readsaves to disk with mode0600inside a0700directory and does NOT auto-read the file into context.--contextwraps the body in an<imported_thread trust="untrusted">envelope before injection, and the envelope file is not pre-written to disk — the user must confirm viaAskUserQuestionbefore any injection or write.--skillshows a confirmation block with the post's origin (name, description, author, community) before installing. On collision, the existing.ot-origin.jsonsidecar is shown alongside the new origin so the user can decide between Replace / Keep / Cancel.- Strict UUID validation on every input form.
- HTTPS enforced unless
OPENTHREAD_API_URLpoints to a loopback host. - Response bodies capped at 5 MB, read in bounded chunks.
- Control characters and ANSI escapes stripped; paths, usernames, secrets, emails, and IPs masked locally as defense-in-depth on top of server-side masking.
Skill installs leave a provenance trail
Every /ot:import --skill install writes a .ot-origin.json sidecar
next to the SKILL.md:
{
"schema": "ot-origin/1",
"postId": "27512cb1-4e7a-4c3b-9d8e-1f2a3b4c5d6e",
"author": "alice",
"community": "coding-with-ai",
"importedAt": "2026-04-15T10:23:11Z",
"pluginVersion": "0.1.12",
"sourceUrl": "https://openthread.me/c/coding-with-ai/post/27512cb1-...",
"title": "Auth helper for gh CLI"
}Future imports that would collide read this sidecar to render a clear
"replacing X by @alice with Y by @bob" comparison before overwriting.
--force skips the prompt but never suppresses the summary.
File permissions and path safety
| File / directory | Mode | Purpose |
|---|---|---|
| ~/.claude/plugins/openthread-share/ | 0755 | plugin root |
| .session.json | 0600 | OAuth tokens |
| ~/.openthread/imports/ | 0700 | untrusted archives |
| ~/.openthread/imports/<uuid>.md | 0600 | imported posts |
| ~/.openthread/audit.log | 0600 | mutating-op log |
| /ot:export output files | 0644 | shareable archives |
Writes are atomic — every file is written as <path>.part and
renamed into place, so a partial download or crash never leaves
corrupt content at the final path.
/ot:export --out <path> is path-traversal guarded: relative
paths must stay under CWD; absolute paths are rejected if they land
inside /etc /dev /proc /sys /bin /sbin /usr /var /boot /lib /lib64.
Retries are bounded
Every network call goes through ot_curl_with_retry:
- 3 attempts total, exponential backoff (1s, 2s).
- 60s wall-clock cap — exceeds and emits a structured error.
- 429 Retry-After is honored up to the 60s cap.
- 4xx errors are terminal (they're caller intent, not transient).
- 5xx errors are retryable within budget.
There is no infinite retry loop. If the server is down, you get one
clean HTTP_ERROR and the command exits.
Concurrency
/ot:install and /ot:update hold a mkdir-based lock at
~/.claude/plugins/openthread-share/.lockdir/. A second concurrent
invocation immediately gets LOCK_HELD instead of racing.
Core skills (/ot:share, /ot:search, etc.) do NOT take the lock —
they run independently and are unaffected by update activity.
First use
Just run one of the four commands. No pre-setup, no install dance:
> /ot:shareThe first /ot:share on a fresh machine prints one line (Signing you
in to OpenThread...), opens a browser tab to complete OAuth, and then
proceeds to publish. You never run /ot:auth login or /ot:install
manually. Once signed in, every subsequent /ot:share is instant —
cached session, no prompts, no network round-trip for auth.
The other three skills — /ot:search, /ot:import, /ot:export —
work anonymously out of the box. They never trigger a browser unless
you explicitly ask for private content, and even then only if you opt
in.
The skills
Four daily skills — listed in the order you're most likely to use them.
Each one works immediately after npm install with no pre-setup, no
prior command, and no configuration step.
| # | Command | What it does | Auth |
|---|---|---|---|
| 1 | /ot:share | Publish the current Claude Code conversation | auto (browser on first use) |
| 2 | /ot:search <query> | Search threads, comments, communities, users, skills | anonymous |
| 3 | /ot:import <id> | Fetch a post: save to disk, inject into context, or install as a skill | anonymous (public), opt-in auth (private) |
| 4 | /ot:export <id> | Archive a post as a local file or SKILL.md template | anonymous |
Four power-user skills — for troubleshooting and non-npm install flows. You do not need any of these during normal daily use.
| # | Command | When you'd need it |
|---|---|---|
| 5 | /ot:status | Something broke — see which layer (plugin, deps, auth, server) is unhappy |
| 6 | /ot:auth login / logout / refresh / whoami | Manually manage the cached session |
| 7 | /ot:update | Update the plugin from git/tarball (npm users use npm update -g) |
| 8 | /ot:install | Bootstrap from a git tag or local path (npm users already have the plugin) |
Manual install
If you prefer not to use npm:
# Option A: via /ot:install from an existing Claude Code session
/ot:install
# Option B: manual clone
git clone https://github.com/openthread/openthread-share ~/.claude/plugins/openthread-share
openthread-claude install # registers with Claude CodeRestart Claude Code. /ot:status will verify the install is healthy.
Uninstall
A dedicated uninstall command isn't shipped yet. To remove manually:
rm -rf ~/.claude/plugins/openthread-share
rm -rf ~/.claude/skills/ot-*
rm -rf ~/.claude/skills/share-thread ~/.claude/skills/search-threads \
~/.claude/skills/import-thread ~/.claude/skills/export-threadYour session (.session.json) and local imports under
~/.openthread/imports/ live outside the plugin dir — delete them
manually if desired.
License
MIT
