跪拜 Guibai
← All articles
AI Programming · Node.js · Open Source

Juejin Hot List Skill v1.4.0: One CLI Call, Verified API, No Login

By Hone ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

For developers building Agent skill packages, this post offers a concrete template: verify the unofficial API, keep deterministic tasks as CLI commands, and document what the API does not return. The pattern matters beyond Juejin because it prevents hallucinations and unpredictable behavior in any skill that talks to an undocumented endpoint.

Summary

The juejin-skills package now includes a hot-list command (v1.4.0) that answers natural-language requests like "look at today's Juejin frontend hot list" by running `node scripts/hot.mjs`. The script hits a public Juejin endpoint that needs no Cookie, maps fields for rank, title, author, heat, views, likes, collects, comments, and article link, and outputs either human-readable text or JSON for pipelines. The author first cross-checked endpoint documentation across sources, sent a live request, and recorded the verified field structure and date in the repo docs, rather than trusting memory or blog examples.

The article argues against wrapping every task in an "autonomous" Agent. A single GET with fixed mapping has no decision branches or memory, so packing it with Agent autonomy only adds uncertainty. Instead, the Agent's only job is translating natural language into a CLI command. The SPEC originally promised a summary field that the API does not return; after testing, the spec was corrected and explicitly states not to fabricate one. Similarly, the `type=new` parameter returns `Internal Server Error`, so it is kept in the parameter list but marked unverified rather than claim support.

A config merge bug shows why every nested default group needs an explicit shallow-merge line. Adding a `hot` group to `DEFAULTS` without updating `loadUserConfig` means a user override like `{"hot":{"defaultLimit":5}}` wipes out `type` and `maxLimit`, breaking `--limit` validation and returning an empty list. The default path never catches it; only an explicit override does. The fix is one line, but the lesson is to check merge logic whenever you add a nested group.

Takeaways
— The Juejin hot list API is public and read-only; no Cookie needed (err_no=0 without auth).
— Endpoint: `https://api.juejin.cn/content_api/v1/content/article_rank?category_id={id}&type=hot&aid=2608&spider=0`.
— Overall ranking uses `category_id=1`, a convention value not present in the categories list; must be mapped separately.
— `author_counter` fields are all zeros and not usable.
— The API response contains no summary field; the skill spec was updated to exclude it and explicitly says not to invent one.
— `type=new` returns `Internal Server Error`; the parameter is kept but marked unverified instead of promised.
— Adding a `hot` nested group to `DEFAULTS` requires a new shallow-merge line in `loadUserConfig`; missing it lets user overrides wipe out defaults, breaking limit validation and returning empty lists.
— The script supports GET with POST fallback, two-level category matching, `--limit` clamped to 1–50, text/JSON dual output, `isMain` guard, and no caching because rankings change in real time.
Conclusions

Using a CLI script for a deterministic task instead of an "autonomous Agent" keeps behavior predictable and reduces the chance of hallucinated decisions, a useful counterbalance to Agent-heavy tooling.

Verifying API fields before coding and correcting the spec from "should have" to "actually has" is a concrete way to prevent AI-generated hallucinations in downstream tools.

The config merge trap is a classic shallow-clone pitfall: default paths never exercise nested overrides, so any new configuration group needs a merge check and ideally a test to catch overwrites.

Concepts & terms
Agent skill
A packaged set of commands or workflows that an AI assistant can call, typically described in a SKILL.md file with trigger words and usage examples.
shallow merge
An object merge that only copies top-level properties; nested objects are overwritten wholesale unless each group is explicitly spread, which can silently drop defaults.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