Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "docwriter-style",
"interface": {
"displayName": "DocWriter style"
},
"plugins": [
{
"name": "docwriter-style-generator",
"source": {
"source": "local",
"path": "./"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_USE"
},
"category": "Productivity"
}
]
}
10 changes: 9 additions & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@
"owner": {
"name": "DocWriter"
},
"interface": {
"displayName": "DocWriter style"
},
"plugins": [
{
"name": "docwriter-style-generator",
"source": "./",
"description": "Learn a writing style from samples and produce a portable my-writing-style skill"
"description": "Learn a writing style from samples and produce a portable my-writing-style skill",
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_USE"
},
"category": "Productivity"
}
]
}
21 changes: 21 additions & 0 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "docwriter-style-generator",
"version": "1.0.0",
"description": "Learn a writing style from samples and produce a portable my-writing-style skill",
"author": {
"name": "DocWriter",
"url": "https://github.com/docwriter-org/style"
},
"homepage": "https://github.com/docwriter-org/style",
"repository": "https://github.com/docwriter-org/style",
"keywords": ["writing", "style", "skill"],
"skills": "./skills/",
"interface": {
"displayName": "DocWriter style generator",
"shortDescription": "Learn a writing style from your own prose",
"longDescription": "Measure word-level habits, run a multi-agent pass over words, sentences, and passages, and write a portable my-writing-style skill.",
"developerName": "DocWriter",
"category": "Productivity",
"websiteURL": "https://github.com/docwriter-org/style"
}
}
67 changes: 58 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,86 @@ Build a `my-writing-style` skill from your own prose.

Give it a few pieces of your writing — local files, URLs, or pasted text — and
it measures word-level habits, runs a multi-agent pass over words, sentences,
and passages, checks each habit with you, and writes a skill to
`~/.claude/skills/my-writing-style/` that Claude Code loads automatically in
every project.
and passages, checks each habit with you, and writes a skill that Claude Code
and Codex load automatically.

