{"id":51421000,"url":"https://github.com/zmaril/housekeeping","last_synced_at":"2026-07-05T00:00:58.351Z","repository":{"id":369151260,"uuid":"1288612038","full_name":"zmaril/housekeeping","owner":"zmaril","description":"Checks that a GitHub repo is in good order","archived":false,"fork":false,"pushed_at":"2026-07-03T20:48:46.000Z","size":98,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-03T21:30:46.195Z","etag":null,"topics":["audit","ci","dependabot","github","housekeeping","repo-hygiene"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zmaril.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-03T19:23:58.000Z","updated_at":"2026-07-03T20:48:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/zmaril/housekeeping","commit_stats":null,"previous_names":["zmaril/housekeeping"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/zmaril/housekeeping","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmaril%2Fhousekeeping","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmaril%2Fhousekeeping/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmaril%2Fhousekeeping/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmaril%2Fhousekeeping/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zmaril","download_url":"https://codeload.github.com/zmaril/housekeeping/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmaril%2Fhousekeeping/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35139194,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audit","ci","dependabot","github","housekeeping","repo-hygiene"],"created_at":"2026-07-05T00:00:53.020Z","updated_at":"2026-07-05T00:00:58.325Z","avatar_url":"https://github.com/zmaril.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# housekeeping\n\n[![Powderworks Housekeeping on the GitHub Marketplace](https://img.shields.io/badge/marketplace-powderworks--housekeeping-blue?logo=github)](https://github.com/marketplace/actions/powderworks-housekeeping)\n\nChecks that a GitHub repo is in good order — branch protection, CI with tests\nand lint, no CI step masking its own failure with `continue-on-error`, a\nscheduled run so bitrot surfaces on its own, bounded job timeouts, no\nrerun-until-green test retries, a pinned (non-floating) CI toolchain, dependabot\ncoverage, secret scanning, read-only workflow tokens, lockfiles committed and in\nsync, gitignore coverage, CODEOWNERS routing review,\n[straitjacket](https://github.com/zmaril/Straitjacket) wired into CI, a README\nthat clears the floor, a reachable website, a license, sane repo metadata, and\nno stale PRs or branches. One repo at a time; run it when you\ntouch a repo.\n\nChecking is always read-only. Fixing is separate, explains itself, and asks\nbefore changing anything; file fixes land on a `housekeeping/\u003ccheck\u003e` branch\nand only push + open a PR on an explicit yes.\n\nThe defaults are my interpretation of what good code looks like, whether\nit's public or private — snobby yet configurable, in the family spirit of\n[straitjacket](https://github.com/zmaril/Straitjacket). Public repos get the\nfull audience-facing treatment; private repos soften those checks (website,\nlicense, changelog, README polish, metadata), because a repo with no audience\ndoesn't owe anyone a changelog. Engineering hygiene — CI, lockfiles,\ndependabot, secret scanning — is required either way. `.housekeeping.toml`\noverrides any of it per repo.\n\n## Install\n\n```sh\nuv tool install git+https://github.com/zmaril/housekeeping\n# or from a checkout:\nuv tool install .\n```\n\nNeeds `gh` (authenticated) and `git`. Lockfile sync checks use whichever of\n`cargo`/`bun`/`npm`/`uv`/… are installed and degrade to presence-only otherwise.\n\n### GitHub Action\n\nRun the audit in your own repo's CI — on PRs, pushes, and a weekly cron for\nthe things that rot without commits (dead links, stale PRs, settings drift):\n\n```yaml\nname: housekeeping\non:\n  push:\n    branches: [main]\n  pull_request:\n  schedule:\n    - cron: \"0 7 * * 1\"\n\njobs:\n  housekeeping:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: zmaril/housekeeping@v1\n```\n\n`v1` moves with compatible releases; pin `@v1.0.0` or a commit SHA if you'd\nrather nothing move under you. Results land in the job summary; a\nrequired-check failure fails the run.\nThe default workflow token can't read some admin-level settings\n(vulnerability alerts, secret scanning, workflow permissions) — those checks\nskip with a note rather than guessing; pass `with: token:` a fine-grained\nPAT with read-only Administration scope for full coverage. Tune or disable\nchecks with `.housekeeping.toml` in your repo root.\n\n### Fleet captain\n\nRepos audit themselves; the captain checks the auditors. A captain repo\ncarries a `housecaptain.toml` naming the fleet:\n\n```toml\nname = \"powderworks\"\n\n[[member]]\nrepo = \"zmaril/housekeeping\"\n\n[[member]]\nrepo = \"zmaril/entl\"\nnote = \"pre-release, in flux\"\n\n[policy.checks]\nconventional-commits = \"required\"\n\n[policy]\nlocked = [\"checks.stray-files\", \"stray-files.allow\"]\n```\n\nPolicy is expectation (divergence surfaced as a conflict) unless **locked**:\nmembers declare `fleet = \"owner/repo\"` in their `.housekeeping.toml`, their\nown audits fetch the manifest and enforce locked keys as law — a PR that\nsets a locked key fails its own CI, so nobody excepts themselves in the same\ndiff that adds the mess. Locking requires a top-level `captain = \"owner/repo\"`\nin the manifest; the captain flags members that don't declare their fleet.\n\n**Adoption note:** the PR that introduces locks to the manifest will have a\nred captain check, by construction. The captain reads member configs from\ntheir main branches — so members that haven't merged their `fleet = ...`\nlines yet show as conflicts, and the captain repo itself conflicts on the\nvery PR that adds its own declaration (it can't bless its own enrollment).\nMerge order: member fleet-lines first, then the manifest PR — merged red on\nthat one self-referential conflict — and the push-triggered captain run\nright after merge is the real verdict.\n\n`housekeeper captain` (or the action with `captain: housecaptain.toml`) is\nthe API-only delegation check: each member has a housekeeping workflow, it\nfires on pull_request + push + schedule, its latest default-branch run is\ngreen, and the member's `.housekeeping.toml` doesn't contradict fleet\npolicy — divergence is surfaced as a conflict for a human to reconcile,\nnever silently resolved. `housekeeper fleet` is the deep version: the full\naudit against every member from your machine, with a scoreboard. And\n`housekeeper captain --dispatch` (action input `dispatch: true`) is the\nfleet's \"now\" button: it triggers every member's self-audit immediately, so\na new check reaches everyone without waiting out the weekly crons.\n\n### Agent skill\n\nThe `tidy-up` skill audits the repo you're in, drives fixes, and does a\nREADME quality pass. Install it into Claude Code as a plugin:\n\n```\n/plugin marketplace add zmaril/housekeeping\n/plugin install housekeeping@powderworks\n```\n\nthen invoke `/housekeeping:tidy-up`. Or install it into any agent\n(Claude Code, Cursor, Copilot, …) via [skills.sh](https://www.skills.sh/):\n\n```sh\nnpx skills add zmaril/housekeeping\n```\n\nEither way, the skill offers to install the `housekeeper` CLI if it's missing.\n\n## Usage\n\n```sh\nhousekeeper check                  # repo inferred from cwd's git remote\nhousekeeper check zmaril/entl      # or named explicitly\nhousekeeper check --only lockfiles,branch-protection\nhousekeeper fix dependabot         # explain, confirm, then act\nhousekeeper report                 # re-render the last run\n```\n\n`check` exits nonzero if any required check fails, so it can gate other\nautomation. Results are saved as JSON under `~/.cache/housekeeping/results/`.\n\n## Per-repo config\n\nDrop `.housekeeping.toml` in a repo root to override defaults:\n\n```toml\n[checks]\nwebsite = \"off\"                    # required | recommended | off\n\n[website]\nurl = \"https://straitjacket.dev\"   # expected homepage\n\n[[codegen]]                        # committed generated code: CI must regen + zero-diff\nname = \"ruby bindings\"\ncommand = \"make bindgen\"\n```\n\nPrivate repos automatically soften `website` and `license` to recommended,\nand branch protection reports skip-with-note where the plan doesn't allow it.\n\n## Skills\n\n`skills/tidy-up/` is the skill source — front door for the audit, fix\ndriving, and the README judgment pass the deterministic check can't do.\nWorking on housekeeping itself? Symlink it into `~/.claude/skills/` instead\nof installing the plugin.\n\n## Design\n\nSee [notes/design.md](notes/design.md).\n\n## Contributing\n\nIssues and PRs welcome. The most useful thing you can send is a repo where\nhousekeeper judges wrongly — a check that passes when it shouldn't, fails\nwhen it shouldn't, or a skip that deserves a better note. Concrete examples\nbeat descriptions.\n\nNew checks are one module in `src/housekeeper/checks/` — see the check\ncontract in [notes/design.md](notes/design.md). House rules: checks are read-only, fixes\nexplain themselves and confirm before touching anything, and skips say why.\nPR titles follow [conventional commits](https://www.conventionalcommits.org)\n(`type(scope): summary`) — CI enforces it, and squash merges inherit the\ntitle, so main's history stays machine-readable.\n`uv run pytest` and `uv run ruff check .` before pushing; CI also runs\n[straitjacket](https://github.com/zmaril/Straitjacket) on everything,\nprose included.\n\n## License\n\n[MIT](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzmaril%2Fhousekeeping","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzmaril%2Fhousekeeping","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzmaril%2Fhousekeeping/lists"}