Skip to main content
Projects are the spine. A milestone is a chunk of a project, a task is a unit of work in one, and both address their parent by slug or by display name. Goals, reminders and entities hang off the same graph without belonging to that hierarchy. Every one of these commands takes a short alias: base p for project, m for milestone, t for task, g for goal, r for reminder, e for entity. Verbs alias too, so base p l is base project list.
The four delete commands here (project delete, milestone delete, task delete and reminder remove) remove data. Three of them print a plan and change nothing until you pass --yes. base reminder remove is the exception: it deletes immediately.

Projects

base project add

Register a new project.
If you leave --path out and the protocol configuration is enabled, the folder is derived from the stage and created for you. If it is not enabled, the project has no folder, which is what base project list --unscoped finds later. The folder matters more since 0.16.0: a file touched inside it loads this project’s domain, with no trigger needed. See Domains and triggers.

base project list

List projects. By default it shows the current workspace only.
The table shows each project’s name, status, path, parent, whether it is nested, its next step with that step’s age ((3 days), or (undated) for one written before 0.16.0), and when it was last active. --json carries parent, nested, next_action_at and next_action_age_days too. Reach for --all before concluding a project has disappeared. Projects move between workspaces, and a project missing from the current workspace is usually a project that now lives somewhere else.

base project get

Show one project in full. Accepts the slug or the display name.

base project update

Change a project’s mutable fields.
--next-action is the field worth keeping current. It is the difference between a project you can resume and a project you have to reconstruct. base doctor lists every next step older than [doctor] stale_next_days (14 by default), and every undated one, with the command to update it. --parent refuses a slug that is not a registered project, and refuses a loop before writing anything (Error: loop: docs-client already has parent basemode-docs). --nested true on a project with no parent is stored with a warning: it does nothing until a parent is set. The update writes to whichever workspace’s data holds the project.

base project peer

Make a project surface in another workspace as well as its own, without moving it.
This adds a link, it does not copy anything. The project still lives in one place, and edits from either workspace are edits to the same project.

base project repath

Re-point a project at its new folder after you move it on disk. This updates the graph and the domain trigger together.
Both arguments are positional: the slug, then the new path, absolute or relative to the workspace root. Do this whenever a folder moves, because a path trigger pointing at a folder that no longer exists is a domain that silently stops firing. It writes exactly what base project update --path writes.

base project paths

Find each project’s real folder.
--suggest lists every project whose folder is missing, is a file, is too broad (it holds two or more other projects, or is your home, Documents, Desktop, Downloads or a workspace root), or is contradicted by its own docs. Each suggestion carries its evidence: the paths named in the project’s handoff and fork docs, and its own document records. A project with two candidate folders is listed with both and never guessed; in the --out file the second is commented out. --apply checks every line first and refuses the whole file on any fault, then sets each folder and moves its domain trigger.

base project rename

Preview by default. Rename a project and its same-named domain everywhere they appear.
Both arguments are positional: the name now (slug or display name), then the new name (lowercase letters, digits and dashes). The preview lists every record and file it would change, per kind and per tier, and the backups it will take. With --yes it backs up every file it writes (<file>.BAK-<date>-pre-rename-<old>) and writes each once; a failure part way puts back what it wrote. The old name stays as an alias. --domain basemod-docs, base project get basemod-docs, a decision slug that starts with it, and a handoff or task naming it all reach the renamed project, and each says basemod-docs is now basemode-docs on stderr. Prompt keywords are left as you set them, so the old name still fires the domain if it was a keyword. It refuses an unknown name, a new name already taken by a project or a domain, and a second rename while one is running.

base project deferred

List deferred projects: open but paused, not listed at session start.
A project defers through base reconcile, which runs at session start only when [protocol] enabled = true: a working project whose folder has had no file change for [defer.days] project days (else [protocol] stale_days, 7 by default) is deferred, and comes back when a file under it changes. Each row prints the date it was deferred and the command that brings it back. See deferred work.

base project move

Destructive. Preview by default. Re-home a project into another workspace’s graph, taking its tasks, its domain, and its decisions, rules and notes with it.
The code map regenerates at the destination rather than travelling, which is why the paths come out right. Pass --no-ast only if you intend to run base sync --ast there yourself.