This is the same style-learning flow used in the
[DocWriter](https://docs.docwriter.org/customize/style) app.

## Install

Add the marketplace, then install the plugin:
Add the marketplace, then install the plugin. Use a session **or** the
terminal — not both.

### Claude Code

Either, in a Claude Code session:

```
/plugin marketplace add docwriter-org/style
/plugin install docwriter-style-generator@docwriter-style
```

Or, in the terminal:

```bash
claude plugin marketplace add docwriter-org/style
claude plugin install docwriter-style-generator@docwriter-style
```

### Codex

## Use
Either, in a Codex session, run `/plugins`, add marketplace
`docwriter-org/style`, then install `docwriter-style-generator`.

Or, in the terminal:

```bash
codex plugin marketplace add docwriter-org/style
codex plugin add docwriter-style-generator@docwriter-style
```

## Update

Refresh the marketplace after we ship a change. Same choice: session **or**
terminal.

### Claude Code

Either, in a Claude Code session:

```
/docwriter-style-generator
/plugin marketplace update docwriter-style
```

Or just ask Claude to learn your writing style — the skill triggers
automatically. Run it again to add a source or update the habits.
Or, in the terminal:

```bash
claude plugin marketplace update docwriter-style
```

### Codex

Either, in a Codex session, open `/plugins` and refresh marketplace
`docwriter-style`.

Or, in the terminal:

```bash
codex plugin marketplace upgrade docwriter-style
```


## Use

In Claude Code run `/docwriter-style-generator`. In Codex run
`$docwriter-style-generator`. Or just ask to learn your writing style — the
skill triggers automatically. Run it again to add a source or update the habits.

## What it produces

A separate skill at `~/.claude/skills/my-writing-style/`:
A separate skill at `~/.claude/skills/my-writing-style/` (Claude Code) and
`~/.agents/skills/my-writing-style/` (Codex):

```
my-writing-style/
Expand Down
36 changes: 23 additions & 13 deletions skills/docwriter-style-generator/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,27 @@ name: docwriter-style-generator
description: >-
Build a writing style skill from your own prose. Measures word-level habits,
then runs a multi-agent pass over words, sentences, and passages, and
produces a portable my-writing-style skill that Claude Code loads
produces a portable my-writing-style skill that Claude Code and Codex load
automatically. Run again to add a source or update the habits. Run
/docwriter-style-generator to start, or let it trigger when you ask to learn
or update a writing style.
/docwriter-style-generator or $docwriter-style-generator to start, or let
it trigger when you ask to learn or update a writing style.
---

# Build a writing style skill

This skill is a generator. It reads your writing, measures word-level habits
with the bundled analyzer, runs a multi-agent pass, checks each habit with
you, and writes a separate `my-writing-style` skill to
`~/.claude/skills/my-writing-style/` that Claude Code picks up automatically in
every project.
you, and writes a separate `my-writing-style` skill that Claude Code and
Codex pick up automatically.

If `~/.claude/skills/my-writing-style/SKILL.md` already exists, ask:
Write the same files to both homes:

```
~/.claude/skills/my-writing-style/ ← Claude Code
~/.agents/skills/my-writing-style/ ← Codex
```

If either home already has `SKILL.md`, ask:

```
AskUserQuestion:
Expand Down Expand Up @@ -77,6 +83,7 @@ directories if they do not exist:

```
~/.claude/skills/my-writing-style/sources/<label>.txt
~/.agents/skills/my-writing-style/sources/<label>.txt
```

Use the user's label as the filename (safe slug). On a rebuild, replace
Expand All @@ -103,8 +110,8 @@ Do not jump straight to impressions of word choice. Measure first, then read.
### 2a. Word-level measurements

This skill ships `scripts/analyze-style.mjs` next to this file. Run it on
every file in `~/.claude/skills/my-writing-style/sources/` in one invocation,
and write the report next to them:
every file in the style skill `sources/` folder in one invocation, and write
the report to `references/metrics.json` in both homes:

```bash
node scripts/analyze-style.mjs \
Expand All @@ -115,6 +122,9 @@ node scripts/analyze-style.mjs \
--measured
```

Copy that `metrics.json` to `~/.agents/skills/my-writing-style/references/` as
well.

`--words` keeps word-level scores. `--measured` drops zeros. A zero is not
evidence of a habit — do not invent absences from missing metrics.

Expand Down Expand Up @@ -205,15 +215,15 @@ AskUserQuestion:
question: "N out of M habits confirmed. Save as your writing style?"
options:
- label: "Save it"
description: "Write the skill to ~/.claude/skills/my-writing-style/"
description: "Write the skill for Claude Code and Codex"
- label: "Start over"
description: "Discard and try with different samples"
```

## 4. Write the my-writing-style skill

Write a complete skill to `~/.claude/skills/my-writing-style/`. Create the
directory if it does not exist.
Write a complete skill to both homes. Create the directories if they do not
exist. The two copies must match.

### SKILL.md

Expand Down Expand Up @@ -281,5 +291,5 @@ scripts/style-data.json
```

After writing, tell the user their style skill is active and will load
automatically in every Claude Code session. They can run this generator
automatically in Claude Code and Codex. They can run this generator
again to add a source or update the habits.
32 changes: 32 additions & 0 deletions tests/lexical-analysis.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ for (const needle of [
'Words and phrases',
'multi-agent pass',
'~/.claude/skills/my-writing-style/sources/',
'~/.agents/skills/my-writing-style/',
'$docwriter-style-generator',
'Add a source',
'Update propositions'
]) {
Expand All @@ -78,4 +80,34 @@ if (skill.includes('/tmp/source-')) {
throw new Error('cleaned sources should live in the style skill, not /tmp');
}

const marketplace = JSON.parse(readFileSync(join(root, '.claude-plugin/marketplace.json'), 'utf8'));
if (marketplace.name !== 'docwriter-style') throw new Error('marketplace name should be docwriter-style');
if (!marketplace.plugins.some((plugin) => plugin.name === 'docwriter-style-generator')) {
throw new Error('marketplace must list docwriter-style-generator');
}
const codexPlugin = JSON.parse(readFileSync(join(root, '.codex-plugin/plugin.json'), 'utf8'));
if (codexPlugin.name !== 'docwriter-style-generator' || codexPlugin.skills !== './skills/') {
throw new Error('Codex plugin manifest must name the generator and point at ./skills/');
}
const agentsMarketplace = JSON.parse(readFileSync(join(root, '.agents/plugins/marketplace.json'), 'utf8'));
if (agentsMarketplace.name !== 'docwriter-style') throw new Error('Codex marketplace name should be docwriter-style');
const [codexListing] = agentsMarketplace.plugins;
if (codexListing?.source?.path !== './' || !codexListing.policy?.installation || !codexListing.category) {
throw new Error('Codex marketplace must list ./ with policy and category');
}

const readme = readFileSync(join(root, 'README.md'), 'utf8');
for (const needle of [
'https://docs.docwriter.org/customize/style',
'/plugin marketplace update docwriter-style',
'claude plugin marketplace update docwriter-style',
'codex plugin marketplace upgrade docwriter-style',
'$docwriter-style-generator',
'Use a session **or** the',
'Either, in a Claude Code session:',
'Or, in the terminal:'
]) {
if (!readme.includes(needle)) throw new Error(`README.md is missing ${needle}`);
}

process.stdout.write(`ok: ${lexical.measurements.length} measured lexical metrics, ${full.measurements.length} measured metrics across four families\n`);
Loading