Use before posting any outward-facing text an agent wrote (PR title or body, PR comment, Jira title, description, or comment, code comment or docstring) to run an independent voice pass with Codex. Trigger on "voice pass", "de-generify this", "make this sound human", "check this PR body". Returns a rewrite plus what changed and why; never posts, edits, or commits on its own.
Recursos
2Instal·la
npx skillscat add taloncjones/dotfiles/voice Instal·la des del registre de SkillsCat.
Voice (independent prose pass)
This skill sends the text to a fresh Codex session (gpt-6-astra) with the
shared style rules and shows the before/after for a human to approve. It
works from Claude or Codex; an Astra author gets a separate context, which
does not provide different-model independence. The script never posts.
Usage
V="${CODEX_HOME:-$HOME/.codex}/skills/voice/scripts/voice.py"
if [ ! -f "$V" ]; then
V="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills/voice/scripts/voice.py"
fi
python3 "$V" lint --kind pr-body --file body.md # mechanical checks only, no model
python3 "$V" rewrite --kind pr-body --file body.md # Codex rewrite + report
python3 "$V" rewrite --pr 123 # title and body via gh pr view
python3 "$V" rewrite --kind code-comment --range src/x.py:40-52
printf '%s' "$TEXT" | python3 "$V" rewrite --kind jira-comment --stdinThe resolver uses the installed Codex skill when present, then the selected
Claude config directory. Both runtimes use the same script and rules. When
reading a source checkout directly, use its loaded skill directory instead.
The child preserves the caller's selected CODEX_HOME.
Kinds: pr-title, pr-body, pr-comment, jira-title, jira-description,jira-comment, code-comment. Flags: --effort high|xhigh (default high),--dry-run (print the prompt, do not call Codex), --json (array of report
objects). Exit 0 nothing to change, 1 rewrite proposed, 2 error.
Steps
- Pick the kind from the table above. For Jira fields, fetch the text via
the MCP Jira tools (getJiraIssuefor summary/description) and pipe it
in with--stdin; the script has no Jira access by design. - Run
rewrite. Show the report verbatim: diff, numbered changes with
rules, protected lines, and theApply withblock. - Ask with
AskUserQuestion: "Apply the rewrite (Recommended)" or "Keep the
original", with the after text in the preview. Do not apply without that
answer. - Apply with the printed command (
gh pr edit ..., the MCP update call,
or paste the after block). Forcode-comment, apply the line
replacements with Edit, one line at a time.
In a herdr session agh pr editapply on a PR this account authored
needs no go; print[INFO] edited PR #n body: <why>. On another
author's PR the shim refuses it: register the draft and ask
a post option startingPostplus a space and ending(draft <hash>), with no negation, hedge or dash aside (refusal words inreferences/posting.md) as the herdr skill's section 4 describes. unchanged: say so in one line and post the original.- Exit
2withinvariant violated: Codex dropped a URL, ticket key,
code span, or protected line. Do not hand-merge; re-run once, then
post the original and say the pass was skipped.
What it protects
- URLs and ticket keys always; fenced blocks for comments and bodies;
inline code spans for bodies and descriptions. - Code lines and load-bearing comments in a
--range: a comment whose
text appears elsewhere in the repo, or a docstring the repo reads via__doc__,getdoc(, or.doc, is sent asprotectedand must come
back byte-identical. The report names the evidence so you can overrule.
Call sites
Wiring is a follow-up task. Each row is one edit: before the outward
write, run rewrite --kind <k> on the text, show before/after, wait for
approval.
| call site | kind | text fed |
|---|---|---|
claude/commands/pr.md, before gh pr create |
pr-title, pr-body | the title and the heredoc body |
claude/commands/jira.md, comment |
jira-comment | the comment text |
claude/skills/ship/SKILL.md, step 4 summary and any PR comment it posts |
pr-comment | the comment body |
claude/skills/post-merge/SKILL.md, step 4 resolution comment |
jira-comment | the resolution comment |
| Herdr review-change findings summary (when posted as a PR comment) | pr-comment | the findings summary |
Jira ticket creation (/start, reconcile backfill) |
jira-title, jira-description | summary and description |
Notes
- Authors draft to
~/.claude/rules/personal/writing-style.md(style per
text kind). The rewrite prompt embeds onlyrules.md, so the pass stays
self-contained and never depends on loading that rule; editrules.md
only when the two conflict. - Runs Codex in an empty scratch dir with a read-only sandbox and no
approvals; the prompt names no tools or skills, so it cannot recurse
into a Claude shell-out. Confirm on first live use: thecodex.log
path printed on failure (or--jsonevent output) should show no
command execution. lintalone is deterministic and free; use it in a hurry.- Each
rewritekeeps its prompt, schema, Codex log, and any body file
under a$TMPDIR/voice.*directory so the printed paths stay valid
after the run. Nothing cleans them up;rm -rf "${TMPDIR:-/tmp}"/voice.*
when they pile up. - Tests:
bash claude/skills/voice/scripts/tests/voice_test.sh(fakes
replace Codex and gh; no network).