base project delete

Destructive. Preview by default. Delete a project.
Without --force it refuses a project that still has children, which is the guard rail. With --force it takes them all, and the decisions and rules go too, and those are usually the part you would actually miss.

Milestones

base milestone add

Add a milestone to a project.

base milestone list

List milestones, optionally within one project.

base milestone get

Show one milestone.

base milestone update

Change a milestone’s status or description.

base milestone delete

Destructive. Preview by default. Delete a milestone.
By default the tasks survive: they are detached back to the project rather than deleted with their milestone. --force is what turns this into a cascade.

base milestone deferred

List deferred milestones: open but paused, not listed at session start.
Each row prints the command that brings it back, base milestone update <slug> --status active. Milestones defer only when [defer] enabled = true.

Tasks

base task add

Add a task to a project, optionally under a milestone.

base task list

List tasks, filtered by project, milestone or label.
Repeated --label narrows rather than widens: two labels means tasks carrying both, not either.

base task get

Show one task, every field.

base task update

Change a task’s mutable fields, including which project or milestone it belongs to.
Reassigning rewrites only the edge you named. Moving a task to a different milestone leaves its project edge alone.

base task done

Mark a task completed.
The short way to do what base task update <slug> --status completed does.

base task tag

Attach or detach free-form labels.

base task delete

Destructive. Preview by default. Delete a task and its edges.

base task deferred

List deferred tasks: open but paused, not listed at session start.
Each row prints the command that brings it back, base task update <slug> --status active. Tasks defer only when [defer] enabled = true.

Goals

A goal is a named target that is not a project and has no tasks under it.

base goal add

base goal list

base goal update

Reminders

A reminder surfaces in DUE NOW at the start of a session once its time has come, numbered, and keeps surfacing until you snooze or archive it. snooze and archive change the reminder in whichever tier holds it and say which, and list reads both tiers. From 8 days overdue, its DUE NOW line says when it will archive itself and how to snooze it. It archives itself only once it is 10 or more days overdue and that warning was first shown at least 2 days earlier; the next session start says so once, with base reminder unarchive <slug>. An archived reminder is kept, never deleted.

base reminder add

Give exactly one of --in, --at or --due.
Adding a reminder whose name already exists moves its time instead of making a second one, and says moved; when that reminder was archived it comes back, and says revived.

base reminder list

List reminders, from both tiers, with each one’s slug, tier and due time.

base reminder snooze

Move a reminder’s surface time forward from now.
Both arguments are positional: the slug, or the reminder’s number in the last session start’s DUE NOW, then a duration (30s, 3m, 2h, 1d). The due date moves with it, so the reminder has one clock. Inside a session the number is read from that session’s own DUE NOW.

base reminder archive

Archive a reminder: it stops surfacing and is kept.
Takes the slug or the DUE NOW number. This is the way to clear a reminder you have handled; remove deletes it.

base reminder unarchive

Bring an archived reminder back.
It surfaces again from its own time, or from now if that has passed. base reminder list --archived prints the slug.

base reminder remove

Destructive, no preview. Remove a reminder outright.
This is a hard delete with no confirmation. Run base reminder list first to get the slug you actually mean, and prefer base reminder archive for a reminder you have handled.

Entities

An entity is a person or an organization. Every entity must link to at least one domain, which is what stops orphans accumulating.

base entity add

base entity list

base entity get

Accepts the slug or the display name.

base entity update

base reconcile

Read each project’s folder for when it was last touched, and bring its active or deferred state back in line with that.
Run --dry-run first. This decides state from filesystem activity, so a project you have been working on outside its registered folder can look dormant when it is not. The dry run also previews the deferral pass for handoffs, forks, tasks and milestones (see [defer]), and says how many tiers it read. Run from outside any workspace, it says it read nothing instead of printing a plan of zeros.

Deferral migration

base defer holds one command, for turning deferral on without a pile of old records going quiet at once.

base defer migrate

Preview by default. Reset the activity clock on records that would otherwise defer as soon as you turn deferral on.
You do not have to run it. Deferring is not deleting: a deferred record stops showing at session start, stays listed by base handoff deferred and its siblings, and comes back with the command each row prints. Run this only if you would rather start the clock fresh for your older records before setting [defer] enabled = true.