From 84d14ee6d2bf19e2d50b8c8262fdacd63a3a5d58 Mon Sep 17 00:00:00 2001 From: Amit Kotlovski Date: Thu, 14 May 2026 16:40:07 +0300 Subject: [PATCH 1/2] feat(code-habits): forbid referencing gitignored paths from shared surfaces `plans-and-investigations-location` already routed personal-process markdown to `.local//`; this adds the missing companion rule that once a path is gitignored you must not cite it from issues, PRs, commit messages, committed code/docs, skills, or any other artefact other readers will see. Two remediation paths are spelled out: promote-to- shared, or summarise-inline. Motivating case: a session referenced a `.local/plans/.md` path in a GitHub issue body, producing a dangling pointer for everyone but the author. Co-Authored-By: Claude Opus 4.7 (1M context) --- .claude-plugin/marketplace.json | 4 +-- CHANGELOG.md | 14 +++++++++ code-habits/.claude-plugin/plugin.json | 2 +- .../SKILL.md | 30 +++++++++++++++++-- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index eb3cdf4..fa22a78 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,7 +6,7 @@ }, "metadata": { "description": "Multi-plugin marketplace with GitButler CLI skill and shared core utilities for Git workflows and version control", - "version": "1.18.0", + "version": "1.19.0", "homepage": "https://github.com/amitkot/claude-code-tools", "repository": { "type": "git", @@ -159,7 +159,7 @@ "name": "code-habits", "source": "./code-habits", "description": "Small, single-rule skills that auto-trigger on common engineering moments — file placement, task completion, claim-grounding, script duplication. One habit per skill, no procedural workflows.", - "version": "0.4.0", + "version": "0.5.0", "author": { "name": "Amit Kotlovski" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index 2eb96d6..ee8fedb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.19.0] - 2026-05-14 + +### Changed + +#### Code Habits Plugin (0.5.0) +- `plans-and-investigations-location` skill: add a new "CRITICAL: never reference gitignored paths from shared surfaces" section. The original skill body covered *where* to put personal-process markdown (`.local//` vs `docs//`) but did not address the failure mode of then citing that gitignored path from a place other readers see. The new section makes the rule explicit: no references to `.local/` — or anything matched by `.gitignore`, `.git/info/exclude`, or a global gitignore — from issue bodies, PR descriptions, commit messages, committed code, committed docs, skills, or any other artefact a teammate will read. Internal session/agent surfaces (TodoWrite, live transcript) are explicitly exempted. +- Two remediation paths spelled out: promote-to-shared (move the file into a tracked location, commit, then reference the committed path) or summarise-inline (put the substance directly in the public artefact instead of linking). +- Description trigger phrase extended to mention the non-reference rule so the skill activates when the agent is about to cite a gitignored path from any shared surface. +- Motivating case: a session referenced `.local/plans/.md` in a GitHub issue body. The file existed on the author's laptop and nowhere else, so the issue pointed reviewers at a dangling path. The fix had to be inline summarisation after the fact; encoding the rule at the skill level prevents the same dangling-reference shape from happening at file-creation/reference time. + +### Technical Details +- Marketplace: 1.18.0 -> 1.19.0 +- Code Habits plugin: 0.4.0 -> 0.5.0 + ## [1.18.0] - 2026-05-13 ### Changed diff --git a/code-habits/.claude-plugin/plugin.json b/code-habits/.claude-plugin/plugin.json index f588a87..3db4d9f 100644 --- a/code-habits/.claude-plugin/plugin.json +++ b/code-habits/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "code-habits", "description": "Small, single-rule skills that auto-trigger on common engineering moments — file placement, task completion, claim-grounding, script duplication. One habit per skill, no procedural workflows.", - "version": "0.4.0", + "version": "0.5.0", "author": { "name": "Amit Kotlovski", "url": "https://github.com/amitkot" diff --git a/code-habits/skills/plans-and-investigations-location/SKILL.md b/code-habits/skills/plans-and-investigations-location/SKILL.md index 0b40e00..2729616 100644 --- a/code-habits/skills/plans-and-investigations-location/SKILL.md +++ b/code-habits/skills/plans-and-investigations-location/SKILL.md @@ -1,7 +1,7 @@ --- name: plans-and-investigations-location -description: Use when about to write an implementation plan, investigation note, design sketch, post-mortem, or any markdown capturing personal process inside a project repo — and especially when about to save under `docs/plans/`, `docs/investigations/`, or `docs/design/`. Routes personal/in-flight work to `.local//` (gitignored) and reserves `docs//` for shared, team-reviewed artefacts. -version: 0.3.0 +description: Use when about to write an implementation plan, investigation note, design sketch, post-mortem, or any markdown capturing personal process inside a project repo — and especially when about to save under `docs/plans/`, `docs/investigations/`, or `docs/design/`. Routes personal/in-flight work to `.local//` (gitignored) and reserves `docs//` for shared, team-reviewed artefacts. Also forbids referencing any gitignored path (`.local/`, `.git/info/exclude` entries, anything in `.gitignore`) from shared surfaces — issue bodies, PR descriptions, committed code, committed docs, skill files, or any other artefact other readers will see. +version: 0.5.0 --- # Plans and investigations: `.local/` first, `docs/` only when shared @@ -19,3 +19,29 @@ Default to `.local//` for plans drafted before approval, investigation not Write to `docs//` only when the user asks for a shared artefact, when promoting a reviewed plan to canonical, or for a deliverable in itself (architecture reference, runbook, post-mortem the team will read). Promote `.local/` → `docs/` as an explicit move + commit the user can see, not a quiet `git add`. `.local/` has no git history or backup — anything that becomes load-bearing (referenced across sessions, asked about by others) should graduate to `docs/`. + +## CRITICAL: never reference gitignored paths from shared surfaces + +A path that only exists in someone's local working copy is invisible to everyone else. The moment you cite `.local/plans/foo.md` (or any other gitignored path) from a place other readers will see, the reference is broken on arrival — they get a dangling pointer to a file they cannot open, cannot review, and cannot reproduce. + +**Do not reference `.local/` — or any file/dir matched by `.gitignore`, `.git/info/exclude`, or a global gitignore — from:** + +- Issue bodies or comments (GitHub, Linear, Jira, etc.) +- PR titles, descriptions, or review comments +- Commit messages +- Any file that is itself committed — source code, tests, configs, scripts, `docs/**`, `README.md`, `CHANGELOG.md` +- Skills, agents, commands, hooks, or any other plugin content shipped to other users +- Slack/email/external messages where the recipient is expected to follow the link + +This applies to **all** gitignored paths, not just `.local/`. If `git check-ignore ` returns the path, it's off-limits as a public reference. Common offenders: `.local/`, `tmp/`, `scratch/`, `node_modules/`, `.env*`, build outputs, anything under a `*.private/` glob. + +### How to apply + +- Before writing a path into a public surface, ask: would a teammate cloning this repo today see this file? If no, do not name it. +- If the content matters publicly, promote it: move the file out of `.local/` into a tracked location (`docs//`, the source tree, etc.), commit it, then reference the committed path. +- If the content is genuinely private and shouldn't graduate, summarise its conclusions inline in the public artefact instead of linking. The reader gets the substance without a dangling pointer. +- Internal session/agent notes (TodoWrite, scratch reasoning the user sees in the live transcript) are fine — those are not shared surfaces. The bar is "will another person later read this without my filesystem?" + +### Why + +A reference to a gitignored file is worse than no reference: it implies evidence exists and is reviewable when it isn't. Reviewers can't audit a plan they can't read; teammates can't reproduce an investigation whose notes live on one laptop; future-you on a different machine hits the same wall. Promoting-to-shared or summarising-inline are both fixable; a merged commit pointing at `.local/foo.md` is not. From 37af4faaea0226c6b9889ffe3da8cf97565e6ff6 Mon Sep 17 00:00:00 2001 From: Amit Kotlovski Date: Sun, 17 May 2026 10:18:07 +0300 Subject: [PATCH 2/2] refactor(code-habits): trim the no-reference-to-gitignored rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the bulleted list, surface-by-surface enumeration, and separate Why with a two-paragraph rule. The substance is the same — gitignored paths exist on one machine, so don't cite them from anywhere others will read; promote-to-shared or summarise-inline are the two fixes; TodoWrite/live transcript are exempt — but the bloat was hiding it. Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 7 ++--- .../SKILL.md | 28 +++---------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee8fedb..35577c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed #### Code Habits Plugin (0.5.0) -- `plans-and-investigations-location` skill: add a new "CRITICAL: never reference gitignored paths from shared surfaces" section. The original skill body covered *where* to put personal-process markdown (`.local//` vs `docs//`) but did not address the failure mode of then citing that gitignored path from a place other readers see. The new section makes the rule explicit: no references to `.local/` — or anything matched by `.gitignore`, `.git/info/exclude`, or a global gitignore — from issue bodies, PR descriptions, commit messages, committed code, committed docs, skills, or any other artefact a teammate will read. Internal session/agent surfaces (TodoWrite, live transcript) are explicitly exempted. -- Two remediation paths spelled out: promote-to-shared (move the file into a tracked location, commit, then reference the committed path) or summarise-inline (put the substance directly in the public artefact instead of linking). -- Description trigger phrase extended to mention the non-reference rule so the skill activates when the agent is about to cite a gitignored path from any shared surface. -- Motivating case: a session referenced `.local/plans/.md` in a GitHub issue body. The file existed on the author's laptop and nowhere else, so the issue pointed reviewers at a dangling path. The fix had to be inline summarisation after the fact; encoding the rule at the skill level prevents the same dangling-reference shape from happening at file-creation/reference time. +- `plans-and-investigations-location` skill: add a short "Never reference gitignored paths from anywhere others will read" rule. The original skill covered *where* to put personal-process markdown but not what happens when you then cite that gitignored path from an issue, PR, commit, committed file, or shipped skill — a dangling pointer for every other reader. Fix paths: promote-to-shared or summarise-inline. Internal session surfaces (TodoWrite, live transcript) are exempted. +- Description trigger phrase extended to cover the non-reference rule. +- Motivating case: a session referenced `.local/plans/.md` in a GitHub issue body, pointing reviewers at a path that only existed on the author's laptop. ### Technical Details - Marketplace: 1.18.0 -> 1.19.0 diff --git a/code-habits/skills/plans-and-investigations-location/SKILL.md b/code-habits/skills/plans-and-investigations-location/SKILL.md index 2729616..698aba6 100644 --- a/code-habits/skills/plans-and-investigations-location/SKILL.md +++ b/code-habits/skills/plans-and-investigations-location/SKILL.md @@ -1,6 +1,6 @@ --- name: plans-and-investigations-location -description: Use when about to write an implementation plan, investigation note, design sketch, post-mortem, or any markdown capturing personal process inside a project repo — and especially when about to save under `docs/plans/`, `docs/investigations/`, or `docs/design/`. Routes personal/in-flight work to `.local//` (gitignored) and reserves `docs//` for shared, team-reviewed artefacts. Also forbids referencing any gitignored path (`.local/`, `.git/info/exclude` entries, anything in `.gitignore`) from shared surfaces — issue bodies, PR descriptions, committed code, committed docs, skill files, or any other artefact other readers will see. +description: Use when about to write an implementation plan, investigation note, design sketch, post-mortem, or any markdown capturing personal process inside a project repo — and especially when about to save under `docs/plans/`, `docs/investigations/`, or `docs/design/`. Routes personal/in-flight work to `.local//` (gitignored) and reserves `docs//` for shared, team-reviewed artefacts. Also forbids referencing any gitignored path (`.local/` included) from anywhere other readers will see — issues, PRs, commits, committed files, skills. version: 0.5.0 --- @@ -20,28 +20,8 @@ Write to `docs//` only when the user asks for a shared artefact, when prom `.local/` has no git history or backup — anything that becomes load-bearing (referenced across sessions, asked about by others) should graduate to `docs/`. -## CRITICAL: never reference gitignored paths from shared surfaces +## Never reference gitignored paths from anywhere others will read -A path that only exists in someone's local working copy is invisible to everyone else. The moment you cite `.local/plans/foo.md` (or any other gitignored path) from a place other readers will see, the reference is broken on arrival — they get a dangling pointer to a file they cannot open, cannot review, and cannot reproduce. +`.local/` and any other gitignored path (anything `git check-ignore` flags) exists on one machine only. Citing it from an issue, PR, commit message, committed file, or shipped skill gives every other reader a dangling pointer. Don't do it. If the content needs to be referenced, promote it to a tracked path first; if it should stay private, summarise the substance inline instead of linking. -**Do not reference `.local/` — or any file/dir matched by `.gitignore`, `.git/info/exclude`, or a global gitignore — from:** - -- Issue bodies or comments (GitHub, Linear, Jira, etc.) -- PR titles, descriptions, or review comments -- Commit messages -- Any file that is itself committed — source code, tests, configs, scripts, `docs/**`, `README.md`, `CHANGELOG.md` -- Skills, agents, commands, hooks, or any other plugin content shipped to other users -- Slack/email/external messages where the recipient is expected to follow the link - -This applies to **all** gitignored paths, not just `.local/`. If `git check-ignore ` returns the path, it's off-limits as a public reference. Common offenders: `.local/`, `tmp/`, `scratch/`, `node_modules/`, `.env*`, build outputs, anything under a `*.private/` glob. - -### How to apply - -- Before writing a path into a public surface, ask: would a teammate cloning this repo today see this file? If no, do not name it. -- If the content matters publicly, promote it: move the file out of `.local/` into a tracked location (`docs//`, the source tree, etc.), commit it, then reference the committed path. -- If the content is genuinely private and shouldn't graduate, summarise its conclusions inline in the public artefact instead of linking. The reader gets the substance without a dangling pointer. -- Internal session/agent notes (TodoWrite, scratch reasoning the user sees in the live transcript) are fine — those are not shared surfaces. The bar is "will another person later read this without my filesystem?" - -### Why - -A reference to a gitignored file is worse than no reference: it implies evidence exists and is reviewable when it isn't. Reviewers can't audit a plan they can't read; teammates can't reproduce an investigation whose notes live on one laptop; future-you on a different machine hits the same wall. Promoting-to-shared or summarising-inline are both fixable; a merged commit pointing at `.local/foo.md` is not. +Internal session surfaces (TodoWrite, the live transcript) are fine — the bar is "will someone later read this without my filesystem?"