framework
- Version 0.7.0
- Published
- 6.23 MB
- 15 dependencies
- MIT license
Install
npm i frameworkyarn add frameworkpnpm add frameworkOverview
The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.
Index
Interfaces
Type Aliases
Interfaces
interface ActiveAgent
interface ActiveAgent {}One project's in-flight run, surfaced in the Overview's "working now" list.
property agentId
agentId: string;Which run this is (#738): a project can have several in flight, one per worktree.
property cwd
cwd: string;The agent's own checkout, so its git/file status is read from the worktree it edits (#738).
property intent
intent?: string;What the user asked to build (the agent's
scopeevent).
property projectId
projectId: string;property projectName
projectName: string;property readyForMerge
readyForMerge?: boolean;Whether the agent signalled
setReadyForMerge()(#326): drives the building/ready dot.
property scope
scope?: string;property sessionName
sessionName?: string;The session name the agent chose (#326), when it set one.
property status
status: AgentStatus;property updatedAt
updatedAt?: string;ISO timestamp of the agent's last event.
interface Activity
interface Activity {}One agent lifecycle event worth a passing mention. Two kinds: an agent
started(enteredrunning) orfinished(reached a terminal status). The card is not shown for these — they only drive notifications — so the fields are just what a notification line needs.
property agentId
agentId: string;The agent this is about.
property kind
kind: 'started' | 'finished';started= the agent enteredrunning;finished= it reached a terminal status.
property projectId
projectId: string;property projectName
projectName: string;property status
status?: AgentStatus;The finished agent's terminal status (
finishedonly), so a stop reads differently from a done.
property title
title?: string;What the agent is building (its
intent), for the notification body; may be absent.
property updatedAt
updatedAt?: string;When the agent last changed, ISO, for ordering and the baseline diff.
interface AgentError
interface AgentError {}One error the agent reported through an
errorblock (#1500).
interface AgentHandoff
interface AgentHandoff {}What a finished session produced and what can still be done with it.
property base
base?: string;What the branch is measured against (the repo's default branch), when one was found.
property branch
branch: string;The branch the work is on.
property commits
commits: HandoffCommit[];property deletions
deletions: number;property empty
empty: boolean;The session produced nothing to hand off: the branch exists but carries no commit the base does not already have — or nothing beyond the framework's own bookkeeping (#1291), which is committed for provenance, never as publishable work. Said out loud, rather than shown as an empty branch.
property exists
exists: boolean;The branch still exists in the repo (a deleted or never-created one does not).
property files
files: HandoffFile[];property hasRemote
hasRemote: boolean;The repo has a remote to push to at all.
property insertions
insertions: number;property merged
merged: boolean;The branch is already merged into the base.
property pendingFiles
pendingFiles?: string[];The files the session changed and never committed, read from its own checkout (#1173).
The agent is instructed to commit what it *found*, never what it *wrote*, so a settled session can hold its whole output in an uncommitted tree. That work is not on the branch yet, so it is not in commits and it does not make empty false. Paths rather than a count, because a no-diff branch must *name* what is waiting instead of offering an Open PR that GitHub can only refuse. Absent when the caller did not say which checkout the session worked in — "nobody asked" and "asked, tree clean" are different answers.
property pr
pr?: LinkedPr;The PR opened for this branch, when there is one.
property prPending
prPending?: boolean;The PR is not known yet, rather than absent (#1028): the lookup is still running.
property pushed
pushed: boolean;The branch is on the remote and the remote is at the same commit.
interface AgentMeta
interface AgentMeta {}A queryable snapshot of the agent, derived entirely from the event log. Lets the dashboard render a header (and a future agent list) without parsing every line.
property branch
branch?: string;The branch the agent's work is on: folded from
branchevents as the agent observes it (#1277), and corrected at teardown while the worktree still exists (#799).Not reliably derivable instead of recorded: a clean agent loses its checkout, and the #326 prompt lets the agent create its own branch, so neither
tf-<sessionName>nor the run-id branch is guaranteed to be the one holding the commits.
property browserStreamPort
browserStreamPort?: number;The loopback port the agent's browser preview is listening on (#813), or absent when the agent has no browser. What lets the daemon proxy the pane: the port is allocated per agent and the dashboard is a different process, so meta is the only place it can learn it.
property cloudAnchor
cloudAnchor?: string;The hand-off anchor a cloud run pushed for its session to clone at (#1601): an empty commit unique to this run, folded from the
cloud-anchorevent. The session works on aclaude/*branch of the cloud's own naming, and this is the ancestor by which the daemon's adoption pass recognizes which of origin'sclaude/*heads is this run's. Absent on non-web runs and on web runs whose pre-hand-off push failed.
property driver
driver?: string;The wrapped agent (from the
sessionevent).
property handoff
handoff?: { push: boolean; pr: boolean; merge?: boolean;};What this session's end-of-session handoff is armed to do (#1102): push its branch, and open a draft PR for it. Both start on.
On the meta because the checkboxes that show it live in a different process from the agent that obeys it, and a tab opened after the agent started has no event history to fold — the same reason browserStreamPort is here. Absent means an older agent, which the reader treats as armed, matching what that agent will actually do.
mergemirrors the auto-merge arming (#1216, #1382) — display-only, like the rest of this field: the agent merges off its own config, never off the meta. Absent on records from before #1382, which the reader treats as off.
property handoffReport
handoffReport?: 'done' | 'skipped' | 'failed';How the end-of-session handoff reported back (#1455), folded from the
handoffevent.What lets a list surface — which reads meta, not the event log — tell "ended, still publishing" from "ended, published": between a clean
endand this field, an armed agent's epilogue is still pushing / opening the PR, exactly the window the session pill calls "publishing…" (#1431). Absent until the event lands, which is what a list reads as "still going".
property handoffSkip
handoffSkip?: AutoHandoffSkip;Why a skipped handoff skipped (#1583), folded from the same
handoffevent as handoffReport. What lets the daemon tell "published elsewhere" from "ended with nothing to hand off": a drain that settles withno-commitswill never run the PR that lifts its ticket lock, so the sweep releases the claim it minted. On the meta because the sweep reads metas, not event logs. Absent on non-skipped handoffs and on older records.
property host
host?: string;The host the owning pid lives on, so a pid probe only trusts a match (#716).
property id
id: string;Stable, path-safe id for this agent (derived from startedAt).
property intent
intent?: string;What this session was asked for (from the
intentevent).
property kind
kind?: 'build' | 'prompt';The flow this agent started under (#1467):
buildfor the scope→build orchestration,promptfor the direct-prompt path (research and transparent runs recordprompttoo). Persisted so a continuation (#762) can re-enter the flow its first leg ran — the composer's Resume always arrives as apromptstart, and without this record a resumed build agent ended as a bare prompt session (no synthesize framing, no backlog offer). Absent on records from before this field, which a reader treats as unknown (the continuation then keeps the prompt path).
property mergeOutcome
mergeOutcome?: 'auto-armed' | 'merged' | 'watched' | 'withheld' | 'failed';How the handoff's merge half went (#1418), folded from the
handoffevent'smergefield.What the daemon's CI watch scans for:
watchedis a PR waiting for green that *this* side must merge (the repo could not arm GitHub auto-merge),auto-armedone GitHub will land by itself but whose checks going red is still ours to notice. On the meta because the watch reads metas, not event logs, and must survive both the agent's process and the daemon's. Absent on runs from before this field, and on every agent whose handoff had no merge to report.
property model
model?: string;The model id the current leg's agent was started with (#1438), folded from each leg's
sessionevent — a continuation (#762) may run a different model than the first leg, so the latest leg wins rather than the first pinning it. Absent when the leg left the agent on its own default (and on records from before this field).
property pendingChoice
pendingChoice?: { id: string; title: string;};The choice gate the agent is currently parked on (#636): set when a
choiceevent fires and cleared when itschoice-resolved(or the agent'send) arrives. Present means the agent is paused waiting for the user's answer — the second "needs you" source after open PRs (#624).
property pid
pid?: number;The OS pid of the process that owns this agent (the one tailing
control.jsonl), on host. Persisted so a reader can tell a live agent from one whose process died without writingend(#716): arunningmeta whose owning pid is gone is stale and gets flipped tostopped.
property pr
pr?: { number: number; url: string;};The pull request this session's work is on (E6), recorded when one is opened rather than re-derived from branch names and timestamps by every surface that wants it.
property readyForMerge
readyForMerge?: boolean;Whether the agent signalled
setReadyForMerge()(#326): building (false/absent) vs ready (true).
property remoteLabel
remoteLabel?: string;The connected device a remote agent (#1067) executes on, for the session list + notice after a reload.
property sessionId
sessionId?: string;The wrapped agent's real session id, once it reports one.
property sessionLink
sessionLink?: string;The link shown to jump into the live agent session.
property sessionName
sessionName?: string;The session name the agent chose (#326), also its
tf-<name>branch.
property settledAt
settledAt?: string;When the agent settled and parked on the user (#785), or absent while the agent is working.
Deliberately not a AgentStatus value: the agent IS still live while it waits (its process is alive, it still takes messages, it still holds the project), and a dozen readers key "live" off
status === 'running'. This is the orthogonal fact — working, or waiting on you — whichstatuscannot carry because it only changes when the agent ends.
property startedAt
startedAt: string;ISO timestamp the store was opened (run start).
property status
status: AgentStatus;property target
target?: 'local' | 'actions' | 'remote' | 'web';Where this run executes (#1050/#1053/#610):
actionsfor a GitHub Actions run,webfor a Claude Code cloud session,remotewhen relayed to a connected device (#1067), absent for a local run. Persisted so the agent view can tell a burst-mode Actions run from a stalled live feed, show a cloud agent's session link after a reload, and gate the browser pane off (#1053).
property ticket
ticket?: string;The ticket this agent is implementing (#1117), repo-relative (
tickets/<file>.md).Set only when the framework picked the ticket itself, so the Overview can show a ticket that is being coded right now as
implementinginstead of inferring it from the plan/spike it left behind. Absent on every agent nobody linked to a ticket.
property updatedAt
updatedAt: string;ISO timestamp of the last event written.
property workspace
workspace?: string;The workspace the agent builds in (from the
sessionevent).
interface AgentWorktree
interface AgentWorktree {}Where a session is working (#798): the checkout, its branch, and what it is holding. Read by the dashboard so a session's action bar can say which worktree it has, rather than leaving the user to infer it from an agent id.
property branch
branch?: string;The branch it is on, absent when the path is not a git repo.
property dirty
dirty: boolean;Uncommitted changes present in that checkout.
property own
own: boolean;True when it is the agent's own worktree; false when it fell back to the project's checkout.
property path
path: string;Absolute path of the checkout this agent works in.
property pr
pr?: LinkedPr;The PR opened for this checkout's branch (#809), when there is one.
property prPending
prPending?: boolean;The PR is not known yet, rather than absent (#1028): the lookup is still running.
property sizeBytes
sizeBytes?: number;Size on disk, bytes. Only read once nothing is writing to it, and best-effort even then.
interface AutoPmJob
interface AutoPmJob {}One thing auto PM knows how to do while the machine is idle (#773).
The jobs form a cycle, and the order matters: triage turns tickets into queued work, [Plan tickets] turns the rest into plans. Once a job queues something the sweep switches to draining it (#855), and the rotation resumes where it left off once the queue is empty again.
property autoMerge
autoMerge?: boolean;Merge this job's PR once its agent opens it (#1216). Set on the drain job: what it implements has already been triaged as consensual, quick-win work a human could have vetoed on the queue, so its PR is the one kind whose review happened before the agent. Declared as data on the job for the same no-name-matching reason as AutoPmJob.drains.
property claim
claim?: PlanAssignment;The
.lock.mdclaim the sweep minted for this start (#1420/#1583), on both pinned variants. What lets the sweep free the claim itself when the agent settles with nothing to hand off: the agent's PR is what normally deletes the lock, and an agent that never made a commit is never opening one.
property describe
describe?: string;A line saying what the job does, wherever its label does not already: under the label in the routines list, and as the log line's wording. Only the maintenance sweep carries one -- "Maintenance" names its preset rather than the work -- while the other routines' labels read as what they do, so their rows stay one line and their log lines say the label itself rather than the same thing twice. Data on the job rather than a name matched in the dashboard, so a rename cannot quietly move the line around.
property drains
drains?: boolean;This job works an entry already on the queue, rather than putting entries on it (#1117).
Only the draining job has a specific piece of work it is about to pick up, so only it can be told which ticket that is. Declared here rather than matched on AutoPmJob.name at the call site, so the job says what it does and a rename cannot quietly unhook it.
property entry
entry?: string;The one queue entry a AutoPmJob.drains job is pinned to (#1204). Set only on the per-start variants pinnedDrainJob builds: the catalog's own drain job carries none, since which entry is next is known only at the moment the sweep starts one.
property fansOut
fansOut?: boolean;This rotation job may fan out to several agents pinned one ticket each (#1327). Only [Plan tickets] declares it: unlike the other rotation jobs it writes per-ticket sibling files rather than rewriting the shared queue document, so concurrent copies do disjoint work and land disjoint edits — the exact property that already lets draining fan out. Declared as data on the job for the same no-name-matching reason as AutoPmJob.drains.
property label
label?: string;The user-facing name, for a surface that lists the routines (#1159). Read off the preset the job fires rather than written again here, so a relabelled preset relabels its routine.
property name
name: string;Stable id: the rotation and the opt-out list (#1209) key on it.
property pinnedBranch
pinnedBranch?: string;The branch this job's prompt pins via its constant session name, when it does (#1293). The triage prompts abort when
the-framework/<SESSION_NAME>already exists, so a leftover branch whose PR was closed or merged jams the routine forever. Declared as data on the job, like AutoPmJob.drains, so the sweep can release the stale name before firing without matching on AutoPmJob.name at the call site.
property prompt
prompt: string;The prompt to run, verbatim.
property ticket
ticket?: string;The one ticket a fanned-out job is pinned to (#1327), as its filename inside
tickets/. Set only on the per-start variants pinnedPlanJob builds, like AutoPmJob.entry is for drains: which tickets are open is known only at the moment the sweep locks them.
property tooltip
tooltip?: string | undefined;The preset's own one-line "what this does" (#1506), for a surface that has to say what a click is about to spend an agent on before it spends it. Read off the preset like AutoPmJob.label, so the sentence the launcher shows for a preset and the sentence the routines list shows for its routine are the same sentence. Absent for a preset without one.
interface AutoPmOutcome
interface AutoPmOutcome {}What the last sweep decided about one project.
property message
message: string;The sentence: what was started, or the reason for standing down.
property path
path: string;Its path, which is what the log line names and the panel shows.
property projectId
projectId: string;Registry id of the project considered.
property started
started: boolean;Whether an agent was started for it.
interface AutoPmReport
interface AutoPmReport {}What auto PM has done lately (#1161).
Every decision was already logged (#855), but the log is the daemon's stdout and the toggle lives in a browser, so from the dashboard a wedged sweep and a healthy idle one looked identical — the same failure #855 fixed one layer down.
property enabled
enabled?: boolean;Whether the preference was on at the last sweep.
undefinedbefore the first one.
property nextSweepAt
nextSweepAt: number;When the next sweep is due, epoch ms.
property outcomes
outcomes: AutoPmOutcome[];One line per project the last sweep considered, in sweep order.
property sweptAt
sweptAt?: number;When the last sweep finished, epoch ms.
undefinedbefore the first one.
interface BridgeAnswer
interface BridgeAnswer {}An answer picked in the dashboard, on its way back to the session (#1237).
queueduntil the extension fetches it, delivers it into the composer and acknowledges; thensent, orfailedwith the extension's reason. The id is what the acknowledgement references, so a stale ack from a tab that died mid-delivery cannot resolve a newer answer.
interface BridgeEvent
interface BridgeEvent {}One thing a cloud session did, as scraped from its page (#1237).
seqis the message's position in the transcript, assigned by the extension, and it is what makes this idempotent: the page is re-read on every DOM change, so the same message arrives many times and the daemon keeps one copy per position rather than a growing pile of repeats.
property receivedAt
receivedAt: string;property role
role: 'agent' | 'user';property seq
seq: number;property sessionId
sessionId: string;property text
text: string;interface BridgeQuestion
interface BridgeQuestion {}A question a cloud session is parked on, as reported by the bridge.
property options
options: { label: string; detail?: string;}[];property receivedAt
receivedAt: string;When the daemon accepted it. Set here, never by the caller.
property recommended
recommended?: string;property sessionId
sessionId: string;The cloud session that asked, which joins back to an agent through
AgentMeta.sessionId.
property title
title: string;interface ChoiceRequest
interface ChoiceRequest {}An interactive choice the agent pauses on until a pick arrives (#304). Emitted as a
choiceFrameworkEvent; the dashboard renders it in a panel and posts the pick back. The recommended option is the default the autopilot auto-accepts.
property autoAcceptMs
autoAcceptMs?: number;Auto-accept the recommended option after this many ms when autopilot is on. Default 10000.
property file
file?: string;The markdown file under approval (e.g.
PLAN_<slug>.agent.md); the doc sidebar renders it.
property id
id: string;Unique id for this pending choice; the pick is posted back against it.
property multi
multi?: boolean;Render as a multi-select checklist (#332): each option is a checkbox pre-checked per its ChoiceOption.default, and the pick resolves to the selected *subset* of ids rather than one. Absent = the single-select gate (#304).
property options
options: readonly ChoiceOption[];The options to choose between (at least one).
property recommended
recommended?: string;The option id pre-selected as the default (autopilot auto-accepts it). Required for a single-select; omitted for a multi select, where each option's own ChoiceOption.default drives the pre-checked set instead.
property title
title: string;The question shown above the options (e.g. "Approve this plan?").
interface CustomPreset
interface CustomPreset {}A user-defined preset (#626): a named prompt the user saved to re-run their own high-signal prompts, sitting beside the built-in presets in the Start form. Just data — the label is the button, the prompt is loaded verbatim into the editor and run as a
promptkind (unlike the built-ins, whose text is a compiled render function).idis stable so edits/deletes address one.
interface DashboardData
interface DashboardData {}The dashboard page payload (#471).
property active
active: ActiveAgent[];Agents going right now, most-recently-updated first (from buildOverview).
property projects
projects: ProjectStat[];Every registered project, most-recently-active first.
property queue
queue: ProjectQueue[];The per-project open TODO backlog (from collectQueue).
property totals
totals: { projects: number; openTodos: number;};interface DriverQuotaWindow
interface DriverQuotaWindow {}One quota window and how much of it the account has burned (#521).
The three concepts here are easy to confuse. DriverUsage is what *this run* spent. DriverRateLimit is a per-turn traffic light (are we still allowed to spend, and when does the window reset). This is the missing middle: the *proportion* of a window consumed, which is the only one of the three that can fill a progress bar.
property kind
kind: 'session' | 'week' | 'week-model' | 'unknown';Normalized window, so callers can gate without matching on prose.
sessionis Claude's 5-hour window,weekits all-models week, andweek-modela single model's week (Opus/Sonnet get their own).Note there is deliberately no
day: Claude measures a 5-hour session and a week, and nothing per day (#519 was specced against a daily limit that does not exist).
property label
label: string;The window's name exactly as the agent phrased it, e.g.
"Current session".
property percentUsed
percentUsed: number;How much of the window is gone, 0-100.
property resetsAtText
resetsAtText?: string;When the window resets, as the agent worded it (`"Jul 18 at 7am (Asia/Jerusalem)"`). Prose, not a timestamp: the agent prints no year, so parsing it to an epoch would be guesswork. DriverRateLimit.resetsAt carries the exact epoch for the window it reports on.
interface FileChange
interface FileChange {}One changed file in a session's Changes list (#817): what moved, and by how much.
interface FileContent
interface FileContent {}One unchanged file's contents for the tree's hover card (#828).
property binary
binary: boolean;Not UTF-8 text, so there is nothing to render.
property path
path: string;The repo-relative path asked for.
property text
text: string;The file's text, cut at MAX_PREVIEW_LINES. Empty when binary.
property truncated
truncated: boolean;The file was longer than the cap and was cut.
interface FileDiff
interface FileDiff {}One file's diff, capped so a hover card can render it.
property added
added: number;property binary
binary: boolean;Nothing textual to show (git reports a binary change, or the file is not UTF-8 text).
property patch
patch: string;Unified diff body, hunks only (git's
diff --git/ index preamble is dropped).
property path
path: string;The repo-relative path asked for.
property removed
removed: number;property status
status: FileGitStatus;property truncated
truncated: boolean;The patch hit the preview cap and was cut.
interface FrameworkFileConfig
interface FrameworkFileConfig {}The per-repo session defaults persisted in
the-framework.yml: the prompt switches and how far a finished session publishes itself, so a repo's config travels with the code instead of being chosen again every session.
property handoff
handoff?: HandoffLevel;How far a finished session publishes itself (#1102/#1173/#1216/B5):
local,push,prormerge. Defaultpr. Whether a session publishes itself is a fact about the repo, so it belongs in the file that travels with it.mergehas to be asked for out loud: publishing a branch is reversible, landing it on the default branch is not. Meant for work whose review already happened before the session — the quick-win and consensual routines merge what a plan the human could veto already settled.
property transparent
transparent?: boolean;Transparent mode (#625): make every agent in this project a raw
claude -p— no framework system prompt, no emit protocols, no consumption guard, no dashboard, no TODO loop. The coarse "only-pick-what-you-need" master off-switch, at the per-project tier. Defaultfalse.
property vanilla
vanilla?: boolean;Remove the built-in #326 system prompt, keeping the session controls. Default
false.One name for one concept (C3). This key used to be
antiLazyPill— the historical name of the prompt's ancestor (#301) — spelled the other way round from thevanillait mapped to everywhere else, so the file, the preference and the agent option each said the same thing in a different direction and three comments apologised for it.
interface GitStatus
interface GitStatus {}A project's git status for the panel.
interface HandoffState
interface HandoffState {}What a session will do with its work when it ends (#1102), and what it did.
property merge
merge: boolean;Merge the PR once opened (#1216) — armed at launch, no checkbox, never changes mid-run. Unlike the pair above this defaults to off: merging is opt-in, so a stream from before the event carried it (#1382) must not read as an agent that will land on main by itself.
property pr
pr: boolean;Open a draft PR on finish. Implies push.
property push
push: boolean;Push the branch to
originon finish.
property result
result?: | { outcome: 'skipped'; reason: AutoHandoffSkip; } | { outcome: 'done'; url?: string; } | { outcome: 'failed'; error: string; };How the handoff ended, once it has run. Absent while the session is still going.
interface HotTicket
interface HotTicket {}One ticket surfaced on the Overview's hot-tickets card, tagged with its project and lane.
property agentId
agentId?: string;An agent is implementing this ticket right now (#1117): its id, for the card to link into.
The difference between "someone planned this at some point" and "this is being coded as you look at it", which the plan/spike proxy could not tell apart. Only set for a ticket a live agent actually recorded (
AgentMeta.ticket), so absent still means the lane was inferred.
property bucket
bucket: HotBucket;property projectId
projectId: string;property projectName
projectName: string;property ticket
ticket: WorkspaceTicket;interface Intervention
interface Intervention {}One item awaiting the human. Two kinds: an open
prto review/merge or close, and anawaitingrun paused on a choice gate. The card, the browser hook, and the Discord watcher all iterate the flat list, branching onkindfor the fields that differ.
property agentId
agentId?: string;Which run this is about (
awaiting#738 /unpushed): a project has several agents.
property awaitId
awaitId?: string;The parked gate's id (
awaitingonly) — its stable identity, so it notifies exactly once.
property branch
branch?: string;The branch the work is sitting on (
unpushedonly).
property commits
commits?: number;How many commits are waiting (
unpushedonly).
property createdAt
createdAt?: string;When the PR was opened (
pr) or the agent last updated (the other two), ISO, for ordering.
property kind
kind: 'pr' | 'awaiting' | 'unpushed';pr= an open PR to review/merge or close;awaiting= an agent paused on a choice gate (#636);unpushed= a finished agent whose branch has commits that were never pushed (#860).
property number
number?: number;The PR number (
pronly).
property projectId
projectId: string;property projectName
projectName: string;property title
title: string;property url
url: string;Where to act: the PR on GitHub (
pr), or the dashboard (the other two, when the URL is known).
interface OnboardingSuggestion
interface OnboardingSuggestion {}What the Onboarding checklist (#958) needs and no other read carries: the server's own working directory, offered as the one-click first project.
Both fields are null where adding projects is not wired (the relay), so a public host never discloses its filesystem layout.
property cwd
cwd: string | null;The server's working directory, or null when it cannot be offered.
property cwdProjectId
cwdProjectId: string | null;The project id for cwd when it is already registered, else null.
interface OpenQuestion
interface OpenQuestion {}One session's open question: the full gate, answerable from wherever it is rendered.
property agentId
agentId: string;property choice
choice: ChoiceRequest;property intent
intent?: string;What the agent was asked to do, for a card whose session never named itself.
property projectId
projectId: string;property projectName
projectName: string;property sessionName
sessionName?: string;The session's name (#326) when it chose one — the card's label; else fall back to intent.
property updatedAt
updatedAt?: string;When the agent last spoke, ISO: what the longest-waiting-first order sorts on.
interface Overview
interface Overview {}The cross-project Overview payload.
interface Preferences
interface Preferences {}property autoPm
autoPm?: boolean;Auto PM (#685): let the daemon start a PM agent by itself when the agent queue has run dry and there is plenty of budget left, so leftover subscription quota goes on the roadmap instead of expiring. **Absent = off**: it spends the user's allowance without being asked, so it is opt-in like notifyDiscord rather than a baseline.
property autoPmConcurrency
autoPmConcurrency?: number;How many agents the routine may keep going at once on one project (#1204). Absent defaults to
DEFAULT_AUTO_PM_CONCURRENCY, and the value is clamped toMAX_AUTO_PM_CONCURRENCY.Only the draining routine fans out: it takes work *off* the queue, one pinned entry per agent, so several at once do disjoint work. The rotation invents work and each of its jobs rewrites the queue file, so it stays one agent per tick whatever this says.
property autoPmOptOut
autoPmOptOut?: string[];The routines autoPm must not fire, by AutoPmJob.name (#1209). Absent or empty = every routine runs, which is what the sweep did before this existed.
Opted *out* rather than opted in, so the list only ever names exceptions: a routine added in a later version is on for everyone, instead of silently never running for whoever saved the setting before it shipped. It names routines rather than indexing them for the same reason AutoPmJob.drains is a flag — a reorder must not move which one is switched off.
property autoSpendOffset
autoSpendOffset?: number;How far the automatic-consumption limit sits from the quota boundary, in percentage points (#960). Absent defaults to DEFAULT_SPEND_OFFSET — a half-day cushion ahead of the boundary — rather than sitting exactly on it (#960 Edit).
Negative holds unattended work back further; positive lets it borrow into the days still to come. It is an *offset* rather than an absolute percentage so the limit travels with the boundary as the week goes on, instead of being overtaken by it on day two.
property bridge
bridge?: boolean;The browser bridge (#1237): let an extension running in the user's own Claude session report the question a Claude web agent is parked on, so it shows in the dashboard rather than only on claude.ai. **Absent = off.** It opens the daemon's one route reachable from another origin, so it is opt-in rather than a baseline, and turning it on is what mints the bridge token.
property browser
browser?: boolean;Give the agent a real browser via chrome-devtools-mcp during the agent (#452); maps to
--browser.
property customPresets
customPresets?: CustomPreset[];User-defined presets (#626): the user's own saved prompts, shown beside the built-in presets.
property driver
driver?: string;Which coding agent drives the agent (#650):
claudeorcodex; maps to--agent. Absent = the default (claude).
property editor
editor?: string;Preferred editor for "Open in editor" (#727): an editor CLI (e.g.
code,cursor,zed). Absent falls back to$FRAMEWORK_EDITOR, thencode.
property handoff
handoff?: HandoffLevel;How far a finished session publishes itself (#1102/#1216/B5): keep it local, push the branch, open a draft PR, or merge that PR. Absent = DEFAULT_HANDOFF (
pr).Default-on, unlike most of this file, because it is what makes the handoff zero-config: the old behaviour was a button nobody was obliged to press, and work that stayed on a local branch nobody was told about (#860). A session can still opt out from its action bar.
property model
model?: string;The model to run on (#628), e.g.
opus/sonnet; maps to an agent's--model. Absent = the driver's default.
property notifyBrowser
notifyBrowser?: boolean;Fire a browser notification when a new item lands on the "needs you" queue (#627). Absent = on.
property notifyDiscord
notifyDiscord?: boolean;Post a Discord message when a new item lands on the "needs you" queue (#627). Absent = off: unlike the in-browser toggle, Discord reaches you when no dashboard is open, so it is opt-in. Gates the daemon watcher *on top of* a
DISCORD_WEBHOOKbeing set (the webhook is where to post; this is whether to).
property notifyHumanIntervention
notifyHumanIntervention?: boolean;The "needs you" category (#627): notify when an agent is awaiting your answer or a PR is ready to review. A *category* toggle, like notifyNewActivity, composing with the method toggles (notifyBrowser / notifyDiscord). **Absent = on**: unlike the other flat opt-in booleans, human-intervention pings are the baseline The Framework leans on, so an unset preference keeps them firing; a user turns them off explicitly.
property notifyNewActivity
notifyNewActivity?: boolean;Also notify on plain agent activity — an agent started, an agent finished (#627). The default-off counterpart to the always-on "needs you" notifications: it keeps you loosely informed of the pipeline moving even when nothing needs you. A *category* toggle: it composes with the method toggles (notifyBrowser / notifyDiscord), so activity reaches whichever are on.
property onBeforeMergeableQuality
onBeforeMergeableQuality?: boolean;On-before-mergeable prompt (#326): on setReadyForMerge(), queue the quality follow-ups as TODO entries.
property onboardingDismissed
onboardingDismissed?: boolean;Whether the Overview's Onboarding checklist has been dismissed (#958). Absent = show it, so a fresh install is walked through setup; dismissing only hides it on the Overview, and the same checklist stays available on the settings page.
property target
target?: AgentLocation;Where a run executes (#1050/#610):
local(this device, the default),actions(a fresh GitHub Actions runner) orweb(a Claude Code cloud session); maps to--run-on. Absent = local.
property theme
theme?: 'system' | 'light' | 'dark';Dashboard color theme (#725):
system(follow the OS, the default),light, ordark. Absent = system.
property transparent
transparent?: boolean;Transparent mode (#625): run the wrapped agent raw — no framework system prompt, emit protocols, consumption guard, dashboard, or TODO loop, so an agent is identical to
claude -p. The coarse master off-switch ("only pick what you need"); maps to--transparent. Absent = off.
property vanilla
vanilla?: boolean;interface ProjectError
interface ProjectError {}interface ProjectionRead
interface ProjectionRead<T> {}A projection over the registered projects, together with the projects it could actually see.
A project whose sources cannot be read contributes no items — which is exactly what a project with nothing waiting contributes.
wholeis what tells the two apart (#1623). Only a caller that keeps a baseline of what it has already announced needs the distinction; the panels that simply render the list readitemsand ignore it.
interface ProjectQueue
interface ProjectQueue {}One project's rolled-up TODO queue.
property items
items: QueueItem[];property open
open: number;Count of unchecked items (what is still queued).
property projectId
projectId: string;property projectName
projectName: string;property total
total: number;Count of all parsed items (open + done).
interface ProjectSummary
interface ProjectSummary {}One project's summary for the Projects sidebar (#314).
property activated
activated: boolean;True when the repo still has its
.the-framework/marker.
property errors
errors?: ProjectError[];What the daemon's background jobs currently find wrong with the project (#1500), oldest first — absent when nothing is. Not part of the summary itself: the dashboard's project list attaches it from the daemon's error state.
property fileConfig
fileConfig?: FrameworkFileConfig;The repo's committed run defaults from
the-framework.yml(#842), so the launcher can show what an agent there will actually resolve to. Read fresh on every summarize, which is what keeps it current after an edit; absent when the repo sets nothing (or the file is malformed, which loadFrameworkConfig reports as empty rather than failing).
property id
id: string;Registry id (stable, URL-safe).
property lastActivityAt
lastActivityAt?: string;ISO timestamp of the project's newest activity: its most recent session.
property name
name: string;Display name (the path's basename).
property path
path: string;Absolute repo path.
interface ProjectTickets
interface ProjectTickets {}One project's tickets, for the cross-project Tickets page (#1144).
property projectId
projectId: string;property projectName
projectName: string;property tickets
tickets: WorkspaceTicket[];interface QuotaBoundaryStatus
interface QuotaBoundaryStatus {}Where the account stands against its boundary.
property boundary
boundary: QuotaBoundary;property limit
limit: QuotaLimit;The line in force, which is the boundary unless the user moved it (#960).
property reached
reached: BoundaryWindow | null;The window that has reached the limit, or
nullwhile there is room.
property windows
windows: BoundaryWindow[];The windows in force: the account's week, plus the selected model's own week when we can tell which it is.
interface QuotaView
interface QuotaView {}Everything the dashboard needs to draw the usage panel (#533): the account's own windows, and where they stand against the quota boundary (#879).
property boundary
boundary?: QuotaBoundaryStatus;Where the account stands against its boundary (#879). Absent when there is no reading, or when the week's reset could not be placed — which is "we don't know", not "nothing is allowed".
property readAt
readAt?: number;When the reading was taken, epoch ms. Absent when there has never been one.
property unavailable
unavailable?: DriverQuotaUnavailableReason;Why there is no reading, when there isn't one. Present alongside stale
windowstoo: the last good reading is kept through a blip, and this says the newest attempt failed, so the UI can mark it stale rather than blank it.
property windows
windows: DriverQuotaWindow[];The account's quota windows as the agent reported them (session, week, and a week per model). Empty when we have no reading at all — check unavailable before reading that as "nothing used".
interface RecentAgent
interface RecentAgent {}One recent session, tagged with the project it belongs to, for the cross-project rail.
property agent
agent: AgentMeta;property projectId
projectId: string;property projectName
projectName: string;interface SessionInfo
interface SessionInfo {}The wrapped agent session (#431): its id and a deep link, when one is known.
property driver
driver?: string;property fake
fake?: boolean;property model
model?: string;The model id the current leg's agent was started with (#1438). Folded per leg like the driver/workspace: the latest
sessionevent wins, and a leg that recorded none clears it.
property sessionId
sessionId?: string;property sessionLink
sessionLink?: string;property workspace
workspace?: string;The directory the agent ran in (#1195), from the opening
sessionevent.Taken from the event rather than the filesystem on purpose: an agent that finishes cleanly has its worktree removed (
tearDownWorktree), so the event is the only surviving record of where the session lived — and that path is exactly whatclaude --resumeneeds to find it again.
interface TicketsMeta
interface TicketsMeta {}What
tickets/meta.jsonrecords about the last import (#1208).Written by the agent doing the import, in the same commit as the tickets it describes, and read here so the view can say when
tickets/last caught up with GitHub. A repo imported before this file existed simply has no stamp, which reads as "not known" rather than as an error.
property lastImportedAt
lastImportedAt?: string;ISO 8601 UTC, the moment the last import began. Absent when nothing has recorded one.
interface WorkspaceDoc
interface WorkspaceDoc {}One surfaced document: its filename and current contents.
interface WorkspaceTicket
interface WorkspaceTicket {}One ticket in
tickets/(#697). The dashboard lists these so the backlog the agent plans from is visible without opening the repo.
property date
date: string;ISO 8601 (#1144/#1265). The
<DATE>_<SLUG>.mdfilename's date when it has one — the format every ticket is written in, imports included — else the file's mtime, for the rare ticket that predates the format. Moves forward on an mtime-dated ticket edited in place (the GitHub update, #1208); a filename-dated one keeps the date it was created on, same as the file itself does.
property effort
effort?: number;The
Effort:its.plan.mdpreamble records (ticketing_format.md:0-10, 0 trivial, 10 takes months). Absent when unplanned or the plan names none.
property file
file: string;Filename inside
tickets/, which is also its identity.
property github
github?: TicketGithubLink;The optional
GitHub:key (GitHub: [#42](https://github.com/org/repo/issues/42)), split into the link text and the URL it points at.
property locked
locked?: boolean;Whether an agent holds this ticket (#1420): a
<name>.lock.mdclaim exists — it is planning the ticket or implementing it directly. Mutually informative withplannedrather than exclusive: the lock covers the ticket's whole life, so a locked ticket may also be planned while its agent keeps working.
property lockedBy
lockedBy?: string;Who the
.lock.mdnames, from itsCLAIMED: <holder>line (#1420) — shown so a human can tell whose claim they are about to release. Absent when the lock is missing or unreadable.
property planned
planned: boolean;Whether a
<name>.plan.mdsits beside it, i.e. #685 already planned it.
property priority
priority?: string;The optional
priority:key, verbatim (a0-10string;10acts immediately).
property summary
summary: string;The
## TLDRline, else the first prose line. Empty when the ticket has neither.
property title
title: string;The
#heading, else the filename made readable.
property topics
topics?: string[];The optional
topics:key (topics: [dx, ui]), as bare tags.
property uncertainty
uncertainty?: number;The
Uncertainty:its.plan.mdpreamble records (0-10, 0 an obvious implementation, 10 highly uncertain how). Absent when unplanned or the plan names none.
interface WorkspaceTicketDetail
interface WorkspaceTicketDetail extends WorkspaceTicket {}One ticket, with its entire markdown rather than just the head (#1144's detail page).
property content
content: string;The ticket's full text, unlike readTickets' head-only read.
Type Aliases
type AgentLocation
type AgentLocation = 'local' | 'actions' | 'web';Where an agent executes.
type AgentStatus
type AgentStatus = 'running' | 'done' | 'stopped' | 'failed';How an agent ended (or that it is still going).
type FrameworkEvent
type FrameworkEvent = /** * Emitted once at start: which agent is wrapped, the workspace, and a link. `model` is the * model id the driver was started with (#1438), recorded per leg — a continuation (#762) emits * its own `session` event and may run a different model, so readers fold the latest rather * than pinning the first. Absent when the agent left the agent on its own default. */ | { kind: 'session'; driver: string; workspace: string; fake: boolean; sessionLink?: string; model?: string; } /** * Emitted once the wrapped agent reports its real session id (not known at * start). Carries the live id and, when a link template was supplied, the * resolved URL to jump into that session (#165). Re-emitted if the id changes * (each Claude Code prompt is a fresh session), keeping the link current. */ | { kind: 'session-update'; sessionId: string; sessionLink?: string; } /** * The full system prompt sent to the wrapped agent for this agent (#343): the * #326 block plus any personas / skills / memory framing, exactly as passed to * the driver's system channel. Emitted once at session start so the dashboard * can show the normally-hidden prompt (the per-turn user prompts arrive as * `driver` `start` events, which already carry their text). Transparency, never * gated on. */ | { kind: 'system-prompt'; text: string; } /** What this session was asked for, emitted once as it opens (#211). */ | { kind: 'intent'; text: string; } /** The wrapped agent's own progress, forwarded verbatim (never gated on). */ | { kind: 'driver'; event: DriverEvent; } /** * The generated app is booted and serving. Emitted after a successful agent when * a serve config is set: the app is kept running so the user can open it, and * the dashboard shows a live preview link (torn down on Ctrl+C). */ | { kind: 'preview'; url: string; command: string; } /** * The agent's browser preview is up and listening on this loopback port (#813). * * Only the port travels. The dashboard reaches the stream through the daemon, which proxies * to this port, so the agent's bridge stays same-origin-invisible and unreachable from the web. * Frames themselves never enter the log: someone will type a password into that pane. */ | { kind: 'browser-stream'; port: number; } /** * The agent's browser is showing this page (#1455 item 6b): emitted for the first real * (http/https) page and again on every change of page, so the transcript can host the live * preview at its point of use rather than only in the rail. Only the URL travels — frames * never enter the log, same rule as `browser-stream`. Re-emitted after each `session` so the * row survives the dashboard's last-session slice (#829); readers fold repeats of the same * URL in place rather than stacking duplicates, like `view` re-shows. */ | { kind: 'browser'; url: string; } /** A framework-level log line. */ | { kind: 'log'; message: string; } /** * Something went wrong that only the user can fix (#1500), reported by the agent itself * through an `error` block rather than left in prose the reader has to notice. The headline * is the first line, the detail is the rest. * * An event, not a status: it says what happened at this point in the run and stays in the log * as history — nothing clears it, because nothing can un-happen it. The project-level errors a * background job finds between runs are the other half (project-errors.ts): those are * conditions that are true *now*, and clear themselves when the condition is gone. */ | { kind: 'error'; headline: string; detail?: string; } /** * An ad-hoc markdown view the agent pushed to show the user (#441), e.g. a plan, * a summary, or a diff writeup. Non-blocking (unlike a `choice`): the dashboard * renders it as a view in the right rail. `id` is stable per title, so re-showing * the same view updates it in place rather than stacking a duplicate. */ | { kind: 'view'; id: string; title: string; markdown: string; } /** * The agent named the session (#326): the `[a-z0-9-]` slug it chose (also its * `tf-<name>` branch), from a `setSessionName()` signal. Non-blocking; * the dashboard shows it as the agent's label. Re-emitted on a rename. */ | { kind: 'session-name'; name: string; } /** * The agent signalled `setReadyForMerge()` (#326): it believes the work is complete * and ready for human review. Non-blocking — it flips the agent's dashboard status from * building (orange) to ready (green); the on-before-mergeable quality prompts hang off it. */ | { kind: 'ready-for-merge'; } /** * The pull request the agent asked for (#1567/#1618), via an `open-pr` block: how an agent * opens a PR *through* the framework instead of running `gh pr create` itself, so the ticket's * issue reference and recording the number still apply. The title is the agent's name for the * work and the description is what changed; either may be absent when the agent wrote only the * other. Non-blocking; the end-of-agent handoff uses the latest one. */ | { kind: 'open-pr'; title?: string; description?: string; } /** * The #326 post-merge cleanup step settled (#835): it queued the quality follow-ups, * queued them but did not finish cleanly, or declined with a {@link OnBeforeMergeableSkip}. * * An event rather than stdout because the surfaces that need it cannot read stdout: a * dashboard-started run is spawned with `stdio: 'ignore'`. Emitted only when the option * was on, so an agent that never asked for the step stays quiet. */ | { kind: 'on-before-mergeable'; outcome: 'queued' | 'incomplete'; } | { kind: 'on-before-mergeable'; outcome: 'skipped'; reason: OnBeforeMergeableSkip; } /** * What the end-of-session handoff is armed to do (#1102), emitted at the start and again * whenever the dashboard's checkboxes change it. * * This is what makes the boxes survive a reload: the control channel carries the instruction, * but only an event reaches the agent's meta, which is the one thing a tab opened later can read. * * `merge` carries the auto-merge arming (#1216) so the armed line can say the most consequential * half of the plan (#1382): without it a merge-armed agent advertised "open a draft PR" and then * merged to main. Optional because journals written before #1382 lack it; absent reads as off, * the conservative display. It has no checkbox and never changes mid-run, so re-emits repeat it. */ | { kind: 'handoff-armed'; push: boolean; pr: boolean; merge?: boolean; } /** * The ticket this agent was started to implement (#1117), as a repo-relative `tickets/<file>.md`. * * Emitted once at start, and only when the framework itself chose the ticket — today that is the * [Drain queue] run, whose queue entry links back to the ticket it was queued from (#1164). An * event rather than a start argument for the usual reason: only an event reaches the agent's meta, * and the meta is what a dashboard tab opened mid-run reads. Absent means nobody knows what this * run is implementing, which is every hand-written prompt. */ | { kind: 'ticket'; path: string; } /** * The pull request this session's work is on (E6), the moment one is opened for it. * * An event for the same reason `ticket` and `branch` are: only an event reaches the agent's meta, * and the meta is what every later surface reads. Before this, each of them re-resolved the PR * live from the branch — trying the recorded branch, then the session-name branch, then the * run-id branch, and filtering the results by whether the PR predated the session — which is a * three-way guess plus a timestamp heuristic standing in for one integer nobody had written down. */ | { kind: 'pull-request'; number: number; url: string; } /** * The branch the agent's work is on (#1277), observed off the checkout rather than guessed: * emitted at start with the branch the agent actually begins on, and again when the framework * renames the run-id branch after the agent names the session. Folded to `AgentMeta.branch`, * which every surface resolves first — before this event the branch was stamped only at * teardown (#799), so any read before that guessed between three naming schemes. */ | { kind: 'branch'; branch: string; } /** * The hand-off anchor a cloud run pushed for its session to clone at (#1601): an empty commit * unique to this run, so the branch the session actually works on — a `claude/*` name of the * cloud's own choosing, never the designated run branch — is recognizable later by plain * ancestry. Folded to `AgentMeta.cloudAnchor`, which the daemon's adoption pass matches * against origin's `claude/*` heads once the session has pushed its work. */ | { kind: 'cloud-anchor'; sha: string; } /** * What the end-of-session handoff actually did (#1102): pushed and/or opened a draft PR, * declined for a reason that is not a fault, or failed at one of the two steps. * * Same reason as on-before-mergeable above: a dashboard-started agent has no stdout anyone reads, * so an outcome that is not an event is an outcome nobody learns. */ | { kind: 'handoff'; outcome: 'skipped'; reason: AutoHandoffSkip; merge?: AutoMergeOutcome; } | { kind: 'handoff'; outcome: 'done'; pushed: boolean; url?: string; number?: number; merge?: AutoMergeOutcome; } | { kind: 'handoff'; outcome: 'failed'; step: 'push' | 'pr'; error: string; } /** * The work has settled and the agent is parked on the user (#785): it stays open as a * conversation (#714), so its process is still alive and it still takes messages, but * the agent is not doing anything until you say something. * * Emitted each time the agent parks, and undone by the next `driver` `start` — so "is it * working or waiting for me" is answerable from the event log rather than inferred from * a status that only changes when the agent ends. */ | { kind: 'settled'; } /** * Cumulative token + cost usage for the agent so far (#322). Emitted after each * agent turn that reports usage; the dashboard renders a live spend readout and * the agent stops itself once `costUsd` reaches the budget cap, if one is set. * * `costUsd` is absent when the agent reports tokens but no price (#540), which * is also when no budget cap can fire. */ | { kind: 'usage'; costUsd?: number; inputTokens: number; outputTokens: number; cacheReadTokens: number; cacheCreationTokens: number; turns: number; } /** * The agent paused on an interactive choice (#304) and is awaiting a pick. The * dashboard renders the options with the recommended default pre-selected and * posts the pick back; a headless agent auto-accepts the recommended option. */ | ({ kind: 'choice'; } & ChoiceRequest) /** A pending {@link ChoiceRequest} was resolved — the agent continues on `picked` (one id, or the selected subset). */ | { kind: 'choice-resolved'; id: string; picked: string | readonly string[]; by: ChoiceBy; } /** * The agent finished. `ok` is false when it threw. `stopped` marks the common, * non-error case where the user interrupted it (the dashboard Stop button / * Ctrl+C), so a surface can show "stopped" rather than "failed". */ | { kind: 'end'; ok: boolean; stopped?: boolean; detail?: string; };The single event type the whole agent streams over. It unifies three sources so the dashboard (and terminal) render one timeline: the session's own narration (the moat: checklist verdicts, deploy), the wrapped agent's own black-box progress, and framework-level status. We own this stream (guardrail #2, #165) rather than surfacing the agent's transport directly.
type HotBucket
type HotBucket = 'in-progress' | 'ai-queue' | 'high-priority';Which lane of the "hot tickets" overview (#1139) a ticket sits in.
type ProjectErrorCode
type ProjectErrorCode = 'data-sync';What went wrong, by kind: the dashboard picks its wording from this, the message carries the detail.
Package Files (28)
- dist/agent-location.d.ts
- dist/agent-view.d.ts
- dist/auto-pm.d.ts
- dist/config.d.ts
- dist/dashboard/activity.d.ts
- dist/dashboard/agent-handoff.d.ts
- dist/dashboard/bridge-endpoints.d.ts
- dist/dashboard/bridge-store.d.ts
- dist/dashboard/dashboard.d.ts
- dist/dashboard/docs.d.ts
- dist/dashboard/file-diff.d.ts
- dist/dashboard/file-read.d.ts
- dist/dashboard/git-status.d.ts
- dist/dashboard/interventions.d.ts
- dist/dashboard/open-questions.d.ts
- dist/dashboard/overview.d.ts
- dist/dashboard/projects.d.ts
- dist/dashboard/queue.d.ts
- dist/dashboard/quota.d.ts
- dist/dashboard/tickets.d.ts
- dist/dashboard/types.d.ts
- dist/driver/types.d.ts
- dist/events.d.ts
- dist/index.d.ts
- dist/project-errors.d.ts
- dist/quota-boundary.d.ts
- dist/registry.d.ts
- dist/store/agent-store.d.ts
Dependencies (15)
Dev Dependencies (13)
Peer Dependencies (0)
No peer dependencies.
Badge
To add a badge like this oneto your package's README, use the codes available below.
You may also use Shields.io to create a custom badge linking to https://www.jsdocs.io/package/framework.
- Markdown[](https://www.jsdocs.io/package/framework)
- HTML<a href="https://www.jsdocs.io/package/framework"><img src="https://img.shields.io/badge/jsDocs.io-reference-blue" alt="jsDocs.io"></a>
- Updated .
Package analyzed in 5325 ms. - Missing or incorrect documentation? Open an issue for this package.
