Turn a completed week of your AI coding sessions into an honest, git-verified, private-by-default work summary, including the figured-out-but-not-yet-shipped work your commits can't show.
honestweek is a locally-run, Claude-Code-native tool, shipped as a skill that orchestrates small zero-dependency Node scripts. It reads your AI coding session transcripts, distils a completed week into an honest shareable summary, re-derives every git-checkable claim against your real commits (or aborts), and produces a draft you review and publish yourself. It never auto-publishes.
Your commits show what shipped. Your sessions show what you figured out: the dead ends you ruled out and the work that's designed but not yet proven. honestweek surfaces that honestly, with a receipt (a pointer to its source commit or session) on every line. Distilled work items also carry a status badge (shipped / in progress / designed, not proven); automatic session-derived digest items state why they surfaced without claiming work status.
- Node ≥ 18
- The system
gitCLI on yourPATH - Zero runtime dependencies: Node built-ins plus
gitonly - Runs entirely locally. No telemetry, no network egress. The optional
previewserver binds to loopback (127.0.0.1) only.
honestweek runs locally with zero npm install. Pick whichever path you prefer.
Add this repo as a plugin marketplace, then install from inside Claude Code:
/plugin marketplace add BryceEWatson/honestweek
/plugin install honestweek@honestweek
…or from your terminal:
claude plugin marketplace add BryceEWatson/honestweek
claude plugin install honestweek@honestweekYou get /honestweek inside Claude Code, with versioned updates via /plugin marketplace update.
Clone into your personal skills directory:
git clone https://github.com/BryceEWatson/honestweek ~/.claude/skills/honestweekEither way, when you run /honestweek the skill invokes its bundled CLI by a skill-anchored absolute path (${CLAUDE_SKILL_DIR}/bin/honestweek.mjs), so the commands work from your own project directory.
Run it straight from GitHub. No install, no clone (zero dependencies, so it's quick):
npx github:BryceEWatson/honestweek --help
npx github:BryceEWatson/honestweek initOr from a clone of the repo:
# run these from the repo root
node bin/honestweek.mjs --helpOnce it's published to npm (not yet; see Releasing), npx honestweek and npm i -g honestweek will work too.
The CLI surface is nine subcommands: init, discover, prompts, digest, validate, build, harvest, preview, and mine. Every one answers --help without touching your files. The mine command (node bin/honestweek.mjs mine --help) is the separate "solved problems worth publishing" pass described under Mining solved problems. The digest command (node bin/honestweek.mjs digest --help) prepares one receipt-bearing review across prompts, ideas, techniques, decisions, reversals, and next steps for page or site output. The prompts command (node bin/honestweek.mjs prompts --help) remains the private prompt inbox and prompt-only compatibility path. The harvest command (node bin/honestweek.mjs harvest) proposes redaction-denylist candidates from the draft to a gitignored sidecar (only the count is printed; the raw nouns stay local for you to review). The preview command (node bin/honestweek.mjs preview) renders the built output as HTML and serves it on a local-only (127.0.0.1) server for you to read in your browser.
End-to-end happy path, in order. Each step names the artifact it produces.
Installed as the skill/plugin? Just run
/honestweek: Claude drives these steps for you and resolves the CLI path automatically. The rawnode bin/honestweek.mjs …commands below are for running the CLI directly from a clone of the repo (cwd = the repo root).
-
init→ writeshonestweek.config.json, inferred from your git state (yourgit config user.emailplus the nearby git repos it finds), for you to review and commit. It also dropshonestweek.config.example.jsonif one isn't present. Two confirmations gate the write; accepting the defaults yields a valid config.node bin/honestweek.mjs init
Those two confirmations need someone to answer them. In a script, in CI, or from an agent's shell nobody does, so
initexits2rather than writing a config you never approved, and tells you to accept the inferred defaults instead:node bin/honestweek.mjs init --yes
--yesleaves an existinghonestweek.config.jsonuntouched; add--forceto overwrite it. -
discover→ scans the last completed week's sessions and session-end handoffs (.claude/handoffs/*.md, forfeatured/referencerepos;displayrepos are never read) from your allowlisted repos and writes the gitignored, redactedhonestweek.draft.json. Handoffs contribute their tagged claims, reversals, and cited commits as additional, bounded material. Deterministic: no model call.node bin/honestweek.mjs discover # or: discover --week 2024-W23 -
/honestweek(the skill) → distils the draft into the human-reviewablehonestweek.items.json, with a status badge and a receipt on every item. This is the one model-judgment step; seeSKILL.mdfor the distillation contract. Forpageorsiteoutput without the opt-in goals registry, runnode bin/honestweek.mjs digest prepare. It scans the completed week from Claude Code and Codex, updates the gitignored private prompt inbox and balanced review model, and writes the public-safehonestweek.prompt-items.jsonlane. Usedigest candidatesanddigest explain <item-ref>to inspect the exact score, selection reason, privacy result, and transcript receipts. Usedigest keep,hide,delete <item-ref> --yes, or confirmeddelete --all --yesto control current items in any category, then runvalidateandbuild. Keep changes selection only and never bypasses receipt or privacy gates. Delete removes private review text and leaves a no-text tombstone so preparation cannot regenerate the item; it cannot recall an output you've already built.digest reset-tombstones <item-ref>|--week <YYYY-Www>|--all --yesis the explicit regeneration control. The balanced digest lane and the goals page are not yet compatible; use the existing distillation path when the goals registry is present.Selected next steps and cues labelled
unresolved idea: <subject>carry automatically for at most the next two reporting weeks. They must still pass the current privacy gate, automatic floor, target, and category cap.digest carry-forward <item-ref>schedules one current public-safe candidate for exactly the next digest and does not extend automatic carry. A human turn labelledpicked up: <subject>orruled out: <subject>retires one unambiguous matching carry. Every carried or renewed item discloses why it appeared and its first-seen and current week. Carry history is private, redacted, and limited to 12 week records.A lifecycle build binds the exact configured output bytes and next carry state with hashes. If an interrupted build leaves
honestweek.carry.pending.json, the nextprepare,validate, orbuildrecovers only a recognized hash combination. Usedigest recover --discard-pendingonly when the output differs and carry is still at its prior hash. Unknown states fail closed. Useprompts list,source,keep,hide, anddeletewhen you want the prompt inbox controls directly. Automatic selection discloses its floor, overall target, category caps, omitted counts, and uncertainty. Privacy edits are deterministic redactions; ambiguous or residual high-risk material stays private.prompts curateremains available when you intentionally want the prompt-only lane.Optional but recommended: gate the distilled items before building:
node bin/honestweek.mjs validate # add --no-dashes for the voice rulevalidateexits2if any item lacks a valid badge or a receipt, names adisplay-role repo or cites a commit against one, or lets a configured redaction term survive into the prose. It catches an authoring leak at the source instead of relying on build-time scrubbing. -
build→ re-derives and git-verifies every cited commit. It aborts with exit code2if any cited commit is unresolved or itsauthorEmailis not inidentity.authorEmails, writing nothing rather than emit a half-true summary. Ashippedbadge additionally requires every cited commit to have landed: reachable from the repo's default branch (origin/HEAD as recorded locally, elsemain/master, else the repo's only branch), checked offline from local refs, never a fetch. Real work still on an unmerged branch keeps its receipt and is downgraded toin progress, announced on stderr; if the repo has no determinable default branch, theshippedclaim is unverifiable and the build aborts (exit2).node bin/honestweek.mjs build
-
emit → on success,
buildrenders the final local output in the configuredoutput.mode(post/changelog/digest/report/page/site) tooutput.file. Thedigestcarries a git-derived Activity summary (commits and active days forfeatured/referencerepos;displayrepos are never git-read, so they get no metrics, and an unreadable repo gets no fabricated0).pagerenders a self-contained, interactive HTML standalone site (see below). You review it and publish it yourself. -
preview(optional) → serves the builtoutput.fileon a local-only127.0.0.1server, then opens your browser. A Markdown output is converted to a locked-down HTML page; thepageoutput is already HTML and is served verbatim (with its inline interactivity). It is a viewer: it reads the filebuildwrote, publishes nothing, and needs no internet. Press Ctrl+C to stop.node bin/honestweek.mjs preview # add --no-open to just print the URL, or --port <n>
The weekly flow above answers "what did I ship". mine answers a different question:
did I solve a problem that a stranger is going to hit too?
Not every hard hour is worth writing up. When your own code breaks and you fix your own code, nobody else can use that. But when a tool you did not write fails in your environment and you work out why, someone else will hit the same wall and paste the same error into a search box. That second kind is rare, it is already sitting in your session logs, and it is almost never written down.
mine finds those, ranks them, and — with --draft — writes one up.
node bin/honestweek.mjs mine # report what is undecided
node bin/honestweek.mjs mine --draft # and write the top one up as a postWhat it reads. Claude Code (~/.claude/projects), Codex (~/.codex/sessions) and
Cowork session logs. Pick with --corpus claude-code,codex,cowork. A name outside that
list is an error (exit 1), not an empty scan — a typo must never read as a quiet week.
How it decides. A session is a candidate only when all three hold:
| Requirement | Why |
|---|---|
| A quotable error from software you did not write | It is what a stranger types into a search box. Errors from your own compiler, test runner or git are excluded. |
| Diagnosis outside your working tree | Probing the machine, reading another program's install directory, or researching a third party's known behaviour. |
| Evidence it was resolved | An unresolved failure is a bug report, not a guide. |
A session that edited your repo far more than it investigated anything else is rejected however good it looks otherwise. That is ordinary work.
The ledger. Findings land in honestweek.findings.json with a status. The number
that matters is the backlog — findings you have not yet accepted or declined:
ERROR SIGNAL — backlog 3 undecided; oldest waiting 12 day(s).
"Found 3 things this run" measures the tool. The backlog measures whether anything reached a reader, and it can only fall when you decide:
node bin/honestweek.mjs mine --decide "<finding key>=published" # or =declinedDrafts are honest by construction. A draft asserts nothing about today. Its
last-verified field is emitted empty, its publication date is left blank, and it
carries a checklist where every item starts UNVERIFIED, plus a "What I could not
check" section. Two things a session log can never establish are always listed there:
whether anyone actually searches for this, and whether the fix still works on the
current build. mine never publishes anything.
When it is blind, it says so. Every run reports files found per corpus and the
retention floor — the oldest session still on disk, since agents delete old logs. If a
corpus resolves to a real directory holding zero logs, mine exits 2: a zero from
a blind sensor is not evidence of a quiet week.
Configure the destination under mine in your config (all optional):
{
"mine": {
"ledger": "honestweek.findings.json",
"ownRepos": ["you/your-repo"],
"publishedErrorStrings": ["an error you already wrote about"],
"draft": {
"dir": "src/content/blog",
"frontmatter": { "title": "", "description": "", "date": "", "tags": [], "lastVerified": "" }
}
}
}draft.frontmatter is your destination's schema, not honestweek's: keys it recognises
are filled in, keys it does not are passed through empty for you. ownRepos stops
issues on your own repositories counting as evidence that someone else's software broke.
See docs/mining.md for the detector's signals, what is measured
versus guessed at, and how the score bar was calibrated.
A short, fabricated (clean-room) example. The distilled honestweek.items.json:
Rendered to the default digest output. Every line carries a status badge and a receipt:
# Weekly digest — 2024-06-10 to 2024-06-16
## Shipped
- **shipped** — Auth redirect now keeps the session cookie across the login bounce. _(your-project)_ (`9f8e7d6`)
## Designed, not proven
- **designed, not proven** — Retry queue for failed webhook deliveries — designed, not yet wired in. _(your-project)_ (`a1b2c3d4`)Set "output": { "mode": "page" } and build writes one self-contained, interactive
HTML file (honestweek.report.html by default) — a polished standalone site with a
git-derived commits/day chart, collapsible per-project cards with metrics, status-badged
items, and an expandable git receipt on each. No target project, no framework, no build
step, and zero external resources (inline CSS + JS, system fonts), so it opens
anywhere and preview can serve it under a no-egress CSP:
node bin/honestweek.mjs build # writes honestweek.report.html
node bin/honestweek.mjs preview # serves it on 127.0.0.1 + opens your browserSame honesty engine as every other mode: every cited commit is verify-or-abort'd, every
number on the page is a deterministic honestweek derivation (git for commits + the chart),
and curated prose is HTML-escaped. A per-project card's active-days is
max(commit-active days, session-active days, entry-active days), so a display-role /
session-only project shows the days it genuinely had interactive sessions (counted from your
local session logs, never authored) instead of a blank. A card's header can never report fewer
active days than the dated rows shown beneath it, even when a session ran from one project's
directory but was curated as another's work by content. In site mode the same reconciliation
keeps the header's "sessions this week" from falling below that active-day span (a session
happens on one day, so N active days mean at least N sessions); for a cross-cwd generalized
project that reconciled figure is a lower bound on its distinct session-days, not a raw
session-log tally. Every figure is a deterministic count, never authored. (To
instead generate INTO an existing website's data
file — the integrated path — use site mode with a committed output.adapter; see
docs/site-integration.md.)
Drop a honestweek.objectives.json registry beside your config and page mode becomes
multi-page: it emits a second self-contained page, goals.html, next to report.html
and cross-links the two. The goals page groups your verified work by goal instead of by
project — goal cards with a kind chip, a what / why / how, a per-week activity strip, status
counts, and an expandable list of the entries behind each goal. With no registry, page
mode stays single-page exactly as above (the goals page is purely additive).
The registry is the publish gate: only goals listed in it appear, and a work item that maps to no goal is omitted. It's validated fail-closed before anything is written (an invalid or leaky registry aborts the whole build, writing neither page).
// honestweek.objectives.json (opt-in; absent -> single-page)
{
"schemaVersion": 1,
"groups": ["open source", "this site"], // area sections, in this order
"groupDescriptions": { // optional per-area what/why intro
"open source": { "teaser": "Tooling, in the open.", "what": "...", "why": "..." }
},
"objectives": {
"ship-the-tool": { // any anchor-safe id
"publicLabel": "Ship the tool as an open engine",
"publicGroup": "open source", // must be one of groups
"kind": "continuous", // optional: "continuous" | "finite"
"what": "...", "why": "...", "how": "...", // optional card body
"howType": "sessions" // optional: "sessions" | "mined" | "planned"
}
},
"projectToObjective": { "your-project": "ship-the-tool" }, // repo label -> goal id
"page": { "title": "My goals", "lede": "..." } // optional page copy overrides
}A work item resolves to a goal by its own objectiveId (if set and in the registry), else by
projectToObjective[<its repo label>]. Cross-week goal activity aggregates the current week
plus any weeks in your local output.archive (so a first run shows one week, richer as weeks
accrue). An optional honestweek.goal-changelog.json adds a "what changed" band for
structural goal-set changes (a goal added / split / retired / relabeled / merged).
preview serves both pages (so the cross-links resolve), still loopback-only under the
same no-external-egress CSP:
node bin/honestweek.mjs build # writes report.html + goals.html (when the registry is present)
node bin/honestweek.mjs preview # serves both at 127.0.0.1 (/ and /goals.html)You commit your own honestweek.config.json. It mirrors honestweek.config.example.json:
{
"identity": { "authorEmails": ["you@example.com"] }, // required, non-empty; the commit-authorship allowlist
"week": { "startsOn": "monday", "timezone": "UTC" }, // optional; startsOn is "monday" for v0.1; timezone is an IANA zone (defaults to the host zone)
"repos": [ // required, non-empty
{ "path": "/path/to/your/repo", "label": "your-project", "role": "featured" },
{ "path": "~/code/a-repo-you-contribute-to", "label": "a-shared-repo", "role": "reference" },
{ "path": "~/code/a-client-repo", "label": "a-private-project", "role": "display" }
],
"redaction": { "codenames": [], "names": [], "terms": [] }, // optional; default-empty private term-lists, scrubbed case-insensitively
"curation": { "maxItems": 12, "automaticMinScore": 2, "retentionWeeks": 12, "automaticCarryWeeks": 2, "categoryCaps": { "prompts": 2, "ideas": 2, "techniques": 3, "decisions": 2, "reversals": 1, "nextSteps": 2 } }, // disclosed digest target, floor, bounded carry, and category caps
"privacy": { "publicRenditions": { "enabled": true, "maxAutomaticChangedPercent": 20, "generalizationMappings": {}, "neverPublicTerms": [] } }, // deterministic public-rendition gate
"output": { "mode": "digest", "file": "honestweek.digest.md" }, // optional; mode ∈ post|changelog|digest|report|page|site, default digest
"voice": { "denyMeta": false } // optional; OFF by default. true = lint authored prose for withholding/honesty-meta (see below)
}| Field | Meaning |
|---|---|
identity.authorEmails |
The emails a commit must be authored by to count as yours. build aborts on any cited commit not authored by one of these. |
week.startsOn |
"monday" (the only supported value in v0.1). |
week.timezone |
IANA timezone used to compute the week boundary; defaults to your host zone. |
repos[].path |
A repo path. ~/~/ expands to your home dir; relative paths resolve against the config file. Sessions are attributed to this repo from any working tree of the same git repository — the path itself, sub-directories, and every git worktree, including ones checked out at a sibling path rather than inside it. Git reads (commits, handoffs, metrics) always use this path alone, so a worktree's branch or detached HEAD never becomes the basis for your commit counts. A separate clone has its own git database and is never attributed here. |
repos[].label |
The short name items reference and outputs display. |
repos[].role |
One of the three trust levels below. |
redaction.codenames / names / terms |
Private tokens scrubbed from all output. Default empty (clean-room). |
curation.* |
Local weekly-selection policy. Defaults target 12 items with caps of 2 prompts, 2 ideas, 3 techniques, 2 decisions, 1 reversal, and 2 next steps. The automatic floor is 2. automaticCarryWeeks defaults to 2 and is hard-limited to 2. retentionWeeks defaults to 12 and is hard-limited to 12. Explicit keeps and one-week renewals are never silently dropped, but they never bypass receipt or privacy gates. |
privacy.publicRenditions.* |
Public-rendition gate. enabled defaults true for the local artifact, maxAutomaticChangedPercent defaults to and cannot exceed 20, and neverPublicTerms extends hard redaction. generalizationMappings remains empty in this slice. Ambiguous or residual high-risk material in every category stays private. |
output.mode |
post (build-in-public update), changelog (in-repo CHANGELOG.md section), digest (the private, local-only weekly file; the default and trust anchor), report (grouped by project, each headed by its git-derived metrics; the structured weekly-work-log shape, still a local file you publish yourself), or site (integrate the verified report into a target website's data artifact via a committed adapter — advanced; see docs/site-integration.md). |
output.file |
Where the output is written. Defaults per mode when unset. (Not used by site, whose write path comes from the adapter.) |
output.adapter |
Required for site mode only: path to the committed adapter (resolved like a repo path) — a .json static field-map, or a .mjs transform (transform(model, ctx)) for artifacts needing grouping/sorting/joins. It maps the verified model onto the site's data artifact; the artifact's own write path lives in the adapter. |
output.redact |
Default true (honestweek scrubs every byte). For site mode only, false delegates string redaction to the committed transform (so a target with its own redactor gets exact placeholder parity) — permitted only with a transform adapter; verify-or-abort and the numeric fact-fence always run. See docs/site-integration.md. |
output.archive / output.archiveDir |
Opt-in local weekly archive. With archive: true, build also snapshots each week to <archiveDir>/<weekStart>.json and maintains <archiveDir>/index.json (the "/log" series; default dir honestweek.archive). Local files only, never pushed. |
voice.denyMeta |
Opt-in authored-prose honesty lint, OFF by default. When true, build aborts (exit 2, writes nothing) if an authored-prose field (item title/summary/text, or curated content/projects prose) narrates its own withholding ("keeping the specifics sealed", "kept generic here", "not public-facing") or announces the page's own honesty ("show the work honestly, receipts and retractions included", "belongs in an honest log"). That's what an honest log should show through its badges and receipts, not say about itself. It's the prose analogue of the numeric fact-fence, names each offending field plus matched phrase plus rule, and is never applied to verified evidence snippets/receipts (where a word like "sealed" can legitimately appear); conversely, keep authored prose out of evidence-named keys (commits, receipt, snippet, ...), which are treated as evidence and skipped. Absent, nothing changes. |
voice.denyPhrases / voice.allowPhrases |
Optional string lists (default empty). denyPhrases extends the built-in denylist with your own phrases (literal, case-insensitive). allowPhrases is the false-positive off-ramp: it exempts a legitimate phrase a built-in pattern would otherwise flag (surgical to the matched text), so one over-eager match doesn't force you to disable the whole lint. |
Repo roles:
featured: git-read and git-verified, and headlined in the output.reference: git-read but not headlined.display: summarized generically and NEVER git-read. Use it for repos you want acknowledged without reading their commits.
| File | Status |
|---|---|
honestweek.draft.json |
The redacted weekly digest from discover. Gitignored. An intermediate working artifact, never published. |
honestweek.prompts.json |
The private, redacted Claude Code and Codex prompt inbox plus no-text deletion tombstones. Gitignored. Never read by a renderer. |
honestweek.curated.json |
The private, redacted six-category review model from digest prepare. Gitignored. It contains exact selection and privacy decisions. A deleted current-week item leaves only a no-text tombstone. |
honestweek.digest.pending.json |
A no-text transaction marker used only to recover an interrupted digest prepare. Gitignored. Other commands fail closed while it exists. |
honestweek.prompt-items.json |
The public-safe lane. Version 1 is prompt-only; version 2 is the balanced digest. Gitignored. validate and build reconstruct it from local sources before use. |
honestweek.carry.json |
The private, redacted carry history, bounded to 12 week records. Gitignored. Only a successful lifecycle build advances it. |
honestweek.carry.pending.json |
The hash-bound output/carry recovery envelope for an interrupted lifecycle build. Gitignored. Unknown output and carry combinations fail closed. |
honestweek.items.json |
The distilled, human-reviewable items. Yours to keep or ignore (gitignored by default; safe to delete). |
honestweek.harvest.json |
Proposed redaction-denylist candidates from harvest. Gitignored. Only the count is printed; the raw nouns stay local for you to review. |
output.file (e.g. honestweek.digest.md) |
The final rendered output. Yours to keep or ignore. |
honestweek.config.json |
Your config. Gitignored by default (it can hold private repo paths/terms); un-ignore it if you want it tracked. |
honestweek.archive/ (opt-in) |
The local weekly snapshots + index.json (the "/log" series). Only written when output.archive is true. Yours to keep, ignore, or commit. |
honestweek.objectives.json (opt-in) |
The goal registry that turns page mode multi-page (emits goals.html). Absent → single-page. The publish gate for goals; commit it if you want the goals page. |
honestweek.goal-changelog.json (opt-in) |
Optional append-only log of structural goal-set changes, rendered as the goals page's "what changed" band. |
honestweek.findings.json (opt-in) |
The mine findings ledger: what was found, and what you accepted or declined. Commit it — it is the only record of what you already said no to, and everything in it is de-identified and redacted before it is written. |
- Only your own allowlisted repos are read. Nothing outside your
reposlist is ever touched. display-role repos are summarized generically and NEVER git-read. There is no code path that runsgitagainst adisplayrepo.- Output stays local until you publish it. honestweek writes local files only.
- No telemetry, no network egress. The optional
previewserver is loopback-only (127.0.0.1): it serves your already-built output to your own browser, and nothing leaves your machine. - Nothing is auto-published. honestweek produces a draft; you are the publisher.
Redaction is pattern-based and deliberately over-redacts when a pattern is ambiguous. It reliably removes email addresses, home and user paths (including ~/…), prefixed API keys and JWTs, KEY=VALUE secrets under a sensitive key name, high-entropy tokens of 32+ characters, UUIDs, bare 9+ digit runs, currency amounts, and every term you list under redaction.
It is a safety net, not a guarantee. Known gaps, so you can decide rather than assume:
- Short, low-entropy secrets. A hand-picked password under 32 characters with no
KEY=prefix (password: hunter2, YAML- or JSON-stylekey: value) is indistinguishable from prose and survives. TheKEY=VALUErule keys on=, not:. - Unlisted spellings of a listed term. Adding
AcmeCorpdoes not coverAcme Corp,Acme-Corp, orDoe, JaneforJane Doe. List the variants you care about;harvestproposes candidates from your own draft. - Structured personal data. Phone numbers, SSNs, and space- or hyphen-separated card numbers are not matched. Only unbroken 9+ digit runs are.
- UNC paths.
\\server\Users\you\…is not matched; drive-letter and POSIX forms are.
Read the built output before you publish it. That review is part of the design, not a formality, and preview exists to make it easy.
honestweek's two non-negotiable promises:
- A receipt on every line. Every emitted item points to its source: a commit SHA or a session turn. An item that reaches the renderer without a receipt is a build error, not a receipt-less line.
- It never asserts a motive the log does not contain. honestweek defaults to under-claiming: verified/measured work that has landed on the repo's default branch reads as
shipped; real work still on an unmerged branch reads asin progress; anything weaker reads asdesigned, not proven. It never narrates intent the transcript doesn't support.
honestweek is publish-ready but not yet on npm. To cut a release so npx honestweek / npm i -g honestweek work:
- Bump the version in
package.json(and.claude-plugin/plugin.jsonto match), commit, and tag:git tag v0.1.0 && git push --tags. - Add the
NPM_TOKENrepository secret first (an npm automation token). Do this before step 3, not after. The release workflow triggers on a Release being published, and publishing a GitHub Release is not reversible in any quiet way: without the token the workflow reachesnpm publishand fails on authentication, leaving a public Release announcing a version that is not on npm. Confirm withgh secret listthatNPM_TOKENis listed. - Automated: publish a GitHub Release for the tag. The
releaseworkflow runs the tests andnpm publish --provenance --access public. Manual alternative:npm publish --access publicfrom a clean checkout afternpm login. - The
filesallowlist inpackage.jsoncontrols what ships to npm (bin/,lib/,SKILL.md, the example config, the plugin manifests). Tests and fixtures are excluded.
Publishing to npm and cutting a GitHub Release are the only steps that go public; everything else in this repo is local.
honestweek reads regular JSONL files under $CODEX_HOME/sessions and $CODEX_HOME/archived_sessions, excluding subagents. It does not read history.jsonl, plaintext logs, or other app state. A Voice or dictated turn is ingested only when Codex records its transcript as a standard event_msg / user_message string in those directories. The audio, local_audio, image, reasoning, tool-output, and other non-message fields are never retained as prompt text. A paired shell record sets only the observed-verification boolean when it contains one literal recognized test or commit command, an explicit zero exit, and matching positive evidence. Current Codex exec wrappers qualify only in a closed form that forwards the unchanged shell result; they are parsed without evaluation, and their source and output text are discarded. Raw session ids and working paths become hashes or private attribution; the redacted prompt, privacy audit, timestamp, source, turn, and receipt hashes remain in the current gitignored review store. Raw transcript retention remains Codex's responsibility and is not changed by honestweek.
A valid Codex session record does not need a final assistant message. Its public-safe human prompt can contribute to cross-session lexical recurrence and automatic draft selection, but it cannot supply assistant-final cues or observed verification unless those records exist. A missing, unconfigured, or display-role working directory makes the turn private. Private or hidden turns cannot supply recurrence evidence or enter automatic output. An ambiguous or high-risk human prompt is withheld from prompt recurrence and prompt output. A labelled cue in that human prompt retains the prompt receipt and conservative prompt audit; an assistant-final cue is gated separately on its own redacted rendition and exact receipt. A malformed record or missing Codex session identity makes that source unreadable and preserves the prior store. The private prompt store is regenerated for the completed week. Its no-text deletion tombstones persist until explicit reset, and redacted lifecycle carry persists only within the limits described above.
{ "week": { "start": "2024-06-10", "end": "2024-06-16" }, "items": [ { "text": "Auth redirect now keeps the session cookie across the login bounce.", "repo": "your-project", "status": "shipped", "receipt": { "sessionId": "a1b2c3d4", "primaryCommit": "9f8e7d6" } }, { "text": "Retry queue for failed webhook deliveries — designed, not yet wired in.", "repo": "your-project", "status": "designed, not proven", "receipt": { "sessionId": "a1b2c3d4" } } ] }