Skip to content

feat(configurable-plans-dir): make the plans directory configurable via .claude/hcf.json - #1

Open
michielgerritsen wants to merge 1 commit into
markshust:mainfrom
controlaltdelete-nl:feature/configurable-plans-dir
Open

feat(configurable-plans-dir): make the plans directory configurable via .claude/hcf.json#1
michielgerritsen wants to merge 1 commit into
markshust:mainfrom
controlaltdelete-nl:feature/configurable-plans-dir

Conversation

@michielgerritsen

Copy link
Copy Markdown

This PR makes the plans directory configurable. I personally don't want to tie the plans to the .claude directory: for me it makes more sense to place the plans directory directly in the root of the project, or maybe in a docs/plans folder for other projects.

This PR introduces an optional .claude/hcf.json config file with a single plansDir key:

{
  "plansDir": "docs/plans"
}

This is an advanced option. Regular users should never have to think about it: no skill creates the file, project-setup never asks about it, and when the file or key is absent everything behaves exactly as it does today (.claude/plans).

How it works

  • plan-create and plan-orchestrate resolve the plans directory once at startup with a shared resolution snippet. A missing file, invalid JSON, or missing key all silently fall back to the default.
  • plansDir must be a relative path inside the repo. Absolute paths and .. segments are rejected and fall back to .claude/plans.
  • Subagents stay config-unaware. The orchestrator passes each tdd-worker its concrete task file path under a ## Task File Path heading, and plan-create passes the plan directory to post-plan agents under a ## Plan Directory heading. devils-advocate no longer hardcodes its findings path. Both agents keep a documented fallback for direct manual invocation.
  • project-setup documents the file as user-owned and hands-off; the interactive flow is unchanged.
  • project-update validates an existing hcf.json: it warns when plansDir escapes the repo, points to a directory that doesn't exist, or when .claude/plans still contains plan folders after a move. Report-only, it never auto-fixes.
  • README gains an "Advanced Configuration" section documenting all of the above.

Notes

  • Changing plansDir on a project with existing plans means moving the plan folders manually; HCF does not migrate them.
  • Minor version bump per the versioning policy; CHANGELOG entry added under [Unreleased].

…ia .claude/hcf.json

Optional advanced config: a plansDir key in .claude/hcf.json overrides
where HCF stores plans (default .claude/plans). No skill creates the
file, project-setup never asks about it, and absolute or repo-escaping
paths fall back to the default. Skills resolve the path once and pass
concrete paths to subagents; tdd-worker and devils-advocate never read
the config themselves.
@markshust

Copy link
Copy Markdown
Owner

First — apologies for the six-week silence. That's on me, and this deserved a response much sooner.

The design here is careful. Opt-in, defaults untouched, no skill creating the file, and the decision to keep subagents config-unaware — concrete paths under ## Plan Directory / ## Task File Path, documented fallbacks, and tdd-worker explicitly told never to read hcf.json — is better than what I'd have reached for. That part should survive as-is.

This is a feature I want. Two things have moved underneath it since June:

2.0.0 replaced pipeline.md with frontmatter enrollment. Your plan-create changes still reference the <pipeline> context block, which no longer exists. The textual conflicts are small — 4 blocks, one per file — but the surrounding rewrite isn't.

2.1.0 added drift detection. plan-create now writes a .hook-fingerprint into the plan directory and plan-orchestrate reads it back on every hook call. Both paths need to follow plansDir, or drift detection silently breaks for precisely the people who enable this.

Two changes I'd ask for beyond the rebase:

Drop the jq dependency, or make it fail loudly. Right now jq ... || echo ".claude/plans" means a missing jq silently produces the default — someone sets plansDir: docs/plans, gets .claude/plans, and nothing tells them why. That's the same failure class as #4, which I just spent a release eliminating. Current macOS does ship jq at /usr/bin/jq, but Debian/Ubuntu minimal and Alpine don't.

There's precedent to follow now: hook discovery moved out of a prose snippet into hooks/discover-hooks.sh, with a zero-dependency test suite in tests/. A hooks/resolve-plans-dir.sh would fit that shape, be testable, and could reuse the harness.

Quote the path. mkdir -p $PLANS_DIR/{plan-name} breaks on docs/my plans. Paths with spaces bit me in discovery too.

Would you like to rebase and take those on? Happy to answer questions about the 2.1.0 changes — HOOKS.md and the fingerprint contract are the relevant parts. If you'd rather hand it off, I can carry it forward with you credited as author. Either is fine by me; just say which you prefer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants