xiaohongshu-auto-posting — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited xiaohongshu-auto-posting (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
End-to-end Xiaohongshu content operation: topic discovery → style reference → writing → publishing → performance tracking.
All process output to user (progress updates, questions, status notifications) follows the user's language.
Automate a complete Xiaohongshu content operation cycle for a configured product: discover high-engagement pain-point topics via search, collect writing style references, generate platform-native content aligned with the style fingerprint, publish with user approval, and track post-publish performance metrics.
creator.xiaohongshu.com) already logged in on a configured stealth browser (browser ID stored in session_state.json)workspaces/xhs-posting/ workspace (auto-created on first run)If browser-act has been confirmed available in the current session → skip this step.
Invoke browser-act via Skill tool to load usage. If installation or configuration issues arise, follow its guidance to resolve then retry.
Covered in Phase 0.5 — login check is deferred until session state is loaded (Phase 0.2) and the browser is opened. If the user triggers Phase 6 directly (standalone tracking mode), still complete Phase 0.2 and Phase 0.5 first.
Each execution generates a unique session name (xhs-<YYYYMMDD>-<HHMM>) to avoid cross-conversation conflicts. The session is opened once in Phase 0.5 and closed at the end of the workflow. All commands in this Skill reference the session via $SESSION — the actual name is determined at runtime.
All runtime files (config, drafts, publish records, screenshots) are written to the user's working directory (CWD) under workspaces/xhs-posting/. This directory is auto-created on first run.
workspaces/xhs-posting/ ← relative to user CWD
├── session_state.json # account & product config
├── config/
│ └── keywords.json # keyword pool
├── tracking/
│ └── published.json # published note records
├── reports/ # performance reports
└── <YYYY-MM-DD>/ # per-run date directory
├── topics/
├── selected_topics.json
├── style_fingerprint.json
├── drafts/
└── replies//xiaohongshu-auto-postingStandalone triggers (jump directly to the corresponding phase, skipping Phase 0–4):
"track performance" / "see data" / "data collection" → Phase 6 performance tracking"settings" / "switch account" / "update keywords" → Phase 0 configuration wizardThree rules that apply to every browser-act session. Violating any one causes silent failures or long hangs. Full details in references/phase5-publish.md §0.
Rule 1 — Never pipe browser-act output directly
Redirect state output to a temp file, then grep the file. Piping may background the command when output contains multi-byte characters, making the result unavailable synchronously.
# WRONG
browser-act --session $SESSION state | grep "Publish"
# CORRECT
browser-act --session $SESSION state > /tmp/s.txt 2>&1 && grep "Publish" /tmp/s.txtRule 2 — Escape all non-ASCII content before passing to eval --stdin
Non-ASCII literals (Chinese, emoji) in JS source cause encoding errors in the subprocess pipeline. Escape to \uXXXX first:
def to_ascii_js(s):
return ''.join(r'\u{:04x}'.format(ord(c)) if ord(c) > 127 else c for c in s)
js = to_ascii_js(open('tmp/script.js', encoding='utf-8').read())
subprocess.run([..., 'eval', '--stdin'], input=js.encode('ascii'), ...)Rule 3 — Use `click`, not `eval`, for actions that trigger navigation
eval hangs (~30 s timeout) when the callback causes a page redirect. Always use browser-act --session $SESSION click <index> for the publish button, then verify the URL immediately after.
Run browser-act browser list:
uv tool upgrade browser-act-cli || uv tool install browser-act-cli --python 3.12, then continueRead workspaces/xhs-posting/session_state.json:
browser_id is empty → proceed to 0.3 First-time Configuration Wizardbrowser_id is non-empty → load and display current config, ask user to confirm or modifysession_state.json structure:
{
"browser_id": "",
"account": {
"nickname": "",
"profile": ""
},
"product": {
"name": "",
"tagline": "",
"url": "",
"install_cmd": ""
},
"keywords_file": "workspaces/xhs-posting/config/keywords.json",
"posting": {
"daily_limit": 1,
"min_interval_hours": 6,
"last_posted_at": null
}
}Step 1: Browser Selection
Run browser-act browser list, then:
When existing browsers are present: display all browsers (id / name / type / desc / proxy), ask the user which one to use for posting:
Existing browsers:
#1 id=xxx name="xxx" type=stealth desc="xxx" proxy=XX
#2 id=xxx name="xxx" type=chrome desc="xxx"
Select a browser number to use for posting, or enter "new" to create one:
>When no browsers exist, or user enters "new":
browser-act get-skills advancedStep 2: Product & Keyword Configuration
Ask the user:
Write to workspaces/xhs-posting/session_state.json and workspaces/xhs-posting/config/keywords.json, then continue to Phase 0.4.
posting.last_posted_at from session_state.jsonmin_interval_hours have passed since the last post, notify the user and ask whether to force continuedaily_limit, notify the userGenerate a unique session name for this execution:
$SESSION = "xhs-<YYYYMMDD>-<HHMM>" # e.g., xhs-20260611-1430Open the browser using the stored browser_id:
browser-act --session $SESSION browser open <browser_id> https://creator.xiaohongshu.com/new/home
browser-act --session $SESSION wait stableVerify login: check that the current URL stays on creator.xiaohongshu.com (not redirected to the login page) and that a user avatar / nickname element is present in state.
--headed mode: browser-act --session $SESSION browser open <browser_id> https://creator.xiaohongshu.com/new/home --headedWait for the user to confirm login, then continue.
Full execution parameters: references/phase1-topic-collection.md.
Overview:
config/keywords.json (sequential mode)score = likes + collects × 2 + comments × 1.5workspaces/xhs-posting/<date>/topics/TOPICS_<kw-slug>.mdFull execution parameters: references/phase2-case-collection.md.
Overview:
workspaces/xhs-posting/<date>/style_fingerprint.jsonPhase 2 runs in parallel with Phase 1 (shared search results, different analysis angle).
After displaying the Phase 1 Top 5, ask the user:
Here are the Top 5 topics. Which ones do you want to write?
(enter numbers like "1 3"; "all" for all; "skip" to pass today)
>On receiving the reply:
workspaces/xhs-posting/<date>/selected_topics.jsonIf the user enters "skip" → end this run without advancing last_index.
Full writing guidelines: references/phase4-writing.md.
Write one draft per selected topic, show a preview after each draft and wait for user approval before moving to the next.
Writing framework: Pain resonance → Struggle / attempts → Product discovery → Concrete proof → Call to action
Hard requirements:
references/phase5-publish.md §5)Pre-Write Gate (confirm all items before writing begins):
key_quote extracted from Phase 1 deep passpain_description confirmed from Phase 1tools_tried confirmed from Phase 1session_state.jsonstyle_fingerprint.json) readAfter writing, generate an HTML preview (see references/phase4-writing.md §7), display it in the conversation, then ask:
Preview above. Ready to publish?
- "ok" / "publish" — proceed to Phase 5 publishing
- "edit: <instruction>" — revise per instruction and re-preview
- "draft" — save as draft, do not publishFull execution parameters: references/phase5-publish.md.
Overview:
GET permit → PUT file — to obtain file_idnote_id from the redirect URL or pageworkspaces/xhs-posting/<date>/published.json, update posting.last_posted_at in session_state.jsonGate: publish only executes after user approval of the content; auto-publishing unapproved content is not allowed.
Full execution parameters: references/phase6-tracking.md.
Standalone trigger: when the user says "track performance" / "see data" / similar trigger words, jump directly to this phase.
Sub-actions:
| Sub-action | Trigger | Description |
|---|---|---|
| 6.1 Single post 24h tracking | Auto-scheduled after Phase 5 publish | Revisit note_id 24h later, update initial metrics |
| 6.2 Batch data collection | User trigger / weekly | Pull latest data for all published notes from recent N days |
| 6.3 View comments | User trigger | View new comments, draft replies, reply after user approval |
| 6.4 Generate report | User trigger | Aggregate data, output table report |
Data stored locally in workspaces/xhs-posting/tracking/.
candidates >= 10, deep-extracted notes = 5, report file existsstyle_fingerprint.json written, sample_notes count >= 1published=true, note_id captured and written to published.jsonAfter completing the workflow (any phase exit — normal completion, user abort, or error), close the session to release resources:
browser-act session close $SESSIONDo not close if the user explicitly requests to keep the session open for manual inspection.
window.__INITIAL_STATE__ hydration timing is inconsistent — retry once after 2 s if emptysearch/notes XHR may not appear in all browser fingerprints; fall back to get markdown if missingexecCommand body injection — always embed hashtags directly in body text (see references/phase5-publish.md §4.3)note_id may not be auto-capturable when note is under review; record as pending_review and fill in manually laterPath: {working-directory}/browser-act-skill-forge-memories/xiaohongshu-auto-posting-xhs-post.memory.md
Before execution: if the file exists, read it first — it records unexpected situations encountered during past executions (e.g., a strategy has become ineffective); adjust strategy accordingly.
After execution: if an unexpected situation is encountered (strategy became ineffective, page redesigned, anti-scraping upgraded, better path discovered), append a line: {YYYY-MM-DD}: {what happened} → {conclusion}
Normal execution does not write to the file. Do not record which keywords were used or how many results were returned — those are task outputs, not experience.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.