This SKILL.md is adialogue script. Each stage gives you explicit lines, input parsing, commands to run, and failure branches. Execute strictly in stage order,do not skip steps。
Stage 0 · Locate the skill root directory (first thing)
When triggered, you must first locate yourself, run this:
SBTI_HOME="$(
for d in "$HOME/.claude/skills/social-sbti" \
"$(pwd)/.claude/skills/social-sbti" \
"$(pwd)/skills/social-sbti" \
"$HOME/.claude/plugins/social-sbti/social-sbti"; do
[ -f "$d/SKILL.md" ] && echo "$d" && break
done
)"
export SBTI_HOME
echo "SBTI_HOME=$SBTI_HOME"
If the output is empty, tell the user the skill installation location is non-standard, ask them for the path, then manually export SBTI_HOME=<路径>。
Afterwardall commandsgo through "$SBTI_HOME/bin/sbti" <subcmd>, do not use relative paths.
Stage 1 · Welcome + choose platform
Lines(output verbatim, the compliance notice must be kept):
🎭 Social-SBTI 人格画像(仅供娱乐 · 只分析本人或公开公众人物)
请选择要分析的平台:
1. 即刻
2. X (Twitter)
Wait for user input: 1 / 2 / 即刻 / X / Twitter
Parse:
1/即刻/jike→PLATFORM=jike2/x/X/twitter→PLATFORM=x
If the user input is an object name rather than a platform choice: you may infer the platform from the object (for example, @sama looks like X,AI产品黄叔 looks like Jike), then confirm once: "I understand you want to analyze @sama on X, correct?"
Next step: Stage 2
Stage 2 · Ask for the object
Lines(Jike):
好的,分析即刻用户。请贴一下对方的即刻主页 URL 或 username。
示例:
https://web.okjike.com/u/E272054E-D904-4F13-A7EC-9ABD2CBF209E
或直接 username
Lines(X):
好的,分析 X 用户。请贴一下对方的 X handle / 主页 URL / user id。
示例:
@sama
https://x.com/elonmusk
44196397 (user id,最稳,不怕改名)
Wait for user input: any string
Save: TARGET=<用户输入>
Compliance confirmation(important): after getting the object, ask:
Just to confirm, this isyour own account, or is ita fully public public figure? This tool does not analyze exes, colleagues, interviewers, investors, or blind dates.
If the user clearly is an ex/colleague/private individual → refuse immediately, stop here, guide them to change the object or give up.
Next step: Stage 3
Stage 3 · Health check + auto repair
Run the health check:
"$SBTI_HOME/bin/sbti" doctor --fix --platform "$PLATFORM"
Parse doctor output:
- All green (exit code 0): skip to Stage 5 (scrape)
- Missing dependencies:
--fixwill automatically pip install, then run doctor again to confirm - Missing credentials: skip to Stage 4
- Python version too low / other hard errors: tell the user the specific reason, stop
Don't fool yourself: if the health check fails, do not proceed to scraping, otherwise it's a waste of time.
Stage 4 · First-time credential setup (run only once)
4A · Jike branch (the whole process is completed in the conversation, do not let the user leave)
jike-auth is an interactive QR code tool: it prints the QR (an ASCII QR code made of unicode block characters) and
progress information to stderr, and after scanning prints the tokens as JSON to stdout. You need to run it in thebackground
and paste the QR from stderr verbatim into the conversation so the user can scan it with the mobile app.
Line 1(short, to make room for the QR):
首次扫码拿 token,马上显示二维码。
Execution steps (strictly in order):
① Start jike-auth in the background,stdout is redirected to inbox(tokens),stderr goes to the background task output file (QR + progress):
mkdir -p ~/.config/sbti && rm -f ~/.config/sbti/jike-tokens.json && \
"$SBTI_HOME/bin/sbti" jike-auth > ~/.config/sbti/jike-tokens.json
⚠️ Be sure to use sbti jike-auth instead of the bare jike-auth. The latter is usually not in PATH under macOS Homebrew
Python —— pip install --user will throw the binary into
~/Library/Python/3.x/bin,and this directory is not picked up by the shell by default.sbti jike-auth
will locate the correct binary itself and then execv to it, without relying on PATH.
When calling the Bash toolbe sure to pass run_in_background: true,and note down the returned task id and
the output file path.
② Wait 2-3 secondsfor jike-auth to print the QR, then use the Read tool to read the output file.
You will see something like:
[+] Session: 642d995d-31a6-...
▄▄▄▄▄▄▄ ▄▄▄▄ ▄▄▄▄ ▄▄ ▄ ▄▄ ▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄▄▄
█ ▄▄▄ █ █ ██▀ ▀█▄▄█▀▀▀▀▄█ █▄███ ▄▄█▀▄█▀▄▀█ █ ▄▄▄ █
...约 25 行 QR...
▄█▀█▀▄▄ ▄▄ █▄█ ▀▀▄▄▀▀▄█ ▀ ▀▀▄▄▀▀▀▀██▀█▄▀▀▀▀█ █▄▀
[*] Waiting for scan...
If you still don't see Waiting for scan...,wait 1 more second and re-read.
③ Paste the entire QR as-is into the conversation(from the [+] Session: line up to just before Waiting for scan all the block-character lines).Wrap it in a code block,with blank lines before and after:
<原样粘贴 stderr 内容>
Then immediately follow with:
👆 Please use theJike App to scan the QR code above. After scanning, I will continue automatically here, no need to switch back and tell me.
④ Wait for the background task to finish. Two ways:
- Call the
TaskOutputtoolblock: true, timeout: 120000(give the user 2 minutes to scan) - Or every 3 seconds
Readonce~/.config/sbti/jike-tokens.json,once the file exists and is non-empty that means the scan is done
⑤ Confirm tokens are in place:
"$SBTI_HOME/bin/sbti" config jike --from-inbox
This will ingest jike-tokens.json into config.json and delete the original file. The output should be
✓ 即刻 tokens 已从 inbox 导入。
⑥ Go back to Stage 3 and rerun doctor once to confirm the credentials are ✓, then proceed to Stage 5.
Failure branches:
| Symptom | Handling |
|---|---|
| Waited 2 minutes without a scan → task exits with 1 | Tell the user "the scan timed out, do you want to try again?",and after confirmation return to step ① |
jike-tokens.json exists but config jike --from-inbox reports a format error |
jike-auth crashed midway,rm delete the file and start over from ① |
| The background task output file takes a long time to show the QR block characters | jike-auth may be stuck on the network,TaskStop kill it, tell the user to check the network and retry |
⚠️ Do not degrade to "ask the user to open another terminal and run jike-auth". This skill promises the whole flow is completed within the conversation; background + QR echo is the standard path.
4B · X branch
Script:
首次使用 X,需要从浏览器 cookies 拿两个字段:
1. 在浏览器登录 https://x.com
2. F12 打开 DevTools → Application → Cookies → https://x.com
3. 找这两个 cookie,复制它们的 Value:
- auth_token (长字符串)
- ct0 (长字符串,CSRF token)
直接贴给我,格式随意,比如:
auth_token = xxxxxx
ct0 = yyyyyy
Wait for the user to reply: two strings
Parse: extract auth_token and ct0 values from the user message
Execute:
"$SBTI_HOME/bin/sbti" config x \
--auth-token "<auth_token 值>" \
--ct0 "<ct0 值>"
Success: cookies have landed in ~/.config/sbti/x_cookies.json. Go back to Stage 3 and rerun doctor.
⚠️ Important note(remind the user after configuration):
X has very strict risk control. The script already has built-in self-rate-limiting, but it is recommended: ≤ 500 items per run, do not run for more than 10 different users a day, and do not commit cookies to git. If you get rate-limited, stop for a day and try again.
Stage 5 · Fetch posts
Execute:
"$SBTI_HOME/bin/sbti" fetch "$PLATFORM" "$TARGET" --limit 200
This will write the data to ./sbti-output/<name>_raw.json(under the user's project root).
Parse the returned: fetcher will print the final path, note it down and call it RAW_FILE。
If it fails:
| Error | Handling |
|---|---|
| 401 / token expired | Have the user rerun jike-auth (Jike) or re-export cookies (X), back to Phase 4 |
| 404 user not found | Have the user confirm whether the URL / username is correct |
| 429 / rate limited | Stop, have the user wait 30 minutes and come back |
| Network error | Have the user check the network and retry |
Do not settle for less by having the user manually paste the posts. Scraping is the cornerstone of this skill.
Phase 6 · Claude scores it personally (this is your core work)
There is no command to call for this step,you are that scoring LLM。
Steps
-
Read raw.json:
Readtool to read$RAW_FILE, enter theposts[]array. -
Sample 150 items:
- Total ≤ 150: read all
- Total > 150: recent 60% (first 90) + earlier 40% (last 60)
-
Read the rubric:
Readtool to read$SBTI_HOME/docs/SCORING_RUBRIC.md. Score against the L/M/H anchors for each dimension. -
Score all 15 dimensions item by item (fixed order):
S1 S2 S3 E1 E2 E3 A1 A2 A3 Ac1 Ac2 Ac3 So1 So2 So3 -
Strictly adhere to hard constraints(excerpted from the rubric):
- Each dimension must cite at least 1 real
post_id(must come from raw.json, do not make it up) - If there is counter-evidence → downgrade by one level
- Confidence < 0.4 or no evidence → force fallback to M
- Each dimension must cite at least 1 real
-
Extra outputs:
overall_impression: 100-200 word overall impressionpersonality_description: 200-300 word "personalized edition" description — must include the subject's specific facts (occupation, projects, catchphrases, representative views), do not use generic copyquotes: 4-6 real original quotes (copy from raw.json'scontent)
-
Write scores.json:
{ "profile": { "screen_name": "...", "platform": "jike|x", "bio": "...", "post_count": 200 }, "personality_description": "...", "overall_impression": "...", "quotes": ["...", "...", "...", "..."], "scores": [ { "dimension": "S1", "level": "H", "confidence": 0.9, "evidence": ["<真实 post_id>", "<真实 post_id>"], "reasoning": "不超过 40 字" } // ... 共 15 条 ] }Path:
./sbti-output/<name>_scores.json(same directory as raw.json, same<name>)。 -
Optional field: if the posts very obviously mention "drinking/baijiu/chugging cups" a lot, add
"drunk": true, which will trigger the DRUNK easter egg.
Self-check list before writing
- All 15 scores are present, order is correct
- Every item has ≥ 1 evidence post_id, all genuinely exist in raw.json
- Those with confidence < 0.4 have been rolled back to M
- quotes are genuine originals, not made up
- personality_description includes specific facts
Note down the scores.json path: SCORES_FILE=./sbti-output/<name>_scores.json
Phase 7 · Match + render
Execute:
"$SBTI_HOME/bin/sbti" finalize "$SCORES_FILE"
This will run the whole chain in one go:
match.py→ match the 27 personality templates, write back to scores.json to fill inpattern+personalitymake_card.py→ generate the HTML cardrender_png.py→ use playwright to screenshot into PNG (skip if not installed, a prompt will be given)
If PNG fails: continue, the HTML can be viewed on its own, and it also has a "📸 Save as image" button.
Phase 8 · Present the results
Present to the user (in this format):
-
Main result (ASCII box):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🎭 <screen_name> 【<CODE>】· <中文名> <mascot> 「<标语>」 匹配度: <XX>% 模式串: <pattern> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -
15-dimension profile(ASCII table, one dimension per row):
自我模型 S1 自尊自信 H — <reasoning> S2 自我清晰 H — <reasoning> S3 核心价值 H — <reasoning> 情感模型 E1 依恋安全 H — <reasoning> ... -
Overall impression: restate
overall_impressionan entire paragraph -
File path:
📁 产物: sbti-output/<name>_scores.json (完整数据) sbti-output/<name>-sbti.html (可分享卡片) sbti-output/<name>-sbti.png (截图,如果 playwright 就绪) -
Open command:
open sbti-output/<name>-sbti.png open sbti-output/<name>-sbti.html
Common pitfalls (learned from real experience)
- "High execution ability ≠ confidence": High Ac3 does not mean high S1; some people are driven by deadlines
- "Sharp tongue ≠ cynicism": Chinese sarcastic expression; don't mistake meme-playing for SHIT
- "Community activity ≠ high So1": It depends on whether they initiate proactively or respond passively
- "Many reposts ≠ emotional investment": Reposting may just be an information stream
- "Self-deprecation ≠ low S1": "I'm really awesome + self-deprecation" is actually H
- M is the safe zone: If unsure, mark M; don't force a fit
- Evidence must be a real post_id: Don't write ids that don't exist in raw.json
Fallback priority on failure
When any step fails, handle it according to the following priority:
- Retry — if it's a temporary error (network, short-term rate limit)
- Fix the root cause — expired credentials, wrong URL, missing dependency
- Tell the user the specific reason and stop — don't fall back to something like "then I'll just use the text you pasted"
Reference
docs/SCORING_RUBRIC.md— 15-dimension L/M/H behavioral anchors (required reading when scoring)docs/DISCLAIMER.md— compliance/refusal phrasingbin/sbti— the only command entry point; see subcommands insbti --helpexamples/huangshu_scores.json— complete scores.json format reference