<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rulesets/.gitignore, branch main</title>
<subtitle>Claude Code skills, rules, and language bundles
</subtitle>
<id>https://git.cjennings.net/rulesets/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/rulesets/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/'/>
<updated>2026-07-27T18:15:14+00:00</updated>
<entry>
<title>fix(rules): stop shipping generic rules into every project</title>
<updated>2026-07-27T18:15:14+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-27T18:13:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=7ea1d7b1402eb68a13479f8073b84819c1d59ec8'/>
<id>urn:sha1:7ea1d7b1402eb68a13479f8073b84819c1d59ec8</id>
<content type='text'>
Generic rules install once at ~/.claude/rules/ and load in every session on the machine. The language bundles copied all twenty into each project as well, so work and .emacs.d loaded them twice. Project rules outrank user-level ones, which makes it worse than waste. A stale project copy overrides the fresh global rule until the next startup heals it, and that is what happened to work's interaction.md this morning for the hours between the commit and its next session.

I stopped install-lang copying them. sync-language-bundle now sweeps the copies earlier installs left, but only where the global rule exists to take over. A machine that hasn't run make install keeps the only copy it has. I swept 20 files each from work and .emacs.d, leaving their language rules and work's publishing overlay untouched.

I updated three existing tests that encoded the old contract. The generic-rule drift test is the interesting one: I made a drifted copy get swept rather than repaired, which is the stronger fix, because that copy outranked the global rule for as long as it existed.

I also gitignored the live session anchor. This repo tracks .ai/, so the anchor read as untracked for a whole session. git-worktree-gate reported rulesets sync-blocked, and every other project skipped its rulesets pull until wrap. The anchor is ephemeral and gets archived under a different name, so nothing needs it tracked.
</content>
</entry>
<entry>
<title>feat(mcp): add user-scope MCP install pipeline</title>
<updated>2026-05-07T04:11:15+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-07T04:11:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=07c2c5ccf288e6ecc25808784ea407821df3d433'/>
<id>urn:sha1:07c2c5ccf288e6ecc25808784ea407821df3d433</id>
<content type='text'>
I needed a single source of truth for MCP server registration so a fresh machine boots with the full set instead of being rebuilt by hand. install.py decrypts mcp/secrets.env.gpg, expands ${VAR} placeholders in mcp/servers.json, and runs claude mcp add --scope user for anything not already registered. Idempotent.

The encrypted bundle carries six values: the Google client id and secret, the Figma API key, the GCP OAuth keys JSON (base64), and the two @a-bonus/google-docs-mcp token caches (personal and work, base64). install.py writes the keys file and the two token files to the paths each package reads at startup, all mode 600.

Bundling the Google Docs tokens lets a new machine connect google-docs-personal and google-docs-work without the interactive OAuth flow. Without the cached token, the package falls back to a browser-redirect flow that Claude Code's stdio MCP loader can't drive, so it shows "Failed to connect" until the user runs the npx command manually.

Make target: install-mcp. Plaintext secrets and the decrypted keys file are gitignored.
</content>
</entry>
<entry>
<title>feat(claude): add claude config and wire it into make install</title>
<updated>2026-05-06T11:09:02+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-06T11:09:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=ce66de633129abc94df03ab5da91ba2ca2e93330'/>
<id>urn:sha1:ce66de633129abc94df03ab5da91ba2ca2e93330</id>
<content type='text'>
I moved Claude Code's user-level config into this repo so it travels with rulesets across machines instead of being machine-specific. The three pieces are settings.json, .mcp.json, and commands/refactor.md.

I extended make install, uninstall, and list to handle the new .claude/ directory. The wildcard for CLAUDE_CONFIG matches both `*.json` and `.*.json` because make's glob skips dotfiles by default. Without the dot variant, .mcp.json wouldn't get picked up.

I also added settings.local.json to .gitignore. That file is per-machine by convention and shouldn't ever land in the shared repo.
</content>
</entry>
<entry>
<title>fix(deps): use uv tool install for playwright-py; gitignore node_modules</title>
<updated>2026-04-19T20:30:20+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-04-19T20:30:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=3e4cea6709edd16a51d513dd96da91e5aad0be66'/>
<id>urn:sha1:3e4cea6709edd16a51d513dd96da91e5aad0be66</id>
<content type='text'>
Two fixes rolled up:

1. Add .gitignore with **/node_modules/, package-lock.json, Python venv /
   cache artifacts, and OS metadata. Prior make deps run produced a 603-
   file playwright-js/node_modules tree that should never be tracked.

2. Makefile deps target: install playwright-py via `uv tool install
   playwright` instead of `pip install --system`. Earlier attempts with
   pip --user, pip --system, and uv pip --system all failed on externally-
   managed Python (PEP 668 on Arch). `uv tool install` creates an isolated
   venv for the CLI, avoiding the conflict. Chromium browsers are shared
   with the JS side via ~/.cache/ms-playwright — no re-download.

   Also added uv itself to the deps target (was missing).

   Library import (`import playwright`) still requires per-project venv,
   which is the right pattern on externally-managed systems. Deps output
   mentions this explicitly.
</content>
</entry>
</feed>
