cdno project
Manage project maps: create, update state, set the core question, hand off and take back,
add/complete/drop milestones, manage waiting-on items, park/activate, complete/drop the project itself, and list/show. Next actions have their own verb, cdno action.
cdno project [OPTIONS] <COMMAND>
Subcommands
| Subcommand | Description |
|---|---|
create | Create a new project map |
state | Update the Current State (auto-logs the previous) |
core-question | Set or clear the core question (auto-logs the previous) |
hand-off | Name who else is moving a project (auto-logs the change) |
take-back | Make a handed-off project yours again (auto-logs the change) |
park | Move a project to _parked/ |
complete | Close a project whose work is done (moves it to _done/<year>/) |
drop | Close a project that is not going to happen (moves it to _done/<year>/) |
activate | Bring a parked or closed project back (enforces the cap) |
list | List active projects, or closed ones with --closed |
show | Show one project |
milestone | Add / complete / drop milestones |
waiting | Add / resolve waiting-on items |
Write subcommands honour --json (a {path, message} result, run non-interactively); list/show
emit their data under --json.
A parked project is a complete map, so every subcommand that writes a project’s body (state,
core-question, hand-off, take-back, milestone, waiting, and the
cdno action verbs that take --project, except start, switch and resume) accepts an active or a
parked slug. When --slug is omitted in a terminal, the picker and shell completion offer the active
and parked projects; park offers active projects only. See
Business rules.
cdno project create
Create a new project map. Created parked if you’re already at the active cap.
| Flag | Description |
|---|---|
--title <TITLE> | Project title (the slug derives from it). |
--slug <SLUG> | Name the new map’s file yourself instead of deriving it from the title. Not a selector: the other subcommands use --slug to pick an existing project. Refused if invalid or taken; see the slug rule. |
--context <CONTEXT> | Life domain: work, side-project, university, family, household, legal, personal. |
--question <QUESTION> | Vault-relative core-question wikilink target (e.g. questions/research/foo). Optional. |
--var <NAME=VALUE> | Value for a custom template’s prompted variable ([variables.prompt]). Repeatable. See Prompted variables. |
cdno project create --title "Surrogate model" --context work
cdno project create --title "Thesis" --context university --var ticket=ABC-123
cdno project create --title "Surrogate model for the mesh-scaling study" --context work --slug surrogate-model
cdno project create --title "Thesis" --context university --question questions/research/surrogate-cost
cdno project state
Update the Current State section. The previous state is auto-logged to today’s daily note first (see Business rules).
| Flag | Description |
|---|---|
--slug <SLUG> | Active or parked project slug. |
--text <TEXT> | The new state text. |
cdno project state --slug surrogate-model --text "Mesh scaling works; assembly is the bottleneck"
cdno project core-question
Set or clear the project’s core question after creation, auto-logging the previous value to today’s
daily note in the same was: / now: shape state uses.
core-question — --slug, and either --question <target> or --clear
cdno project core-question --slug surrogate-model --question questions/research/does-it-scale
cdno project core-question --slug surrogate-model --clear
--question takes the bare wikilink target, the same form
create --question takes — questions/research/foo, not [[…]], which is
rejected rather than double-wrapped.
Passing neither flag non-interactively is an error, not a silent detach: dropping a project’s question is a decision and has to be asked for.
cdno project hand-off
Record that someone else is moving an open (active or parked) project: the map gets
held_by: "<name>", and today’s daily note gets a holder on [[<slug>]] entry with indented was: /
now: lines, the side with no holder written (mine). A hand-off records a fact about the
project: someone else is moving it now, and the next move is theirs. Because the
active cap counts the projects that are
yours to move, an active project that names a holder is not counted; but handing off is never the
answer to a full cap. Name a holder only when someone else really has the project; to make room,
park, complete or drop one. The map stays where it is, and its deadlines stay in
cdno commitments.
| Flag | Description |
|---|---|
--slug <SLUG> | Active or parked project slug. |
--to <WHO> | Who has it: a name, or a wikilink target such as [[people/ana-ruiz]]. Prompted as “Who has it?”. |
cdno project hand-off --slug hull-survey --to "Ana Ruiz"
# Handed hull-survey to Ana Ruiz (projects/hull-survey.md)
A hand-off is refused when:
- the value names you or nobody (
me,tbd,someone, or another entry ofholder_sentinels): if you cannot name who has the project, it is yours. Keep it, or runcdno project take-backif it was handed off; - the value is a date, which names no one: give the person’s name instead;
- an action on the project is in focus: pause it
first with
cdno action pause, then hand it off; - the project is closed: only an active or parked project has a holder, so
activateit first if the work has come back.
Handing a project to the holder it already names changes nothing and logs nothing.
cdno project take-back
Clear a project’s holder: the map gets held_by: null and the daily note a holder on [[<slug>]]
entry with now: (mine). An active project then counts toward the cap again, so taking one back at
the cap is refused with the list of counted projects; park, complete or drop one of them first. A
parked project stays parked: taking it back clears the name only and needs no slot.
| Flag | Description |
|---|---|
--slug <SLUG> | Active or parked project slug. |
cdno project take-back --slug hull-survey
# Took hull-survey back (projects/hull-survey.md)
cdno project park
Move an active project to projects/_parked/, freeing a slot against the five-project cap.
| Flag | Description |
|---|---|
--slug <SLUG> | Active project slug. |
cdno project park --slug surrogate-model
cdno project complete
Close a project because its work is done. The map moves to projects/_done/<year>/<slug>.md with
status: completed and closed: set to today, and the daily log gets
project completed [[<slug>]] — <title>. It works on an active or a parked project and never needs a
slot, since closing adds nothing to the active count.
| Flag | Description |
|---|---|
--slug <SLUG> | Active or parked project slug. |
A completion is a claim that the work was done, so it is refused while any action or milestone is still open, and there is no flag to force it. The refusal lists what is open:
surrogate-model has 3 open items:
- [ ] Run feature set B on full geometry mesh (deep)
- [ ] [[actions/characterise-kan-ppo-sample-efficiency]] (deep)
- [ ] ICML paper submitted — hard: 2026-05-22
Still open, not touched: [[commitments/reviewer-report]] (due 2026-10-15)
Complete or drop each of them (or add it to the project that now owns it), then run again.
Tick what was done (cdno action done, milestone done), drop
what is not happening (cdno action drop, milestone drop,
each with its own reason), and run the command again:
cdno project complete --slug surrogate-model
# Completed surrogate-model. 4 of 5 slots in use.
Standalone commitments linked to the project are never touched: a promise to someone else does not end with the project. The success message names any that are still open.
cdno project drop
Close a project that is not going to happen. The map moves to projects/_done/<year>/<slug>.md with
status: dropped and closed: set to today, and the daily log gets
project dropped on [[<slug>]] — <title>, with the reason on an indented reason: line. Like
complete, it works on an active or a parked project and never needs a slot: ending a shelved plan
does not bring it back first.
| Flag | Description |
|---|---|
--slug <SLUG> | Active or parked project slug. |
--reason <REASON> | Why it is being dropped. Optional and never prompted for, but worth giving. |
--drop-open | Drop the project’s open actions and milestones with it, without asking. |
With open actions or milestones, drop lists them as complete does. In a terminal it then asks
Let these N go and drop <slug>? [y/N], and pressing Enter keeps everything. On y each open item
is dropped with the project, logged as its own action dropped on / milestone dropped on line
with reason: project dropped (<your reason>) (or plain reason: project dropped without
--reason), and an attached action note is archived as dropped.
If the list changed while you were answering, nothing is dropped and the new list is shown.
Non-interactively the list is printed and the command exits 1, unless you pass --drop-open.
cdno project drop --slug bayesian-opt-survey --reason "superseded by the ICML work"
cdno project drop --slug bayesian-opt-survey --reason "superseded" --drop-open
# Dropped bayesian-opt-survey. 4 of 5 slots in use. Let go: 2 actions, 1 milestone.
Items that were in fact done should be ticked first: a drop records that work was let go, not that it was finished.
Under --json a refusal from either verb prints the same project_has_open_items object the MCP
server returns (the items plus an open_items_hash) and exits 1; a success prints path,
message, dropped_actions, dropped_milestones and untouched_commitments.
A closed project can be closed again with the other outcome, as a new decision: a dropped project
that turns out to have been finished can be completed, and the reverse. It is re-filed under this
year’s folder with today’s closed: date and a new log line. Closing it again with the same outcome
is refused, naming the date it already has.
cdno project activate
Bring a parked, completed or dropped project back to projects/. A closed project also has its
closed: date cleared, so it can be closed again later with a fresh one. The log says
project [[<slug>]] activated. Fails if it would exceed the active cap — park another first. The
interactive picker and shell completion offer parked and closed projects, labelled.
| Flag | Description |
|---|---|
--slug <SLUG> | Parked or closed project slug. |
cdno project activate --slug surrogate-model
cdno project list
List active projects with a state snippet. Each project renders as a card — a coloured bar keyed to
its context, the slug as a title, and the state wrapped underneath. Honours --json.
A project that names someone else as its holder carries one more line, held by: <name> · does not count toward the cap. A value on holder_sentinels leaves the map
yours, so it prints no holder line. Under --json each row
carries held_by and counts (see JSON output).
In a terminal this then offers to open one of the projects it just listed, printing the same thing
cdno project show would and asking again until you press Esc. Piped output, --no-interactive, and
--json skip the prompt. See Colour and interactivity.
With --closed it lists completed and dropped projects instead, newest first, each with its outcome
and closing date. Under --json each row carries slug, title, context, outcome and
closed_on.
cdno project list
cdno project list --json | jq '.[].slug'
cdno project list --no-interactive # listing only, never a prompt
cdno project list --closed
cdno project show
Show a compact summary of a single project (any status). The slug is an optional positional: omit it
in a terminal and cdno offers a picker covering active and parked projects. Honours --json
(emits the project summary object).
For an active or parked project it ends with Held by: <name> when the map names someone else (a
sentinel prints none), and Counts toward the cap: yes or no.
cdno project show surrogate-model
cdno project show # pick from a list
cdno project show surrogate-model --json
cdno project milestone
Manage milestones — markers of progress. A --hard milestone is a real deadline counted in
cdno commitments.
add — --slug, --title, --date <YYYY-MM-DD> (optional), --hard
done — --slug, --query (case-insensitive substring of the milestone title)
drop — --slug, --query, --reason (optional)
cdno project milestone add --slug surrogate-model --title "Submit to ICML" --date 2026-01-22 --hard
cdno project milestone add --slug surrogate-model --title "All Round-1 replies received"
cdno project milestone done --slug surrogate-model --query "submit to icml"
cdno project milestone drop --slug surrogate-model --query "book the venue" --reason "the funder withdrew"
Use drop rather than done when the milestone is not going to happen — superseded, mis-typed, or
overtaken by events. done ticks the bullet and writes milestone done on ... to the daily log,
asserting a milestone that was met; drop removes the bullet and writes milestone dropped on ...
instead, so a later reader can tell a plan that changed from a plan that was kept. --reason is
optional and never prompted for: a correction is simply a drop with no reason. Only open - [ ]
bullets are matched — a completed milestone is a record of what happened, not a plan to revise.
--date is optional. Some milestones are gated by a condition rather than a date — “all Round-1
replies received” on a correspondence-driven project — and omitting the flag records the milestone
as target: TBD rather than making you invent an estimate. An undated milestone does not appear
in cdno commitments, which is the point: a date you made up reads later like a
commitment somebody made. It completes with done exactly like a dated one.
Interactively, the calendar is offered behind a yes/no so the undated case is reachable without knowing the flag can be omitted.
--hard requires --date: a hard deadline with no date is rejected rather than quietly downgraded
to a soft target.
cdno project waiting
Track external blockers.
add — --slug, --description
resolve — --slug, --query (substring of the item)
cdno project waiting add --slug surrogate-model --description "Cluster quota from IT"
cdno project waiting resolve --slug surrogate-model --query "cluster quota"
Related MCP tools
create_project, update_project_state,
park_project,
complete_project,
drop_project,
activate_project,
hand_off_project, list_projects,
get_project_context, add_milestone,
complete_milestone, set_core_question,
add_waiting_on,
resolve_waiting_on.
See also
- Managing projects.
action— the next-action list.