Setup project
Registering a project is a per-project act with a per-project lifetime.
setup-user is a per-person act, run once. Keeping them in one skill meant
every new repository cost a full personal-setup run, which is what this skill
exists to end.
Slash-only on purpose. It writes daikenja.yaml, and its seeding step can
propose dozens of ledger entries. Nothing about "set this up" should make that
fire on its own -- the user runs /daikenja:setup-project when they mean to.
disable-model-invocation: true is set for that reason.
This skill never writes ledger content. Seeding derives candidate entries
and hands them to /daikenja:project-log, which shows the exact lines and waits
for approval. project-log remains the only writer of a ledger, per
docs/config-writers.md § Who writes what.
Step 0: the preconditions
Read ~/.claude/daikenja/daikenja.yaml. Three outcomes and no others:
It does not exist. Stop. Say so and name the skill that creates it:
Daikenja is not configured yet -- there is no ~/.claude/daikenja/daikenja.yaml. Run /daikenja:setup-user first. Nothing was written.It exists but does not parse. Stop. Name the first line that does not parse. Never guess the intent and never rewrite a file you cannot parse -- the same rule every Daikenja skill follows.
It exists but
profile.nameis unset or empty. Stop. The configuration is incomplete, andsetup-useris what completes it. Say so and name it.
On a file that exists and parses, also check the version marker and emit the
one-line notice if it applies, per docs/config-versioning.md § Version marker
and upgrades. It never blocks registration. This skill does not migrate and
does not write daikenja_version, even though it writes to the same file --
the upgrade branch lives in setup-user and stays there.
This skill never captures profile data. If the user offers a name, role or tone
here, record nothing and point at /daikenja:setup-user.
There is no environment gate in this skill. setup-user ran Step 0 already, and
its config file could not exist otherwise.
Step 1: read what already exists
Before proposing anything:
- The current directory's normalized path -- forward slashes, no trailing
slash, compared case-insensitively, per
docs/config-resolution.md§ Finding the project. - Every path of every
projects:entry -- itspathslist, or itspathscalar read as a one-element list -- normalized the same way, and whether any is an exact match for this directory. - Whether a ledger already exists on disk at the resolved path -- the matched
project's
ledger:key, otherwise.daikenja/ledger.mdunder the project root, which is the first path in the entry. This decides whether Step 4 is a first seed or a top-up, and it is read-only here.
A ledger on disk with no matching projects: entry is a normal state, not
an error. The file on disk is the fact and the config is the index. Register the
project and leave the ledger exactly as it is.
Step 2: register the project
An exact path match already exists, on any path of any entry. Say which key it is registered under and leave the entry alone. Registration is idempotent, and it is not a place to silently change a key someone chose. Go to Step 3 -- an already-registered project can still want its keys set or its ledger seeded.
No match. Ask one question before proposing anything, because there are now two answers and only the user knows which one is meant:
Is this a new project, or another directory of one you already track? Registered: <key>, <key>, <key>.A new project. Propose a new entry, key defaulting to the directory's own name, and ask if the user wants a different label. The key is a human label and is never matched against a directory, so it may be anything that reads well -- but it is what a read skill accepts as an argument, so short and typeable beats decorative:
<dir-name>: paths: - <normalized absolute path>Another directory of an existing project. Append this path to that entry's
paths, and change nothing else. Appending never reorders the list: the first path is the project root and therefore where the ledger lives, so moving it would silently repoint the ledger at a different file. Say which directory stays the root.An entry written in the single-value
path:form is converted to a two-elementpaths:list, with the existing value first. Say so in the proposal -- it is the same project resolving the same way, but the file now looks different from how the user left it.
Registering a project with no directory at all is a legal, and asked-for,
outcome. A programme that spans a wiki, a tracker and a chat space has no
folder to register. Write the entry with paths: [] when the user says the
project has no directory, and never invent a path to fill the gap.
Such an entry needs an absolute ledger: in the same write, and it is not
optional here. With no root there is nothing for a relative pointer to
resolve against, so a pathless entry without one resolves as a project and then
fails the moment anything asks for its ledger. Propose the convention from
docs/config-resolution.md § Resolving ledger --
~/.claude/daikenja/ledgers/<project-key>.md -- as part of the same entry:
<key>:
paths: []
ledger: <home>/.claude/daikenja/ledgers/<key>.md
Say what the pair buys: reachable by name from anywhere, with its record kept
outside any repository. Step 3's ledger question is then already answered and
is not asked again.
A prefix match that is not exact is a nested project. The current directory sits inside a registered one. Say which project it resolves to today and ask before registering a second entry -- resolution takes the longest matching prefix, so a new inner entry silently takes over every skill run in this subtree. That is sometimes exactly what the user wants and is never something to assume. Adding this directory to the outer project instead is the other answer, and it is often the one meant.
Add the entry with the Edit tool, under projects:. Never rewrite the file.
Hand-added keys, other projects and the template's comments all survive an edit
and none of them survive a regeneration.
Step 3: offer the per-project keys
setup-user left these unset because it had no idea what the project was. This
skill does, so it offers them once rather than leaving them to be discovered.
Ask in one short round, and take silence as "leave them all unset":
Registered. Three optional settings for this project -- skip any or all:
1. ledger -- where the ledger file lives: a path relative to the project root,
or an absolute path (useful for a project with no repository of its own --
the convention is ~/.claude/daikenja/ledgers/<project-key>.md). Default
.daikenja/ledger.md.
2. stale_after_days -- how long an open item may sit before project-gaps calls
it stale. Inherits <the profile value> if you skip it.
3. norms_doc -- your team's ways-of-working document, as a path or a URL.
Setting it turns on self-review's ROLE CHECK, which is off by default.
Every one of these is optional and every one has a defined default in
docs/config-schema.md § Field notes. Write only the keys the user
answers. A key written at its own default value is noise that reads like a
deliberate override to the next person who opens the file.
Never write last_checkpoint here. It belongs to project-catchup, which
sets it after it has actually reported a delta. Writing it at registration would
claim a report that never happened, and the first project-catchup run would
then skip everything older than the moment of registration.
State the values you are about to write and wait for a yes, then edit them into the entry from Step 2.
Step 4: offer to seed the ledger
Optional, and reachable on its own. A project registered months ago can run
/daikenja:setup-project purely to seed, and Steps 2 and 3 will both be no-ops
that say so. Offer it in one line and take no for an answer:
Want to seed the ledger from what this project already has -- a decision log,
a wiki space, a Slack channel, a README? I will propose entries and write
nothing without your approval. Otherwise we are done.
Step 4a: look for a register the project already keeps
Do this before asking for sources, not after. Many projects already keep architecture decision records, RFCs, a decision log or a numbered question register, and finding that out on the fifth exchange means several rounds of entries have already been proposed against a source that turns out to be superseded.
Look for the usual homes -- docs/adr/, docs/decisions/, docs/rfc/,
adr/, decisions/, or a file whose name says the same thing. This is a scan
of file names in the project, not a read of the repository for material.
project-log's rule against reading the repository to guess what happened is
about inventing material for an ordinary log entry; here the user has asked for
exactly this and the results are shown before anything is proposed.
When the project already keeps one, the ledger is the index and those documents are the depth. Say so plainly, because the honest first read of such a project is "you may not need Daikenja here":
This project already keeps 11 decision records in docs/adr/ and a numbered
question register. Daikenja does not replace those. What it adds is one place
that answers "what is settled, what is open, who owns it" across all of them.
Each entry would be one line pointing at the record that holds the detail.
Three rules follow, and all three have to be settled before the first write:
- Entry bodies are one line pointing at the source. No narrative, no
history, no summary of the record's reasoning. That is the same rule
project-logalready applies to every entry body -- nothing about the format changes to support this. - Carry the source identifier across. People cite
ADR-0007andQ-04in chat and in standups, and a migration that drops those references breaks every one of them. Propose entries in ascending source-identifier order so thatproject-log's sequential allocation landsADR-0007onD-007where the source numbering allows it. Where it cannot -- gaps in the source sequence, two sources feeding one section, or a ledger that already holds entries -- the body opens with the source identifier instead. Decide which before the first write. A written entry is never renumbered, so this cannot be corrected afterwards. - Do not edit the source documents. Keeping a status index in two places means they drift, and stripping the duplicate from the source is usually the right follow-up -- but it is the user's call and it is outside this skill. Say it once, as a recommendation, and touch nothing.
Step 4b: name the sources
Ask for them one category at a time, in this order, because each answer changes what is worth asking for next:
- Repositories, READMEs and design or decision documents.
- Wiki pages -- Confluence, Notion, an internal handbook.
- Chat -- a Slack channel, specific threads, an email chain.
For each source, fetch what the session's connectors can actually reach.
A source this session cannot reach is one notice line, then continue. Never hard-stop, and never make any part of this skill conditional on a connector:
No Slack connector in this session, so I cannot read #harbor-rollout. Paste the
messages you want covered, or skip it and we carry on with the rest.
Sources also become Context links, which are ledger content and therefore go
through project-log like everything else. A source the user pasted rather than
linked has no URL and is not a context link.
Step 4c: propose in tranches, through project-log
A seed run has more material than an ordinary log run, and that changes how the
proposal is shaped -- it does not change who approves it. Seeding adds no
second approval gate. project-log's contract is the gate: it shows the exact
lines, waits, and accepts partial approval.
What seeding adds is a bound on how much is put in front of the user at once. Forty-one entries in one message makes "just the first two" unusable, and a tranche the user answers around is a tranche nobody approved.
- One tranche at a time, in this order -- decisions, then open items, then
context links. Hand each to
project-log, which proposes it and waits. - Restate any outstanding proposal before opening a new one. If the previous tranche was not answered, or was answered about something else, say what is still unwritten before showing anything further. Silence is not approval, and neither is the user replying about something else.
- Split a long tranche by source, not by count. "The eleven decision records" and "the four decisions from the rollout channel" are two proposals a person can hold in their head. "Entries 1 to 15 of 34" is not.
- Nothing carries forward. An approval of one tranche approves that tranche.
The classification rules, the attribution rules, the duplicate check and the
insert rule are all project-log's and are not restated here. Four things are
worth saying because a seed run hits them and a normal log run does not:
- Date each entry with the date it was actually decided or raised, not with today. That is what the date field means, and a backfill is the one situation where the two differ for every entry.
- An entry whose date cannot be established is not proposed. Ask the user
for it. An approximation is a real answer: take it, and
project-logwrites the entry with theApproximate date.marker and the derivation in the body, perledger-format.md§ Approximate dates. Only when the user cannot supply even an approximation is the entry left out, and then say which ones were dropped and why. The date field is required and absolute, and no part of this skill licenses inventing one. - Anything implied but not stated goes in the proposal as a question, not as an entry. A design document describing a preference is not a decision, and a register's open question is an open item rather than a decision about it. A question the register records as answered is a resolved open item naming the decision that answered it, not a decision in its own right.
- A partial approval can break a supersession pair. Approving a decision
that supersedes another while dropping the one it supersedes leaves a body
claiming
Supersedeswith nothing to point at, and the ledger's rule is that the marking lives on both entries. Say so before the write and let the user choose -- keep both, or write the surviving decision without theSupersedesclause. Never write half a pair and never repair it afterwards.
Say what a backfill does to the audit before the user runs it. Entries dated
to their true origin are older than stale_after_days the moment they land, so
project-gaps reports them immediately. That is correct and it still surprises
people:
These are dated when they were raised, so anything older than 21 days will show
up as stale in /daikenja:project-gaps straight away. That is the audit working,
not a fault in the entries.
Step 5: confirm
Two or three lines: what was written, where, and what was deliberately left
alone, per ${CLAUDE_PLUGIN_ROOT}/docs/response-format.md -- the result
leads, and seeded entries are counted as ranges, not listed one by one.
Registered this project as `harbor` at C:/GitHub/harbor, with
stale_after_days: 30. Seeded 11 decisions and 6 open items through
project-log -- D-001 to D-011, O-001 to O-006. Left `ledger` and `norms_doc`
unset, so they use the defaults.
If seeding was declined or produced nothing, say that plainly and name
/daikenja:project-log as the way to add entries later.
Re-running this skill
Safe at any time, and expected. An exact path match -- against any path of any
entry -- leaves the entry and its key untouched, Step 3 shows what is already set before asking, and seeding a project
that already has a ledger proposes only what is not already recorded --
project-log's duplicate check is what enforces that, and an entry it matches
comes back as a proposed edit rather than a near copy.
Running it purely to seed an already-registered project is a normal use, not a workaround.
Failure cases
One notice line, then continue with reduced behavior. Hard-stop only when the missing thing is the task itself -- same rule every Daikenja skill follows.
| Situation | What to do |
|---|---|
daikenja.yaml absent |
Stop. Name /daikenja:setup-user. Never create the file here. |
daikenja.yaml malformed |
Stop. Name the first line that does not parse. Never guess the intent and never rewrite the file. |
profile.name unset or empty |
Stop. The configuration is incomplete. Point at /daikenja:setup-user. |
| An exact path match already exists | Say which key, leave it alone, and carry on to Steps 3 and 4. Registration is idempotent. |
An entry carries both path and paths |
Read it as the union of the two and say so, naming the key. Offer to fold it into one paths list on approval; never rewrite it silently. |
| The user names an existing project to add this directory to, and the key does not exist | Ask again, listing the registered keys. Never create a new entry under a key the user only half-remembered. |
| The user says the project has no directory | Not a failure. Write paths: [] and an absolute ledger: in the same entry, per Step 2 -- a pathless entry without one has nowhere to keep its record. |
| The current directory is inside an already-registered project | Say which project it resolves to and ask before adding a second entry. Never assume a nested registration is wanted. |
The current directory is the user's home directory or ~/.claude |
Stop. Neither is a project. Say so and write nothing. |
daikenja.yaml is not writable |
Stop. Name the path and the error. Do not write the entry anywhere else. |
| A named source is unreachable this session | One notice naming the source and what is missing, then continue with the rest. Never stop, and never make the skill conditional on a connector. |
| A source is reachable but empty, or the fetch fails halfway | One notice, then continue. Never guess at the content of something you could not read. |
| The project already keeps its own decision records | Not a failure. Say what was found, offer the index-and-depth shape from Step 4a, and let the user decide whether Daikenja adds anything here. |
| A seed entry has no recoverable date | Ask. If the user cannot supply one, drop that entry and name it in the report. Never date it today and never invent one. |
| A tranche goes unanswered | Restate what is still unwritten before proposing anything further. Silence is not approval. |
| The ledger is missing a required H2 section, or a line does not parse | project-log's failure table governs. Hand the material over and let it stop; do not repair a ledger from here. |
What this skill does not do
- It does not capture profile data, copy
personas.mdorwriting-style.md, or create anything in Google Drive. That is/daikenja:setup-user, and it stays there. - It does not write ledger content.
/daikenja:project-logdoes, on its own approval, and it is the only skill that does. - It does not write
last_checkpoint. That is/daikenja:project-catchup. - It does not edit the project's own documents -- a decision record, a wiki page or a README that a seed run read stays exactly as it was found.
- It does not migrate or convert anything from a previous Daikenja layout.