A curated collection of development, data science, writing, workshop, legal, and research workflows for Claude Code.
Requires Claude Code 2.1.287 or later. The tool-call guards and bulk-guard run only as a mod, and mods load from 2.1.287. The plugin manifest has no field for a minimum Claude Code version, so on an older version the SessionStart hook prints a warning that the guards are inactive.
# 1. Install the plugin
/plugin marketplace add edwinhu/workflows
# 2. Install dependencies — per-skill node packages (bun), plus the optional CLIs for
# knowledge management, email, and calendar
bash ~/.claude/plugins/cache/edwinhu-plugins/workflows/*/bin/install-deps.sh
# 3. (Optional) Live marimo kernel work — only needed by the `marimo` skill
claude plugin marketplace add marimo-team/marimo-pair
claude plugin install marimo-pair@marimo-pairmarimo-pair is a separate upstream plugin, deliberately not declared as a hard dependency: an
uninstalled dependency stops the whole plugin from loading, and one skill should not be able to
take the other sixty with it. The marimo skill routes live-kernel work to
Skill(skill="marimo-pair:marimo-pair") and works for notebook authoring without it.
The script's first step runs bun install in every skill that ships a package.json —
cite-check, deep-research and farm-out at the time of writing, each with its own lockfile.
node_modules/ is gitignored and never shipped, so a fresh clone or a fresh plugin install has no
node dependencies until this runs, and those skills' own test suites cannot even resolve their
imports before it. The rest of the script is only needed for skills that use the external tools
below. The plugin's own TypeScript hooks and JavaScript/TypeScript workflow runners use Bun; the core workflows do not require the optional CLIs installed by this script.
The script recognizes macOS, Linux, and Windows-like environments on x64 or arm64 and attempts to download matching pre-built binaries from GitHub Releases. If a tool does not publish an asset for the detected platform, the script warns and skips it:
| Tool | Purpose | Used by |
|---|---|---|
| nlm | NotebookLM CLI | librarian agent, internal nlm skill |
| readwise-custom | Readwise RAG/chat/upload | librarian agent, internal readwise-chat skill |
| scholar | Google Scholar search | librarian agent, internal google-scholar skill |
| consensus | Academic paper search | librarian agent, internal consensus skill |
| morgen | Calendar & tasks | Direct Bash, or session in ~/areas/assistant/ |
| superhuman | email-handling skill (via Bash) |
Requires gh (GitHub CLI). Tools already on your $PATH are skipped.
These are the skills you invoke directly with /name:
/work is the spine: clarify with the user, draft a plan they edit and approve, self-set a goal,
run workflow.js to implement and independently verify, then put the result in front of a human in
tuicr. Human rejection routes back to CLARIFY. The domain workflows dispatch through it and add
their own computed gate.
| Workflow | Adds to the work loop |
|---|---|
/work |
nothing — the generic loop for any task worth doing properly |
/dev |
TDD discipline: a failing test before the change, and lens reviews for security, performance and test coverage |
/ds |
a computed data-quality gate (DQ1-DQ6, M1, R1) over the panel the run builds |
/writing |
a computed plan-grammar and citation gate, plus the domain style register the plan's Domain: selects |
/workshop |
a computed deck gate over the Typst slides and speaker notes built from a paper |
/workflow-creator |
designs, repairs and audits workflows themselves |
Plan review is computed and happens before dispatch: plan-lint.ts over the built args and
plan-preflight.ts executing their commands at baseline, enforced by work-dispatch.sh while the
run is still armed. No agent reads the plan markdown looking for defects.
Part of the document skill group — one pipeline (extract → create → repair → build → render → verify) bundling the Anthropic Office skills with this project's repair/build/render tooling.
| Skill | Purpose |
|---|---|
/docx |
Word document creation, editing, tracked changes |
/pdf |
PDF extraction, creation, form filling |
/pptx |
Presentation creation and editing |
/xlsx |
Spreadsheet creation and analysis |
/docx-render |
Faithful Word export to PDF/PNG |
/law-review-docx |
Markdown/legal draft → law-review-styled Word doc |
/law-econ-docx |
Markdown law-and-economics manuscript → author-date, journal-ready Word doc |
Office format skills sourced from anthropics/skills via git submodule. Shared converters + the Google-export OOXML package repair (
scripts/docx_repair.py) live inscripts/. See references/document-skills.md for the full group and how the stages decouple.
| Skill | Purpose |
|---|---|
/ds-tables |
Publication tables in Python — pyfixest.etable() regression tables and great_tables GT formatting |
/ds-figures |
Publication-ready, accessible figures for papers, slides, and notebooks |
/crsp-lseg-splice |
Extend stale CRSP stock panels with current LSEG data |
/npx-ownership-panel |
Build the WRDS proxy-voting × ownership panel |
/fuzzy-name-matching |
Entity resolution / record linkage by name — char n-gram TF-IDF + sparse_dot_topn top-k cosine, normalize-first, scoped + global two-pass |
| Skill | Purpose |
|---|---|
/cite-check |
Verify academic citations against source PDFs |
/de-ai-revise |
Revise flagged prose to remove corpus-validated AI writing tics |
| Skill | Purpose |
|---|---|
/skill-creator |
Skill creation with superpowers enforcement patterns |
/plugin-creator |
Plugin-level creation and editing across manifests, hooks, and skills |
/workflow-creator |
Create a new structured workflow through shared-v1 |
/workflow-creator-improve |
Audit, repair, redesign, or migrate an existing workflow |
These skills have user-invocable: false — Claude loads them automatically when relevant or a workflow dispatches them internally. You don't call them directly.
bluebook, bluebook-audit, docx-repair, source-verify
wrds, lseg-data, gemini-batch
nlm, google-scholar, readwise, readwise-chat, readwise-search, readwise-docs, readwise-prune
consensus, research
marimo, jupytext, notebook-debug
farm-out, look-at, visual-verify, visual-mockup, data-context, continuous-learning, pattern-capture, ai-anti-patterns, obsidian-organize, pptx-render, headline-card
farm-out is the dispatcher work runs its agents through — work-dispatch.sh uses the sibling copy
by default, so the plugin dispatches without an outside install. It fetches its own SDK on first run.
None. The work spine has no sub-skills: the phases are beats inside skills/work/workflow.js,
dispatched as agents, so there is nothing to invoke by name and nothing to keep in sync.
Specialized subagents. The directory states the scope: agents/ is auto-discovered by Claude Code
and registers plugin-scoped (workflows:<name>), while user-agents/ is not auto-discovered and
registers user-scoped (bare name, hooks: honoured) via a symlink into ~/.claude/agents/:
| Agent | Role | Scope | Hooks |
|---|---|---|---|
librarian |
Knowledge management orchestration (NLM, Readwise, Scholar, Workspace) | plugin | — |
ds |
Empirical implementer — datasets, tables, figures, numbers; C/V/A/E constraints arrive as task refs |
user | — |
ds-reviewer |
Read-only grading of existing empirical work against C/V/A/E constraints | user | — |
workshop |
Talk implementer — Typst deck and speaker notes from a paper; preloads typst:typst |
user | — |
workshop-reviewer |
Read-only grading of slides.typ and notes.typ against the canonical Typst modules |
user | — |
writing |
General long-form prose — memos, letters, briefs, reports | user | source-first PreToolUse guard |
writing-legal |
Law review prose — footnotes, Bluebook short forms | user | source-first PreToolUse guard |
writing-econ |
Finance and accounting journal prose | user | source-first PreToolUse guard |
writing-reviewer |
Read-only prose grading against the preloaded register and the tic table | user | — |
The work spine's per-beat verifiers are still dispatched from skills/work/workflow.js with the
prompt the run needs, so no agent file exists for them. Implementers are the exception: /ds,
/writing and /workshop each set implementerAgentType to the matching agent above, and the
teaching plugin sets it to its own lecture-impl. /dev and /workflow-creator deliberately leave
it unset.
Claude Code's system prompt tells the model what kind of work it is doing. Its # Doing tasks
section opens with "The user will primarily request you to perform software engineering tasks", and
instructs that an unclear instruction be read in that context. A separate # Tone and style section
asks for short, concise responses and file_path:line_number references. Neither is wrong for code.
Both are wrong for a law review article, a lecture, or a seminar deck, where the deliverable is long
and the reader is a person rather than a terminal.
An output style can remove the first of those and cannot remove the second. Setting a style drops
# Doing tasks entirely unless the style's frontmatter sets keep-coding-instructions: true;
# Tone and style is emitted unconditionally. So a custom style does not replace the framing — it
competes with what survives, and the surviving half is precisely the half that shortens prose and
formats references for an editor.
A subagent replaces the prompt instead of arguing with it. A custom subagent's body is its entire
system prompt: Anthropic's documentation says a subagent receives that prompt plus environment
details, not the full Claude Code system prompt, and claude --agent <name> applies the same to a
main session. Asking one confirms it — it reports neither the software-engineering sentence nor a
# Tone and style section at all. That is the whole reason this plugin routes prose, decks,
teaching material and empirical work through agents rather than tuning a style.
The directory split follows from a second quirk. A hooks: block in agent frontmatter is ignored
for plugin-shipped agents and honoured for user-scoped ones, so any agent that needs a blocking
guard has to be user-scoped. user-agents/ is not a discovery location, so a symlink into
~/.claude/agents/ registers each file user-scoped under its bare name with its hooks live, while
agents/ stays auto-discovered and plugin-scoped. It is one file either way, and the plugin still
ships both.
Judging is not writing, and the roster's shape follows from that. A review lens only reads, so the
built-in Explore plus a good prompt and the right reference paths is sufficient and cheaper; an
agent earns a file only when it needs a custom prompt, hooks, or preloaded skills. The three domain
reviewers exist because grading against a constraint set needs a body this repo controls — a
built-in judge's prompt is predefined, so the modules it grades against have to reach it as task
refs rather than as anything the lens can skip — and no exam reviewer exists because a prompt
covers it. Constraint prose itself is never a skill: it has one canonical home under
constraints/ (Typst rule texts under ~/.claude/skills/typst/rules/, checkers under constraints/),
reaches dispatched agents as refs, and reaches interactive ones through the typst:typst bang
line. The same test explains the two workflows that set no implementer override: /dev and
/workflow-creator produce code and workflow definitions, where the software-engineering framing is
correct rather than a defect.
The register skills — writing-general, writing-legal, writing-econ, ai-anti-patterns — are
user-invocable: false for the same reason. Loading a register into the main chat stacks it on top
of the framing it is meant to displace;
routing the work to an agent that preloads it replaces that prompt instead. They deliberately do not
set disable-model-invocation: true, which would break both the skills: preload and the Skill
tool path a persona session needs.
Every workflow runs the same loop, in skills/work/workflow.js. The plan's <!-- work:dispatch -->
block is the sole authority and its canonical specHash is verified by each dispatched agent; the
gate is computed in JS from raw counts, fails closed on a dead agent, and returns the selector that
drives the fix loop. A domain workflow contributes its own mechanical checks and review lenses — it
does not get its own lifecycle.
Hooks auto-run at specific lifecycle events. The table has one row per command target registered in hooks/hooks.json:
| Script | Event | Trigger | Purpose |
|---|---|---|---|
session-start.ts |
SessionStart | startup/resume/clear/compact | Inject using-skills meta-skill; report an unfinished work run |
session-end.ts |
Stop | * | Update LEARNINGS.md timestamp |
lint-check.ts |
PostToolUse | Edit/Write | Lint after file changes (ESLint, ruff, lintr) |
writing-prose-check.ts |
PostToolUse | Edit/Write | Check edited prose for writing-quality violations |
cite-fidelity-lint.ts |
PostToolUse | Edit/Write | Check edited writing for citation-ledger fidelity |
pr-url-logger.ts |
PostToolUse | Bash | Log PR URLs and GitHub Actions status |
overflow-check.ts |
PostToolUse | Bash | Detect Typst content overflow after compilation |
pattern-scan.ts |
SessionEnd | clear/logout/prompt_input_exit/other | Scan session for reusable patterns |
The per-call guards run in-process on tool.call in the plugin's mod (hooks/guards/mod.ts), not as
spawned settings hooks. Each can only deny or add context, never approve. The scripts of the same
name under hooks/ stay as their settings-hook entry points (skills wire some in frontmatter) and
share the code; tests/mod-guards-parity.test.ts holds the two to identical answers.
| Guard | Before / after | Tools | Purpose |
|---|---|---|---|
image-read-guard |
before | Read | Redirect to look-at for media files |
read-guard |
before | Read, Bash | Deny unbounded dumps of large files |
suggest-compact |
before | Edit, Write | Suggest compaction at edit-count checkpoints |
pgrep-self-match |
before | Bash, Monitor | Deny self-matching pgrep/pkill -f and path-less rg |
bun-parallel-guard |
before | Bash | Deny a multi-file bun test without --parallel |
cron-delete-guard |
before / after | CronDelete / CronCreate | Keep an in-flight work run's heartbeat; record new ids |
atomic-constraint-guard |
after | Edit, Write | Validate atomic constraint file structure |
typst-convention-guard |
after | Edit, Write | Typst convention violations |
validate-skill-paths |
after | Edit, Write | ${CLAUDE_*} references to missing files |
hooks/bulk-guard.mjs is a Claude Code mod (2.1.287+), listed under "modules" in hooks/hooks.json. It runs in every session that loads the plugin, farm-out children included. It enforces the rule that per-document coding or extraction over many files is ONE gemini-batch job on pre-cut excerpts. On tool.call it does the following:
| Rule | Tools | Action |
|---|---|---|
Distinct documents read (≥20 KB; .txt .htm .html .xml .sgml .pdf .nc, or a path containing filings/archives/edgar/raw/prospect), via Read or a Bash dump (cat, head, tail, sed -n, less, pdftotext, strings, python/awk one-liners). Rereads do not count |
Read, Bash | note at 5, deny at 10 |
farm.sh / farm-team.sh / work-dispatch.sh --tasks with ≥5 rows near-identical to row 0 after masking paths, numbers, CIKs and accessions (similarity ≥0.8) |
Bash | deny |
A for/while/xargs loop that runs claude -p, codex exec, gemini or agy -p per item |
Bash | deny |
A model API call inside a loop (/v1/messages, Anthropic/OpenAI SDK, generateContent outside a batch flow). batches.create, batchPredictionJobs and request-JSONL writing are allowed; an Edit only trips the rule if it introduces the pattern |
Bash; Write/Edit of .py .ts .js .sh |
deny |
| A Read, Bash or Grep result over 20K tokens (chars/4) | Read, Bash, Grep | full output saved under $XDG_RUNTIME_DIR/bulk-guard/; the model sees head 6K + tail 2K |
Every threshold has an env override: BULK_GUARD_WARN_DOCS, _DENY_DOCS, _DOC_BYTES, _FANOUT_ROWS, _SIMILARITY, _TRIM_TOKENS, _HEAD_TOKENS, _TAIL_TOKENS. BULK_GUARD_OFF=1 in the user's environment disables the guard, and any command that sets it is denied. Each warn, deny and trim is appended to $XDG_RUNTIME_DIR/bulk-guard/events.jsonl, and the prompt band shows docs read N/10 · trimmed K results.
A work run keeps two records, one owner each: the approved plan at .claude/plans/<slug>.md is the
run's authority and the file work hashes in place, and .work/<run-id>/ holds the args, the
verdict JSON and the plan bytes each round actually ran under. Project auto-memory retains reusable
facts; project directories retain real inputs and deliverables.
For cross-session task persistence, set CLAUDE_CODE_TASK_LIST_ID in .envrc:
export CLAUDE_CODE_TASK_LIST_ID="my-project"workflows/
├── .claude-plugin/ # Plugin manifest
│ ├── plugin.json # Version and metadata
│ └── marketplace.json # Marketplace listing
├── agents/ # Plugin-scoped subagents (auto-discovered)
├── user-agents/ # User-scoped subagents (symlinked into ~/.claude/agents/)
├── skills/ # User-facing and internal skills
│ ├── work/ # The spine: workflow.js, plan-lint, dispatch, gate
│ ├── dev/, ds/, writing/, workshop/, workflow-creator/ # Domain workflows
│ ├── farm-out/ # The dispatcher the `work` skill farms agents out through
│ ├── docx, pdf, pptx, xlsx # Document formats (symlinks)
│ └── ... # Internal phases and auto-invoked skills
├── bin/ # Optional dependency installer
├── docs/ # Architecture and investigation records
├── hooks/ # Hook scripts
│ ├── hooks.json # Hook configuration
│ └── *.ts # Hook implementations run with Bun
├── references/ # Shared constraint and reference docs
├── scripts/ # Compilers, checks, renderers, and support tools
├── tests/ # Contract and regression tests
├── workflows/ # Shared and domain workflow runners
│ ├── lib/ # Runner libraries and task contracts
│ └── templates/ # Dynamic workflow templates
├── external/
│ └── anthropic-skills/ # Git submodule for document skills
└── PHILOSOPHY.md # Workflow design philosophy
Key Points:
skills/contains both user-facing and internal phase skills (auto-discovered; internal skills useuser-invocable: false)agents/contains plugin-scoped subagents, auto-discovered by Claude Code asworkflows:<name>user-agents/contains user-scoped subagents; they reach Claude Code only through the symlink into~/.claude/agents/that~/dotfiles/scripts/setup-claude-symlinks.shcreateshooks/contains TypeScript hook entry points called directly byhooks.jsonworkflows/contains the shared runner plus writing, workshop, and workflow-creator adaptersscripts/contains deterministic compilers, validation checks, renderers, and support toolsreferences/contains shared constraint and enforcement docs
The office format skills come from Anthropic's official skills repo. To update:
git submodule update --remote external/anthropic-skillsThis project was heavily inspired by obra/superpowers, particularly:
- The SessionStart hook pattern for injecting meta-skills
- The "using-skills" approach that teaches HOW to use skills rather than listing WHAT skills exist
- The philosophy that skills should be invoked on-demand, not dumped into every session
Office format skills (docx, pdf, pptx, xlsx) are from anthropics/skills.
MIT
Edwin Hu