A repository can arrive in Fleet three ways: added from disk, cloned from an organisation, or created. Creating scaffolds a project, commits it, publishes it, registers it, and opens a session with a brief.
What actually runs
Fleet does not have its own idea of what a Next.js app looks like. Each template runs the
ecosystem's real generator: create-next-app, cargo new, npm create vite, flutter create, and
so on, across Node, Python, Go, Rust, PHP, Swift and Dart.
Because those are real commands, Fleet probes for the toolchain first. A template whose toolchain is missing is offered in agent mode instead, where the agent sets the project up itself.
Purpose
You pick what the project is for: a SaaS product, a marketing site, an internal tool, a dashboard, a CLI, a library, an API, a mobile app, an AI agent, a data pipeline, a prototype.
That choice does not change the scaffolder. It changes the brief the first session receives, so the agent starts knowing what it is building rather than asking.
Integrations
You can tick integrations: authentication, a database, payments, email, analytics, UI, testing, CI, error reporting.
What Fleet does with them is deliberately small. It installs the dependency and writes the
environment keys as blank lines in .env.example, and it tells the agent in the brief what to
connect.
It does not generate the wiring. A generator that wires an auth provider into your middleware owns a stack opinion that is wrong by the next major version, and a stale generator is worse than no generator, because it looks authoritative. The agent writes the integration against the current docs, with you watching.
The order of operations
Ordering is nearly all of the correctness here, and it is worth knowing what Fleet refuses to do.
- It asks git where the repository root is rather than assuming, and refuses when the answer is an ancestor of the target directory. Otherwise it would commit your new project into a repository you already had.
- It writes
CLAUDE.mdand.env.exampleafter the scaffolder, becausecargo newand several Next templates refuse a non-empty directory outright, and it never overwrites what the scaffolder wrote. - It commits before publishing, because publishing with no commits fails.
- It registers the repository after the remote exists, and then corrects the base branch from git
itself, because a scaffolder's own
git initpicks its own default and a wrong base makes every future session branch from a ref that does not exist.
There is always a commit before the session opens
This is not tidiness. A session makes no worktree until its first prompt, and git worktree add on
a repository with zero commits fails, which would discard the brief already queued to be sent. The
brief is the entire payload of a created project, so it would vanish silently.
The consequence worth saying out loud: the scaffold lands on a fleet/ branch and reaches your base
branch through the normal review flow. A freshly published main starts nearly empty on purpose.
When something fails
Three tiers, and nothing is ever deleted.
- A scaffold step failing is fatal to the create, but the tree stays where it is. It is deliberately not downgraded to agent mode, because an agent scaffolding over a half written tree cannot tell its own new file from a half written one.
- Everything after there is a committed tree is soft. A failed dependency install or a failed repository creation lands in warnings and in the brief's notes. Losing a project to a registry outage would be absurd.
- Registration is unconditional once a commit exists, or the project would be on disk and invisible to the app that made it.
A local-only project is a degraded success rather than a failure, exactly as branching falls back to a local base when a fetch fails. The pane explains which you got, and an authentication failure retries through your own Terminal, because interactive logins never happen inside Fleet.
Security of a template
One argv element is one argument, and there is no shell anywhere in this. Placeholders are
substituted inside single arguments and never across them, so a module path can contain one. The
project name and the owner are each validated twice, on the resolved path rather than on the string
that produced it, and an owner that starts with a dash is refused because passing it to gh would
be flag injection.