From cdf1c55c5f4a07a80a1d6c0cee5adea8b64a3ecb Mon Sep 17 00:00:00 2001 From: typebasedio Date: Wed, 22 Apr 2026 19:52:24 -0400 Subject: [PATCH] docs(v0.5): describe workspace root vs project subdir in project CLAUDE.md Rewrites the built-in project CLAUDE.md template with a new Workspace Structure section that explains the root-vs-subdir split. File Placement rules refer to the subdirectory. Git section keeps the single-repo rule and explicitly names the project subdirectory as an example of where not to init. Co-Authored-By: Claude Opus 4.7 (1M context) --- internal/seed/templates.go | 36 ++++++++++++++++++++++++--------- internal/seed/templates_test.go | 15 ++++++++++++++ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/internal/seed/templates.go b/internal/seed/templates.go index 7e61437..a65e1ed 100644 --- a/internal/seed/templates.go +++ b/internal/seed/templates.go @@ -45,28 +45,44 @@ func ClaudeMDProject() string { This is a ctask project workspace -- a long-lived working environment, not a disposable task. +## Workspace Structure + +This is a ctask project workspace. The workspace root contains ctask management +files. Your project code lives in the project subdirectory. + +- Workspace root: ctask metadata, session logs, notes, reference material +- Project subdirectory: source code, project CLAUDE.md, project configuration +- ` + "`context/`" + `: reference material and imported specs (workspace level) +- ` + "`output/`" + `: deliverables and exports (workspace level) +- ` + "`logs/`" + `: session logs (managed by ctask) + +When working on project code, operate inside the project subdirectory. +Place project-specific CLAUDE.md, documentation, and configuration there. + ## File Placement -- Source code -> ` + "`src/`" + ` or workspace root -- Documentation -> ` + "`docs/`" + ` -- Deliverables and exports -> ` + "`output/`" + ` -- Reference material -> ` + "`context/`" + ` -- Tests -> ` + "`tests/`" + ` -- Configuration files -> workspace root +- Source code -> ` + "`src/`" + ` (inside the project subdirectory) +- Documentation -> ` + "`docs/`" + ` (workspace level for general notes, project subdir for project docs) +- Deliverables and exports -> ` + "`output/`" + ` (workspace level) +- Reference material -> ` + "`context/`" + ` (workspace level) +- Tests -> ` + "`tests/`" + ` (inside the project subdirectory) +- Configuration files -> inside the project subdirectory - Do not place non-code outputs in the workspace root ## Conventions - This project uses git. Commit meaningful changes with clear messages. - Do not install global packages or modify system files unless asked. -- Record important assumptions and actions in notes.md. +- Record important assumptions and actions in notes.md (workspace level). - Keep the workspace root clean. ## Git -This workspace uses a single git repository at the workspace root. -Do not initialize additional git repositories inside subdirectories. -All project code, even if nested in a subdirectory, is tracked by the root repo. +This workspace uses a single git repository initialized at the workspace root. +The project subdirectory and all its contents are tracked by this root repo. +Do not initialize additional git repositories inside the project subdirectory +or any other subdirectory. If you need to check git status or make commits, +the repo root is the workspace root. ## Session Handoff diff --git a/internal/seed/templates_test.go b/internal/seed/templates_test.go index 73b9048..50c04af 100644 --- a/internal/seed/templates_test.go +++ b/internal/seed/templates_test.go @@ -74,6 +74,21 @@ func TestClaudeMDProjectContainsNestedGitRule(t *testing.T) { } } +func TestClaudeMDProjectDescribesWorkspaceStructure(t *testing.T) { + body := ClaudeMDProject() + for _, must := range []string{ + "## Workspace Structure", + "Workspace root: ctask metadata", + "Project subdirectory", + "project CLAUDE.md", + "operate inside the project subdirectory", + } { + if !strings.Contains(body, must) { + t.Errorf("project CLAUDE.md missing marker %q", must) + } + } +} + func TestNotesMDIsASCII(t *testing.T) { content := NotesMD("test title") for i, b := range []byte(content) {