StateFile class
Atomic JSON read/write for the artisan state file.
The file is PER PROJECT: ~/.artisan/sessions/<hash>/state.json, keyed by
the project root. It used to be one global ~/.artisan/state.json, which
meant a second project's artisan start silently took the slot and every
connected command from the first project then drove the second app,
succeeding each time. The measured case had a worktree in another
repository rewrite it mid-session, and two commands later produced a
screenshot of an entirely different product.
~/.artisan/state.json is still written, as a pointer to whichever
session started last. That is an interop contract rather than a shim:
the documented recovery recipe when artisan start cannot boot an app
is to hand-write that file, and external tooling reads it.
Written by artisan start after a successful flutter run spawn; consumed
by stop, status, logs, doctor, restart, and every connected-mode
command (dusk:, telescope:, tinker) to locate the running app's VM
Service WebSocket URI.
Schema:
pid(int, required): the flutter run process PIDstdinPipe(string, required): path to the FIFOflutter run's stdin reads from.reloadandhot-restartwriter/Rinto it, so a hand-written state without this key cannot hot restartstdinHolderPid(int, required): PID of the process holding the FIFO open for writing, reaped bystopbooting(bool, optional): present and true only between the spawn and the VM Service URI landing. A caller that gave up in that window left the app running, and this says the record is incomplete rather than wrongvmServiceUri(string, null whilebooting): canonicalws://host:port/<token>/wswebPort(int, required):--web-portpassed to fluttervmServicePort(int, optional, informational, default 8181)startedAt(ISO 8601 UTC string, required)profile(string, required,debug|static)projectRoot(string, required)device(string, required,chrome|macos|linux|windows| device UDID)chromePid(int | null, D6 Chrome capture outcome)tmpProfileDir(string | null, D6 Chrome capture outcome)cdpPort(int | null, --cdp-port value passed to start; null when CDP not enabled)
Properties
- hashCode → int
-
The hash code for this object.
no setterinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Static Properties
- debugHomeOverride ↔ String?
-
Test injection seam: overrides the resolved home directory.
Production code never sets this.
getter/setter pair
- debugProjectRootOverride ↔ String?
-
Test injection seam: overrides the resolved project root.
getter/setter pair
- homeDir → String
-
The directory every artisan artifact lives under, session or not.
no setter
- legacyPointerPath → String
-
The single global file every version before session isolation used.
no setter
- path → String
-
Absolute path to the state file this process reads and writes.
no setter
- pathOverride ↔ String?
-
Explicit path override, set from
--state=<path>. Null means "resolve from the project root", subject to explicitPath.getter/setter pair
Static Methods
-
delete(
) → Future< void> - Delete this project's state. Idempotent.
-
explicitPath(
) → String? - The session the caller NAMED, by flag or by environment, or null when they named none.
-
projectRootFor(
String from) → String -
The package root
frombelongs to: the nearest ancestor holding apubspec.yaml, orfromitself when there is none. -
read(
) → Future< Map< String, dynamic> ?> - Read the state for this project. Returns null when absent.
-
sessionDirFor(
String projectRoot) → String - The directory holding one session's state, log and FIFO.
-
sessionPathFor(
String projectRoot) → String -
The session file for
projectRoot. -
write(
Map< String, dynamic> data) → Future<void> - Write atomically via .tmp + rename (no partial-state windows).