NORTH-STAR.md
Updated September 18, 2026
NORTH-STAR.md sits at the root of a project and says what is worth building in it. A conventions file says how to build. This one says what is worth building.
An agent has no institutional memory and it defaults to compliance. Ask for a thing and you get the thing, built well and on scope. Nothing in that loop ever says “this should not exist”. The only source of a “no” is you, and one person does not scale to six workers at once. A project with agents working in it and no written criterion for rejecting work collects competent drift faster than one without.
The file is plain markdown at a conventional path, so every agent reads it on the same terms. Nothing enforces it. It is a thinking aid, never a gate.
Who reads it
Whoever turns a goal into tasks. That is the reader whose judgment this is for: an orchestrator, or you at the moment you decide what to hand out. By the time a worker reads its brief, the decision has already been made upstream.
A worker must never refuse, renegotiate, or re-scope an assigned task on the strength of this file. It cannot see the context that justified the brief, so a conflict it thinks it sees is usually not one. crystl’s generated instructions block says exactly that, in those words, so a fan-out does not turn into six workers second-guessing their briefs. A worker that spots a real conflict says so in its report and carries on.
The six sections
Each one is phrased so a proposed task can be held against it.
- What this is for. One sentence: the thing being optimized.
- Who it is for. Whose problem counts, and whose does not.
- What good looks like. What a piece of work has to serve to be worth doing.
- What this is not. The explicit non-goals.
- What we have already rejected, and why. Dated, one line each.
- Current focus. What is in scope this cycle, dated.
Section 5 is the one nobody has. Most people cannot write principles cold, which is how vision documents end up vague. Anyone can answer “name something you turned down, and why”. The principles fall out of the rejections instead of being invented. It is also the section an orchestrator can actually use, because it is concrete, and it stops the same bad idea being proposed every quarter.
Section 6 is the staleness guard. A dated focus that has not moved in six months is visible rot. An undated principle is not.
Getting it written
crystl never writes this file for you, and no starter kit ships one. The only thing a kit could ship is an empty skeleton, which is the wall-poster document the whole feature exists to displace.
What crystl does instead is hand the job to the agent already sitting in your gem. Two doors, one prompt:
- the create north star button on the finding in the project optimizer;
crystl northstar initin a shard.
Both send the same composed text. The agent reads the repo first, drafts what the project looks like it is for and what you appear to have turned down, and then asks you to correct it. Correcting a wrong draft is much easier than authoring from nothing.
Two things it asks rather than infers: who it is for, which a repo rarely says, and what has been rejected, which lives in your head. The prompt also refuses principle and practice material. Test coverage, lint rules and dependency policy belong in your conventions file, and an agent offered them will say so.
If no shard is open, or the one that is open is mid-line, nothing is typed and the prompt is printed for you to paste. It is never lost.
It is a file you revise
A direction file written once and never touched describes a project you have stopped building. What it holds is exactly the material that moves: what you have learned the thing is for, who it turned out to serve, what you decided against last month.
So the button has two labels. With no file it says create north star. With a file already there it says revisit north star, and the prompt behind it is seeded with what the file currently says, so the agent opens with what changed rather than a blank page. crystl northstar init does the same thing from the terminal.
Recording a “no”
Drafting is one sitting. Nothing in it ever adds a line afterwards, and section 5 is the section that needs appending most. The moment a rejection happens is the moment to record it, because the reasoning cannot be recovered a month later.
crystl northstar reject "a second task panel, the workbench already does this"
That stamps today’s date and writes one line under the rejections section. Everything else in the file is left exactly as it was: your prose, your ordering, your headings. The section is matched by meaning rather than by its number, so a heading you titled “What we’ve said no to” keeps its name. A file with no such section gets one.
Your agent is told to offer this right after you turn something down.
If you already use spec-kit
A project that keeps this material in .specify/memory/constitution.md or constitution.md is read there instead. crystl does not ask you for a second file.
Writes only ever go to NORTH-STAR.md. That asymmetry is deliberate. A constitution is maintained for another tool, and putting a crystl field inside it edits someone else’s document. A project with only a constitution gets a NORTH-STAR.md holding what crystl writes, and from then on that file is the one it reads.
The distinction between the two is one line: a constitution says how to build, this says what is worth building. Every example principle in spec-kit’s own template is about how to build. Nothing in it concerns what to build or what to refuse.
The name
“North star” is ordinary English for guiding direction, so an agent meeting the file in an unfamiliar repo understands it without knowing what crystl is. It is also distinctive enough that no future agent-file standard will claim it, which DIRECTION.md or VISION.md could not promise.
One known collision: in product circles “north star” already means a single metric. This file is not that. Its first section and the drafting prompt both set the frame before the misreading can take hold.
Where the optimizer fits
Every other optimizer check asks whether an agent can do the work here: build commands, test commands, conventions. This is the one check that asks whether the work should be done, and it runs on a gem of every type, General included. A folder of client notes drifts the same way a product does.
The finding is worded “no stated criterion for rejecting work”, never “no vision doc”. The second phrasing is what produces the empty document.
It fires in four cases:
- the file does not exist;
- it exists and its sections are headings with nothing under them;
- it exists and nothing you wrote points at it (crystl’s own generated block names it on every project and does not count);
- it exists, is written, and its current focus has not moved while the project has. That last one takes no points off. It only fires on a gem with recent activity, so it means “you are working on something this file no longer describes” rather than nagging a project nobody has touched.
The finding is classified substance, not structure, so no starter kit can clear it. That classification is what keeps it honest.
Scope
One file per gem, at the project root. Not one per subdirectory: a monorepo’s packages inherit the root file, and a direction file per folder is the same empty document multiplied.
Related docs
- gem types: the type lives in this file, and scopes what the optimizer asks
- project optimizer: where the create and revisit buttons are
- new gem setup: where this offer comes up first, on a brand-new gem
- CLI:
crystl northstar initandcrystl northstar reject - agent instruction files: where principles and practice belong instead