JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 19
  • Score
    100M100P100Q102780F
  • License MIT

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.

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@openthread/claude-code-plugin) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    @openthread/claude-code-plugin

    Share, search, import, and install Claude Code conversations as skills via OpenThreadthe 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.

    npm version license downloads

    Install

    npm i -g @openthread/claude-code-plugin

    The postinstall script registers the plugin with Claude Code automatically. Restart Claude Code, then check it's healthy:

    > /ot:status
    Plugin:   ✓ openthread-share v0.1.12
    Skills:   ✓ 8/8 installed
    Deps:     ✓ python3 3.11  ✓ curl 8.1  ✓ bash 5.2
    Auth:     ✗ not signed in
              fix: /ot:auth login
    Server:   ✓ reachable
    Updates:  ✓ up to date

    Then sign in:

    > /ot:auth login

    Your first share is now a one-liner:

    > /ot:share

    The 8 skills

    Command Purpose Auth required
    /ot:share Publish the current Claude Code conversation Yes
    /ot:search <query> Search threads, comments, communities, users, skills No
    /ot:import <id> Fetch a post: save to disk, inject into context, or install as a skill No (public), Yes (private)
    /ot:export <id> Archive a post as a local file or SKILL.md template No
    /ot:install Bootstrap the plugin on this machine
    /ot:update Atomic update with staged swap + rollback
    /ot:status Health report: plugin, skills, deps, auth, server, updates
    /ot:auth {login|logout|refresh|whoami} Manage authentication

    Examples

    Share the current conversation

    > /ot:share

    The plugin runs a silent preflight in parallel (auth check, session discovery, context detection, community fetch) then asks at most four questions:

    1. Context — if the session covers multiple topics, pick a segment or share the full thread.
    2. Community — multi-select from recommended communities. Picking multiple publishes one post per community.
    3. Tags — accept the auto-generated tags or type your own.
    4. Post typeThread (standard conversation) or Skill (reusable, importable by others).

    Output is a clean summary block with the post URL. No raw JSON, no leaked UUIDs, no "open this URL" tool spam.

    Non-interactive variants:

    /ot:share --yes                   # skip the editor preview
    /ot:share --skill --segment 2     # publish segment 2 as a skill

    Search OpenThread

    > /ot:search "hono auth middleware" --limit 5
    
    [1] Debugging PKCE token refresh in auth middleware
        c/coding-with-ai · u/alice · 3h ago · ▲ 42 · 💬 7

    Filters:

    /ot:search "code review" --type comments
    /ot:search "gh auth helper" --type skills       # only skill-shares
    /ot:search "hono" --community coding-with-ai
    /ot:search "typescript" --provider claude --time week

    Import a post

    The most expressive command in the plugin. One flag picks the destination:

    /ot:import <id>                       # --read (default) → file on disk
    /ot:import <id> --read                #   explicit
    /ot:import <id> --context             #   inject into this conversation
    /ot:import <id> --skill               #   install as ~/.claude/skills/<name>/
    /ot:import <id> --skill --project     #   install as <cwd>/.claude/skills/<name>/

    Every imported byte is treated as untrusted third-party data. See the Security guarantees section for the full trust boundary.

    Export a post as an archive or template

    /ot:export <id>                       # markdown archive in CWD (default)
    /ot:export <id> --format json
    /ot:export <id> --format text --no-banner
    /ot:export <id> --skill               # SKILL.md template (frontmatter line 1)
    /ot:export <id> --out ./thread.md
    /ot:export <id> --stdout              # body to stdout, metadata to stderr

    /ot:export --skill writes a template file you can commit to a repo — it does NOT install anything globally. To install a remote post as a skill, use /ot:import --skill (different command, different target).

    Manage authentication

    /ot:auth              # whoami if signed in, else login
    /ot:auth login        # force a fresh browser OAuth flow
    /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

    Check plugin health

    /ot:status                   # full pretty report card
    /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:status is side-effect-free. Safe to run any time. Every failing line includes a fix: <command> hint.

    Update the plugin

    /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 backup

    Updates 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.

    Security 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:

    1. Returns a cached access token if one is valid.
    2. Refreshes the token silently if it's within 60s of expiry.
    3. 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.
    • --read saves to disk with mode 0600 inside a 0700 directory and does NOT auto-read the file into context.
    • --context wraps 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 via AskUserQuestion before any injection or write.
    • --skill shows a confirmation block with the post's origin (name, description, author, community) before installing. On collision, the existing .ot-origin.json sidecar 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_URL points 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.

    Audit log

    Every mutating operation writes one JSON line to ~/.openthread/audit.log (mode 0600, rotates to .1 at 1 MB):

    {"ts":"2026-04-15T10:23:11Z","action":"import.skill","result":"success","pluginVersion":"0.1.12","detail":{"postId":"27512cb1-..."}}

    Events logged: install, update, rollback, auth.login, auth.logout, auth.refresh, import.skill, share. Purely local — never shipped over the network.

    Structured errors

    Every script emits {error, message, retryAfter?, hint?} JSON on stderr. No raw stack traces leak to the user. The canonical error codes:

    Category Codes
    Auth AUTH_REQUIRED · AUTH_EXPIRED · AUTH_REVOKED · AUTH_DENIED · AUTH_TIMEOUT
    Input MISSING_INPUT · MISSING_REQUIRED · INVALID_UUID · INVALID_FLAGS · UNKNOWN_FLAG · INVALID_FORMAT
    Network NETWORK · HTTP_ERROR · RATE_LIMITED · FORBIDDEN · NOT_FOUND · SIZE_EXCEEDED · INCOMPATIBLE_API · INSECURE_SCHEME
    Filesystem EXISTS · UNSAFE_PATH · WRITE_FAILED · MISSING_DEP
    Plugin NOT_INSTALLED · LOCK_HELD · VERSION_MISMATCH · STAGE_FAILED
    Internal INVALID_JSON · INTERNAL

    Testing

    Run the full live regression suite against https://openthread.me (or your own server) any time:

    bash ~/.claude/plugins/marketplaces/openthread/plugins/ot/scripts/test-live.sh

    The suite runs 31 tests across 10 sections in ~12 seconds. It's safe to run any time: anonymous-only by default, stashes your session to /tmp and restores it on exit, and uses only public fixture post IDs.

    Options:

    test-live.sh                         # full sweep
    test-live.sh --fast                  # skip destructive simulations (~8s)
    test-live.sh --only 'import.skill'   # filter by name pattern
    test-live.sh --verbose               # print full output of failing tests
    OPENTHREAD_API_URL=https://staging.openthread.me test-live.sh   # staging

    Exit code 0 means all green, 1 means at least one failure (counts and fix hints printed in the summary).

    CLI commands (npm wrapper)

    Command Description
    openthread-claude install Install and register the plugin with Claude Code
    openthread-claude uninstall Remove the plugin and deregister from Claude Code
    openthread-claude status Show plugin installation and registration state
    openthread-claude update Reinstall the plugin (update to current version)

    These are for npm-level install management. Inside Claude Code itself, use the slash commands (/ot:install, /ot:update, etc.) — they're richer, safer, and locked for concurrency.

    Configuration

    Environment variables override the default endpoints. Set them in your shell profile or .env file.

    Variable Default Description
    OPENTHREAD_API_URL https://openthread.me Backend base URL (bare — plugin appends /api/...). Trailing /api is normalized away.
    OPENTHREAD_WEB_URL https://openthread.me Web app base URL (used for post links)
    OPENTHREAD_UPDATE_SOURCE git Update source type (git / tarball / local)
    OPENTHREAD_UPDATE_FROM (git repo) Override the default update URL
    OPENTHREAD_IMPORT_OVERWRITE 0 Allow overwriting an existing import/skill (set to 1)
    OPENTHREAD_EXPORT_OVERWRITE 0 Allow overwriting an existing export file
    TOKEN_NO_BROWSER 0 Never launch a browser from token.sh get (honored globally)

    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 Code

    Restart 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-thread

    Your session (.session.json) and local imports under ~/.openthread/imports/ live outside the plugin dir — delete them manually if desired.

    License

    MIT