Oh Story writes Chinese web novels through files, gates and a line-by-line lint
Claude Code / Codex / OpenCode agent skills for writing Chinese web novels: ranking analysis, chapter breakdown, writing, removing AI style, and a full cover-art workflow, supporting both serials and short stories. 13 skills for novel writing and long-form fiction with file-based continuity tracking. MIT licensed.
At a glance
- What is it?
- Oh Story is a 13-skill pack for Chinese web novel writing that installs into Claude Code, Codex CLI, OpenCode and four other hosts. It keeps continuity in a 12KB file instead of the chat window, blocks prose when the outline is missing, and lints the result line by line.
- Who is it for?
- Use Oh Story if you serialize on a Chinese platform and your real failure mode is losing track of chapter 60: the 12KB state card, the outline gate and the regenerated tracking views hold up because they are scripts, not prompts. Do not expect it to supply a model, a taste, or a judgement about prose it has no template for.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- zenstory-ai/oh-story-claudecode8,604 ★ · +1,448
| Repository | 2026-09-28 | 2026-11-14 |
|---|---|---|
| zenstory-ai/oh-story-claudecode | 7.2k | 8.6k |
1,448 Stars in the last 47 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Continuity lives in a 12KB state card, not in the chat window
Oh Story stores a long serial's memory in files. Settings, outline, prose and tracking each live in their own directory (`设定/`, `大纲/`, `正文/`, `追踪/`), and `/story-long-write` does not lean on the conversation window to recall what happened. It writes the running state into `追踪/上下文.md`: a fixed seven-column card with a hard 12KB cap, whose full text is kept out of the writer prompt; the main session passes the writer only the state relevant to the chapter, and the outline, relevant settings and needed character cards are still read per task. Compressing the context does not quietly drop a setup. The demo long novel was rebuilt from its first twenty published chapters with `/story-import`, and this is the card as it stood before chapter 21:
## 当前位置
- 当前章:第20章 卷:第一卷·军宣整顿 故事时间:《如愿》点击破亿后的第二天
## 长期约束
- 军宣爽点必须通过作品效果、传播数据和围观反应链兑现,不能只靠系统播报。
- 钟嘉嘉未公开的军方培养安排属于作者真相,正文揭示前不能当成读者已知。
## 活跃伏笔
- F016|钟嘉嘉并非普通军报实习生,她的军方家庭背景仍未完全公开|埋第7章|回收章未定|高
- F049|吴伟收到寻衅滋事公诉通知,最终法律结果尚未落地|埋第18章|回收章未定|高
- F054|一位老兵邀请江晨上门听当年的故事,为后续创作提供入口|埋第20章|回收章未定|高
## 下一章承诺
- 先补第21章细纲,再承接老兵邀请、新歌伴奏和钢琴能力。Three of those entries are open setups with no payoff chapter chosen yet. The split the pack insists on is between what the author knows and what the reader knows: the second long-term constraint files the military placement as author truth, so it cannot be used as reader-known information before it is revealed. The project uses that separation to check whether a character knows an answer too early and whether a setup has already been revealed.
One npx command, then /story-setup and a new session
The pack lands in whichever coding agent you already run, and the model that writes your chapters is that agent's own model. No GPU, no second model, no key of its own. Installation is one command:
npx skills add zenstory-ai/oh-story-claudecode -y -g`-g` installs globally so the skills load from any directory; drop the flag and you get a project-local install. Updating is the same command run again. Hosts that can import a GitHub repo or a single skill get the same result from a sentence:
安装这个 skill https://github.com/zenstory-ai/oh-story-claudecodeThen run `/story-setup` at the project root (Codex writes it `$story-setup`) to deploy the hooks, agents and reference files the current host supports, and start a new session afterwards, because the setup writes into the project rather than into the running conversation. The named hosts are Claude Code, Codex CLI, Google Antigravity, OpenCode, ZCode, OpenClaw and Reasonix, plus any web agent that can read project files. Per-host deployment differences and known install failures, from a Windows `ENOENT` to the Antigravity `agy -p` flag and leftover directories, are collected in `docs/hosts.md` rather than here.
guard-outline-before-prose.sh stops the chapter before prose starts
The gate is the interesting part. One run of `/story-long-write 写第21章` produced this, and the order of the lines is the point:
细纲 细纲_第021章.md 追踪里写着「第21章尚无细纲」,skill 先补纲:单元 L1-03、目标情绪、本章标价、闭环状态、10 个情节点四列表格(外加可选的分辨率列)
章级检查 storyctl.py chapter check ready · 字数 2068 / 目标 2300
├ check-ai-patterns.js 0 命中
├ check-degeneration.js 0 命中
└ normalize-punctuation 0 命中
追踪提交 storyctl.py chapter commit tracking_committed=true · state_revision 0 → 1
派生视图 tracking_commit.py check 上下文.md / 伏笔.md / 角色状态/ / 时间线/ / 逐章记录/ 全部由 state 重生成,逐字一致Tracking still said chapter 21 had no outline, so the skill wrote `细纲_第021章.md` before a line of prose: unit L1-03, target emotion, what the chapter costs, closure status, and a four-column table of ten plot points with an optional resolution column. The long-form flow checks the outline and tracking before any prose is written. Once the outline passes structural acceptance, `narrative-writer` writes in two batches, facts and setups are checked before the chapter is committed, a deslop review is called when the read needs it, and the deterministic scripts close with `chapter check`. Note what the log hands you: 2068 characters against a 2300 target, three checkers at zero hits, `state_revision` moving 0 to 1. Two costs come with that ordering. The gate fires on the file, not on your intent, so a chapter you meant to write loosely gets an outline imposed on it first. And the hooks are scripts you did not write, so a hook that misjudges blocks the chapter instead of advising you.
Hand edits to the tracking files are rejected by the next check
Everything under `追踪/` except the state file is generated. After a commit, `tracking_commit.py check` re-renders `上下文.md`, `伏笔.md`, `角色状态/`, `时间线/` and `逐章记录/` from `_tracking-state.json` and compares them word for word (`逐字一致`), which is why editing one by hand gets the commit rejected. The commit itself is short and mechanical:
## 当前位置
- 当前章:第20章 场景:火箭军文工团,钟嘉嘉送来老兵书法礼后
+ 当前章:第21章 场景:火箭军文工团办公室,江晨收到谭守义地址回信后
## 活跃伏笔
- F054|一位老兵邀请江晨上门听当年的故事,为后续创作提供入口|埋第20章|回收章未定|高
+ F054|谭守义已给邻市地址,江晨定次日上门听故事|埋第20章|第22章|高
+ F057|谭守义有个讲了五十年没人听全过的故事,内容未揭示|埋第21章|第22章|高
+ F058|任务三:离别主题作品、开放日当天热度1000万+、限时14天|埋第21章|第27章|高
## 下一章承诺
- 先补第21章细纲,再承接老兵邀请、新歌伴奏和钢琴能力。
+ 江晨向周薄森请假出营,赴邻市听谭守义讲完整故事并录音,揭示F057。
## 连贯性风险
- 第21章尚无细纲,不能直接写正文。
+ 谭守义故事的作者真相为候选(E015),作者可在第22章细纲前改;揭示前不当读者已知。F054 moves from an undecided payoff chapter to chapter 22, two new setups open at F057 and F058, and the risk line that said chapter 21 had no outline is replaced by a note marking the veteran's story as a candidate truth (E015) you can still change before chapter 22's outline. The retired risk is not deleted but filed under 本章退役登记 in `逐章记录/第021章.md`, so nothing vanishes from the record. The new character 谭守义 gets a settings card and a state file of his own, and the story he carries stays unrevealed in `时间线/作者真相.md` while `读者已知.md` holds only the one line the reader actually saw.
/story-deslop is a lint with named rules, line numbers and severities
The deslop pass is local and mechanical. It matches known sentence templates and prints the file, the line and column, the rule name, the matched fragment and whether the hit blocks. Rule names are literal: `not-is-comparison`, `negation-parade`, `voice-contrast`, `cliche-density-tic`, and one aimed at em dashes. Run against a hand-built sample of AI-sounding prose it reported 8 hits, 7 of them blocking. Four of the eight:
改前.md:11:1 [blocking] negation-parade (没有犹豫,没有生涩,)
改前.md:19:3 [blocking] voice-contrast (声音不大,却)
改前.md:21:2 [blocking] not-is-comparison (不是一次简单的弹奏,而是一场蓄谋已久的惊艳亮相)
改前.md:3:1 [advisory] cliche-density-tic (仿佛 一丝 深吸一口气 缓缓 微微)The same scan over chapter 21 of the demo novel found nothing and exited 0, on text of nearly the same length. The comparison in `demo/去AI味对照/` points at a difference that is not vocabulary size but who does the labelling: the weaker version hands the reader a verdict about the scene, the stronger one leaves the same event as a visible action or object. Know what the pass cannot do. It is a template matcher over a fixed rule list, so a fresh AI habit nobody has written a rule for passes clean, and a pattern that suits your own voice is still a blocking hit until you rewrite around it.
The analysis skills grade a rival book against one platform's taste
`/story-long-analyze` reads a book you want to learn from and grades it against the reader it is meant to sell to. The demo run takes the first 23 chapters of 《盘龙》, about 62,000 characters, and scores them for a male-channel progression reader on 番茄:
| 维度 | 评分 | 说明(节选) | |------|------|------| | 开篇钩子 | 2 | 前 500 字纯地理定位 + 晨练群像,无悬念 / 冲突 / 反差,靠「平民努力出头」慢渗。代入扎实但即时拉力弱。 | | 主角塑造 | 4 | 延迟点名(第 60 段才点名)+ 他人惊叹引出,「衰败贵族 + 六岁神童」反差立人设。三章里最强项。 | | 爽点设计 | 1 | 三章零传统爽点,爽感被刻意延迟到第 18 章金手指登场,赌代入复利。 |
Hook 2, because the first 500 characters are geographic setup and a morning-exercise group portrait with no suspense, conflict or contrast. Lead 4, the strongest of the three, because the protagonist is not named until paragraph 60 and arrives through another character's amazement, the declining noble plus six-year-old prodigy contrast doing the work. Payoff 1: zero conventional payoffs in three chapters, the cheat arriving in chapter 18 on purpose. The summary calls it an extreme structure that would turn readers away on that platform if copied wholesale, while the extracted techniques, exposition through a mentor, delayed naming, emotion pushed out through the body, are reusable elsewhere. Read those numbers as one platform's taste, not a verdict on the book.
`/story-short-analyze` does the same at short length on your own work: the demo run over an 8,500-character story produced 54 plot nodes and 11 techniques, every node anchored to its source lines and tagged with an emotion type and an intensity from minus 9 to plus 9. It also names the cost it found, node N47 dumping the male lead's forgiveness in interior monologue, telling where the subgenre needs showing. `/story-short-write` then reads those 11 techniques back as input.
What the pack cannot do, and what that costs the writer
There is no model of its own. The writing model is whatever your agent is already configured with, so cost, context budget and prose style all arrive from that host, and moving hosts moves the sentences under the same gates. The checks are pattern matchers with no sense of your intent, so an unlisted habit passes clean while a listed pattern that suits your voice stays a blocking hit. And the repository's package.json is a private test harness for the dashboard, `node --test tests/dashboard-server.test.mjs` plus `playwright test` against Playwright ^1.62.0, not a published library, so there is no API to call, only skills to invoke. Smaller consequences worth knowing: `/story dashboard` serves the workbench on 127.0.0.1 and does not upload the chapters, so nothing is remote to fall back on. The newest release tag is v0.9.2 from 2026-10-30, so read the changelog to learn which version `npx` resolved. The platforms in view are Chinese ones, 起点, 番茄, 晋江, 七猫 and 知乎盐言, and the demo stories are Chinese web fiction, so the taste encoded in the scoring skills only transfers if that is your market. With 8,267 stars, 1,169 forks, 7 open issues and a last push on 2026-11-02, this is a project moving fast enough to break on you, and `docs/hosts.md` is where the breakage list lives.
Editorial conclusion
Use Oh Story if you serialize on a Chinese platform and your real failure mode is losing track of chapter 60: the 12KB state card, the outline gate and the regenerated tracking views hold up because they are scripts, not prompts. Do not expect it to supply a model, a taste, or a judgement about prose it has no template for. Read docs/hosts.md before assuming your agent installed cleanly, and run one chapter you disliked through /story-deslop before committing a live serial to it.
Frequently asked questions
What does Oh Story install into my coding agent?
Thirteen skills covering ranking-list scans, book teardowns, outline and prose writing, deslopping and cover images, plus the hooks, agents and reference files that `/story-setup` deploys. The command is `npx skills add zenstory-ai/oh-story-claudecode -y -g`, followed by `/story-setup` in the project root and a new session.
Can Oh Story write a chapter without a detailed outline?
No. The long-form flow checks the outline and tracking before writing prose, and in the demo run for chapter 21 the pack wrote `细纲_第021章.md` first, with unit L1-03, target emotion, chapter price, closure status and ten plot points in a four-column table.
Can I edit the tracking files by hand in Oh Story?
Not the derived ones. `上下文.md`, `伏笔.md`, `角色状态/`, `时间线/` and `逐章记录/` are re-rendered from `_tracking-state.json` by `tracking_commit.py check`, which compares them word for word and rejects a hand-edited copy.
Does the deslop check catch every AI-sounding sentence?
No. It matches known templates and reports file, line, rule and severity; the scan of chapter 21 returned zero hits and exit 0. A pattern with no rule behind it is not matched at all.
Which coding agents does Oh Story support?
Claude Code, Codex CLI, Google Antigravity, OpenCode, ZCode, OpenClaw and Reasonix, plus any web agent that can read project files. Per-host deployment notes and known install failures are kept in `docs/hosts.md`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/zenstory-ai-oh-story-claudecode)Star history chart for your README
[](https://hysenlabs.com/projects/zenstory-ai-oh-story-claudecode)Was this useful?