frizz 0.13.9 → 0.13.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -12
- package/dist/frizz.js +57 -53
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -27,22 +27,20 @@ Frizz is for you if you have any of these opinions:
|
|
|
27
27
|
|
|
28
28
|
**Requirements.** Node 22.13+, and a [Claude Code](https://claude.com/claude-code) or [Codex](https://developers.openai.com/codex) subscription you are signed in to — Frizz drives the subscription you already pay for. Frizz brings its own pinned copy of each CLI (downloaded once, on first start), so the version on your PATH is yours to manage and never changes what a thread runs.
|
|
29
29
|
|
|
30
|
-
Then run it
|
|
30
|
+
Then run it, from anywhere.
|
|
31
31
|
|
|
32
32
|
```sh
|
|
33
|
-
$ cd path/to/acme
|
|
34
33
|
$ npx frizz
|
|
35
34
|
|
|
36
35
|
FRIZZ v0.4.0 ready in 4.0s
|
|
37
36
|
|
|
38
|
-
➜ Local: http://127.0.0.1:9393/
|
|
39
|
-
➜ Project: acme — path/to/acme
|
|
37
|
+
➜ Local: http://127.0.0.1:9393/
|
|
40
38
|
➜ Logs: ~/Library/Application Support/Frizz/projects/979dae3c-fe15-4038-817e-11d0e7491959/logs/frizz-2026-08-01T13-44-43-16931.log
|
|
41
39
|
|
|
42
40
|
press ctrl-c to stop · run with --debug for the full event feed
|
|
43
41
|
```
|
|
44
42
|
|
|
45
|
-
A browser tab opens at `http://127.0.0.1:9393
|
|
43
|
+
A browser tab opens on the dashboard at `http://127.0.0.1:9393/`. Add a **project** there — any folder: a repo, a jj checkout, or a folder of scripts. Frizz has no opinion about version control and does not require Git. Each project gets its own board at `/project/<name>`, and from then on running `npx frizz` inside that folder opens its board. Frizz always listens on port 9393 (19393 if something else holds it), and one server serves every project on the machine, so a second run joins the server already running rather than starting another. Runs on macOS, Linux, and Windows.
|
|
46
44
|
|
|
47
45
|
<p align="center">
|
|
48
46
|
<img src="assets/board.png" alt="The Frizz board: the project rail down the left, the composer and the queue of threads beside it, and on the right a card where an agent is asking an answerable question with numbered options drawn as keycaps, with its snooze clock and done check in the card's header." width="100%">
|
|
@@ -67,7 +65,7 @@ Frizz is a browser tab, a queue, and the agent CLIs you already pay for. It brin
|
|
|
67
65
|
|
|
68
66
|
### Projects
|
|
69
67
|
|
|
70
|
-
Every
|
|
68
|
+
Every folder you add becomes a project with its own board, all served by the one Frizz on your machine. The dashboard at `http://127.0.0.1:9393/` lists them, and it is where `npx frizz` lands when it is run outside one.
|
|
71
69
|
|
|
72
70
|
<p align="center">
|
|
73
71
|
<img src="assets/projects.png" alt="The Frizz home page: a rail of project icons down the left, and four project cards — design-system, acme-web, acme-api, frizz — each with its home-relative path and when it was last opened, plus an Add a project card." width="100%">
|
|
@@ -134,10 +132,11 @@ Frizz production launcher
|
|
|
134
132
|
|
|
135
133
|
Usage: npx frizz [options]
|
|
136
134
|
|
|
137
|
-
Run it
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
Run it anywhere. One server serves EVERY project on this machine, each at its own
|
|
136
|
+
/project/<name> URL, so a second run joins the one already going. In a folder that is already a
|
|
137
|
+
project it opens that project's board; anywhere else it opens the dashboard, where projects are
|
|
138
|
+
added. Runs the npm-resolved immutable Frizz package, then opens it in your default browser. Use
|
|
139
|
+
frizz-dev only for a source checkout.
|
|
141
140
|
|
|
142
141
|
Options:
|
|
143
142
|
--no-app print the URL without opening a browser
|
|
@@ -254,7 +253,7 @@ Frizz has its own small vocabulary. Most of it names a feature, so this doubles
|
|
|
254
253
|
| **Snooze** | Hide a card until later — an hour, tomorrow morning, or a date you pick — optionally with a follow-up prompt attached. |
|
|
255
254
|
| **Goal** | A standing prompt a thread receives on its own — every time it rests, on a clock, or both — until you switch it off or the agent says it's done. |
|
|
256
255
|
| **Scratchpad** | A thread's durable working memory, readable under its **Doc** tab. Where a worker keeps what a summary would otherwise lose: the approach, the alternatives it rejected, the decisions you made and reversed. |
|
|
257
|
-
| **`FRIZZ.md`** | An optional file at your repo root whose contents are injected into every thread, for when you want agents to follow your repo's own norms. Only agents Frizz starts read it.
|
|
256
|
+
| **`FRIZZ.md`** | An optional file at your repo root whose contents are injected into every thread, for when you want agents to follow your repo's own norms. Only agents Frizz starts read it. |
|
|
258
257
|
|
|
259
258
|
<br/>
|
|
260
259
|
|
|
@@ -267,7 +266,7 @@ Frizz has its own small vocabulary. Most of it names a feature, so this doubles
|
|
|
267
266
|
|
|
268
267
|
<h2 align="center">Contributing</h2>
|
|
269
268
|
|
|
270
|
-
Issues and pull requests are welcome. Fork the repo, branch off `main`, and open the PR against `main` — CI runs on every pull request.
|
|
269
|
+
Issues and pull requests are welcome. Fork the repo, branch off `main`, and open the PR against `main` — CI runs on every pull request. Keep **Allow edits by maintainers** checked (GitHub offers it only on forks in a personal account, not an organization), so a follow-up commit from the maintainer can land in your PR rather than separately on `main`.
|
|
271
270
|
|
|
272
271
|
Three checks run in CI, and they need no install:
|
|
273
272
|
|
package/dist/frizz.js
CHANGED
|
@@ -926,6 +926,9 @@ function frizzRoots() {
|
|
|
926
926
|
function projectStateDir(projectId, home) {
|
|
927
927
|
return join3(home ? frizzPaths({ home }).data : frizzRoots().data, "projects", projectId);
|
|
928
928
|
}
|
|
929
|
+
function launchHostDir(home) {
|
|
930
|
+
return join3(home ? frizzPaths({ home }).data : frizzRoots().data, "host");
|
|
931
|
+
}
|
|
929
932
|
var LEGACY_DIR_NAME, cached;
|
|
930
933
|
var init_frizz_paths = __esm({
|
|
931
934
|
"packages/server/src/frizz-paths.ts"() {
|
|
@@ -13275,31 +13278,6 @@ var init_drainable_worker = __esm({
|
|
|
13275
13278
|
}
|
|
13276
13279
|
});
|
|
13277
13280
|
|
|
13278
|
-
// packages/shared/src/frizz-md.ts
|
|
13279
|
-
var FrizzMdLanding, FrizzMdAutonomy, FRIZZ_MD_NOTES_MAX, FrizzMdAnswers, FrizzMdStatus;
|
|
13280
|
-
var init_frizz_md = __esm({
|
|
13281
|
-
"packages/shared/src/frizz-md.ts"() {
|
|
13282
|
-
"use strict";
|
|
13283
|
-
init_zod();
|
|
13284
|
-
FrizzMdLanding = external_exports.enum(["pull-request", "main", "main-push", "branch"]);
|
|
13285
|
-
FrizzMdAutonomy = external_exports.enum(["decide", "balanced", "check-in"]);
|
|
13286
|
-
FRIZZ_MD_NOTES_MAX = 8e3;
|
|
13287
|
-
FrizzMdAnswers = external_exports.object({
|
|
13288
|
-
landing: FrizzMdLanding,
|
|
13289
|
-
autonomy: FrizzMdAutonomy,
|
|
13290
|
-
notes: external_exports.string().max(FRIZZ_MD_NOTES_MAX)
|
|
13291
|
-
}).strict();
|
|
13292
|
-
FrizzMdStatus = external_exports.object({
|
|
13293
|
-
/** A FRIZZ.md is already at the project root: the project has its rules, so nothing is asked. */
|
|
13294
|
-
exists: external_exports.boolean(),
|
|
13295
|
-
/** The operator skipped the questionnaire for this project: it is not asked again. */
|
|
13296
|
-
skipped: external_exports.boolean(),
|
|
13297
|
-
/** The branch the landing rules name — the remote's default, else the checked-out one, else `main`. */
|
|
13298
|
-
defaultBranch: external_exports.string()
|
|
13299
|
-
});
|
|
13300
|
-
}
|
|
13301
|
-
});
|
|
13302
|
-
|
|
13303
13281
|
// packages/shared/src/receipt-bus.ts
|
|
13304
13282
|
var init_receipt_bus = __esm({
|
|
13305
13283
|
"packages/shared/src/receipt-bus.ts"() {
|
|
@@ -13547,7 +13525,7 @@ function requireEffortOutsideAcp(profile, ctx) {
|
|
|
13547
13525
|
function fallbackPort(base) {
|
|
13548
13526
|
return base + 1e4;
|
|
13549
13527
|
}
|
|
13550
|
-
var import_yaml, ATTACHMENT_IMAGE_EXTENSIONS, ATTACHMENT_TEXT_EXTENSIONS, ATTACHMENT_OFFICE_EXTENSIONS, ATTACHMENT_DATA_EXTENSIONS, ATTACHMENT_ARCHIVE_EXTENSIONS, ATTACHMENT_DOC_EXTENSIONS, ATTACHMENT_EXTENSIONS, ATTACHMENT_MAX_BASE64_CHARS, ATTACHMENT_MAX_BYTES, ATTACHMENT_EXT_SET, ATTACHMENT_ACCEPT, FrizzStatus, BlockMechanism, RuntimeState, Backend, CodexModel, ClaudeModel, AcpAgent, AcpAgentModel, AcpAgentModels, AcpAgentModelsInput, ThreadProfileOption, ThreadAgent, SubAgentView, BgShellView, CompletionHoldOp, CompletionHold, AskOption, AskQuestion, PendingAsk, AwaitingHint, RETIRED_AWAITING_KINDS, RETIRED_LINE_RE, AWAITING_FOR_MAX_MS, SnoozeUntil, SNOOZE_PROMPT_MAX, SnoozePrompt, RECURRING_PROMPT_MAX, RECURRING_MIN_INTERVAL_SECONDS, RECURRING_MAX_INTERVAL_SECONDS, RecurringPromptText, RecurringIntervalSeconds, ThreadRecurringPrompt, TIMER_PROMPT_MAX, TIMER_MAX_DELAY_SECONDS, TimerPromptText, SIGNOFF_NUDGE_MARKER, SIGNOFF_NUDGE_MESSAGE, SIGNOFF_NUDGE_MESSAGE_NEEDS_INPUT, ThreadWatchKind, GithubChecksState, GithubMergeState, GithubWatchStatus, GithubIssueStatus, ThreadWatchView, PR_WATCH_FOR_MAX_MS, PR_WATCH_DEFAULT_FOR_MS, PrWatchView, AddOwnPrWatchInput, AddOwnPrWatchResult, DropOwnPrWatchInput, DropOwnPrWatchResult, OwnWatchKind, AddOwnWatchInput, OwnWatchView, AddOwnWatchResult, DropOwnWatchInput, DropOwnWatchResult, AskQuestionKind, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, SECRET_TTL_MS, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, SettledQuestionView, ThreadSettledQuestionsResult, MarkOwnDoneInput, MarkOwnDoneResult, ListOwnPrWatchesInput, OwnPrWatchesResult, ThreadTimerView, ThreadFence, LimitWindow, LimitPause, ProviderError, ThreadLinkView, UpsertOwnLinkInput, UpsertOwnLinkResult, DropOwnLinkInput, DropOwnLinkResult, LiveTool, ThreadView, BoardErrorItem, BoardSnapshot, QuotaWindow, ProviderQuota, QuotaSnapshot, ProviderAuth, AccountEmails, AuthSnapshot, AccountBackend, AccountLogoutInput, AccountLogoutResult, PermissionMode, LocalFileOpener, Settings, DispatchProviderPreferences, DispatchPreferences, DispatchProfileSnapshotShape, DispatchProfileSnapshot, SetDispatchPreferenceInput, DispatchInput, ADOPT_THREAD_MESSAGE_MAX_CHARS, AdoptThreadInput, AdoptThreadResult, AdoptSessionInput, FollowUpInput, DismissFailedFollowUpInput, DismissFailedFollowUpResult, UnqueueFollowUpInput, UnqueueFollowUpResult, DeliverQueuedNowInput, DeliverQueuedNowResult, CompactThreadInput, SetThreadSnoozeInput, SetThreadPinnedInput, SetThreadRecurringPromptInput, SetOwnThreadRecurringPromptInput, SetOwnThreadRecurringPromptResult, GetOwnThreadRecurringPromptInput, OwnThreadRecurringPromptResult, SetOwnThreadTimerInput, CancelOwnThreadTimerInput, ListOwnThreadTimersInput, OwnThreadTimersResult, ThreadActivityItem, ListOwnThreadActivityInput, OwnThreadActivityResult, SetOwnThreadTimerResult, CancelOwnThreadTimerResult, SetOwnThreadStopHookInput, SetOwnThreadHeartbeatInput, ThreadPluginReloadResult, RenameThreadInput, AiRenameThreadInput, AiRenameThreadResult, SetOwnThreadTitleInput, SetOwnThreadTitleResult, SetThreadPermissionInput, SetThreadPermissionResult, ThreadProfileOptionsInput, ThreadProfileOptionsResult, ThreadSkillSource, ThreadSkill, ThreadSkillsInput, ThreadSkillsResult, SetThreadProfileInput, SetThreadProfileResult, UpgradeThreadModelInput, UpgradeThreadModelResult, DISPATCH_TASK_BANNER, DISPATCH_TASK_BANNER_MARKER, HUMAN_GAP_FLOOR_MS, GithubWakeItem, GithubWakeSteer, WAKE_SCOPE, WAKE_REF, WAKE_SINGLE, WAKE_MULTI_HEAD, PR_WATCH_FINISHED, PR_WATCH_CI_PASSED, PR_WATCH_CI_GATED, PR_WATCH_STATE, PR_WATCH_CI_FAILED, GithubStatus, GithubRefCard, GithubRefPreviewInput, GithubRefPreviewResult, GithubItem, GithubListInput, GithubListResult, GithubBatchInput, GithubBatchResult, BoardMeta, ServerEvent, TranscriptEdit, TranscriptTodo, TranscriptToolCall, TranscriptPart, TranscriptMessage, TranscriptPageCursor, EditedFile, TranscriptPage, TranscriptEarlierInput, SocketTranscriptSlug, SocketFilePath, SocketTranscriptClientMsg, SocketFileClientMsg, SocketClientMsg, ProjectCard, ProjectRailCounts, PROJECT_ICON_MAX_BASE64_CHARS, DirectoryPickResult, ThreadLocation, FRIZZ_ROUTE_PREFIX, DEFAULT_PORT;
|
|
13528
|
+
var import_yaml, ATTACHMENT_IMAGE_EXTENSIONS, ATTACHMENT_TEXT_EXTENSIONS, ATTACHMENT_OFFICE_EXTENSIONS, ATTACHMENT_DATA_EXTENSIONS, ATTACHMENT_ARCHIVE_EXTENSIONS, ATTACHMENT_DOC_EXTENSIONS, ATTACHMENT_EXTENSIONS, ATTACHMENT_MAX_BASE64_CHARS, ATTACHMENT_MAX_BYTES, ATTACHMENT_EXT_SET, ATTACHMENT_ACCEPT, FrizzStatus, BlockMechanism, RuntimeState, Backend, CodexModel, ClaudeModel, AcpAgent, AcpAgentModel, AcpAgentModels, AcpAgentModelsInput, ThreadProfileOption, ThreadAgent, SubAgentView, BgShellView, CompletionHoldOp, CompletionHold, AskOption, AskQuestion, PendingAsk, AwaitingHint, RETIRED_AWAITING_KINDS, RETIRED_LINE_RE, AWAITING_FOR_MAX_MS, SnoozeUntil, SNOOZE_PROMPT_MAX, SnoozePrompt, RECURRING_PROMPT_MAX, RECURRING_MIN_INTERVAL_SECONDS, RECURRING_MAX_INTERVAL_SECONDS, RecurringPromptText, RecurringIntervalSeconds, ThreadRecurringPrompt, TIMER_PROMPT_MAX, TIMER_MAX_DELAY_SECONDS, TimerPromptText, SIGNOFF_NUDGE_MARKER, SIGNOFF_NUDGE_MESSAGE, SIGNOFF_NUDGE_MESSAGE_NEEDS_INPUT, ThreadWatchKind, GithubChecksState, GithubMergeState, GithubWatchStatus, GithubIssueStatus, ThreadWatchView, PR_WATCH_FOR_MAX_MS, PR_WATCH_DEFAULT_FOR_MS, PrWatchView, AddOwnPrWatchInput, AddOwnPrWatchResult, DropOwnPrWatchInput, DropOwnPrWatchResult, OwnWatchKind, AddOwnWatchInput, OwnWatchView, AddOwnWatchResult, DropOwnWatchInput, DropOwnWatchResult, AskQuestionKind, AskedOptionSchema, AskedQuestionSchema, AskInput, RegisteredQuestionView, SECRET_TTL_MS, AskResult, UnaskInput, UnaskResult, QuestionAnswerSchema, AnswerQuestionsInput, AnswerQuestionsResult, DismissQuestionsInput, DismissQuestionsResult, SettledQuestionView, ThreadSettledQuestionsResult, MarkOwnDoneInput, MarkOwnDoneResult, ListOwnPrWatchesInput, OwnPrWatchesResult, ThreadTimerView, ThreadFence, LimitWindow, LimitPause, ProviderError, ThreadLinkView, UpsertOwnLinkInput, UpsertOwnLinkResult, DropOwnLinkInput, DropOwnLinkResult, LiveTool, ThreadView, BoardErrorItem, BoardSnapshot, QuotaWindow, ProviderQuota, QuotaSnapshot, ProviderAuth, AccountEmails, AuthSnapshot, AccountBackend, AccountLogoutInput, AccountLogoutResult, PermissionMode, LocalFileOpener, Settings, DispatchProviderPreferences, DispatchPreferences, DispatchProfileSnapshotShape, DispatchProfileSnapshot, SetDispatchPreferenceInput, DispatchInput, ADOPT_THREAD_MESSAGE_MAX_CHARS, AdoptThreadInput, AdoptThreadResult, AdoptSessionInput, FollowUpInput, SteerThreadInput, SteerThreadResult, DismissFailedFollowUpInput, DismissFailedFollowUpResult, UnqueueFollowUpInput, UnqueueFollowUpResult, DeliverQueuedNowInput, DeliverQueuedNowResult, CompactThreadInput, SetThreadSnoozeInput, SetThreadPinnedInput, SetThreadRecurringPromptInput, SetOwnThreadRecurringPromptInput, SetOwnThreadRecurringPromptResult, GetOwnThreadRecurringPromptInput, OwnThreadRecurringPromptResult, SetOwnThreadTimerInput, CancelOwnThreadTimerInput, ListOwnThreadTimersInput, OwnThreadTimersResult, ThreadActivityItem, ListOwnThreadActivityInput, OwnThreadActivityResult, SetOwnThreadTimerResult, CancelOwnThreadTimerResult, SetOwnThreadStopHookInput, SetOwnThreadHeartbeatInput, ThreadPluginReloadResult, RenameThreadInput, AiRenameThreadInput, AiRenameThreadResult, SetOwnThreadTitleInput, SetOwnThreadTitleResult, SetThreadPermissionInput, SetThreadPermissionResult, ThreadProfileOptionsInput, ThreadProfileOptionsResult, ThreadSkillSource, ThreadSkill, ThreadSkillsInput, ThreadSkillsResult, SetThreadProfileInput, SetThreadProfileResult, UpgradeThreadModelInput, UpgradeThreadModelResult, DISPATCH_TASK_BANNER, DISPATCH_TASK_BANNER_MARKER, HUMAN_GAP_FLOOR_MS, GithubWakeItem, GithubWakeSteer, WAKE_SCOPE, WAKE_REF, WAKE_SINGLE, WAKE_MULTI_HEAD, PR_WATCH_FINISHED, PR_WATCH_CI_PASSED, PR_WATCH_CI_GATED, PR_WATCH_STATE, PR_WATCH_CI_FAILED, GithubStatus, GithubRefCard, GithubRefPreviewInput, GithubRefPreviewResult, GithubItem, GithubListInput, GithubListResult, GithubBatchInput, GithubBatchResult, BoardMeta, ServerEvent, TranscriptEdit, TranscriptTodo, TranscriptToolCall, TranscriptPart, TranscriptMessage, TranscriptPageCursor, EditedFile, TranscriptPage, TranscriptEarlierInput, SocketTranscriptSlug, SocketFilePath, SocketTranscriptClientMsg, SocketFileClientMsg, SocketClientMsg, ProjectCard, ProjectRailCounts, PROJECT_ICON_MAX_BASE64_CHARS, DirectoryPickResult, ThreadLocation, FRIZZ_ROUTE_PREFIX, DEFAULT_PORT;
|
|
13551
13529
|
var init_src = __esm({
|
|
13552
13530
|
"packages/shared/src/index.ts"() {
|
|
13553
13531
|
"use strict";
|
|
@@ -13560,7 +13538,6 @@ var init_src = __esm({
|
|
|
13560
13538
|
init_code_fences();
|
|
13561
13539
|
init_delta();
|
|
13562
13540
|
init_drainable_worker();
|
|
13563
|
-
init_frizz_md();
|
|
13564
13541
|
init_interactions();
|
|
13565
13542
|
init_receipt_bus();
|
|
13566
13543
|
init_relay_protocol();
|
|
@@ -13662,7 +13639,7 @@ var init_src = __esm({
|
|
|
13662
13639
|
"running",
|
|
13663
13640
|
// process alive, turn in flight
|
|
13664
13641
|
"perm-prompt",
|
|
13665
|
-
// process alive,
|
|
13642
|
+
// process alive, parked on a permission request a person has not answered yet
|
|
13666
13643
|
"turn-idle",
|
|
13667
13644
|
// process alive, waiting at the prompt
|
|
13668
13645
|
"exited"
|
|
@@ -14859,6 +14836,19 @@ var init_src = __esm({
|
|
|
14859
14836
|
// ambiguous, and only the operator decides to risk a second copy.
|
|
14860
14837
|
supersedes: external_exports.string().min(1).max(200).optional()
|
|
14861
14838
|
});
|
|
14839
|
+
SteerThreadInput = external_exports.object({
|
|
14840
|
+
from: ThreadSlug,
|
|
14841
|
+
to: ThreadSlug,
|
|
14842
|
+
message: external_exports.string().min(1).max(1e5)
|
|
14843
|
+
}).strict();
|
|
14844
|
+
SteerThreadResult = external_exports.object({
|
|
14845
|
+
slug: ThreadSlug,
|
|
14846
|
+
title: external_exports.string(),
|
|
14847
|
+
// What the target was doing when the message arrived: `running` ⇒ it reads it at its next tool
|
|
14848
|
+
// boundary; `resting` ⇒ the message started its next turn; `reopened` ⇒ it was marked done and this
|
|
14849
|
+
// message put it back on the board.
|
|
14850
|
+
delivery: external_exports.enum(["running", "resting", "reopened"])
|
|
14851
|
+
}).strict();
|
|
14862
14852
|
DismissFailedFollowUpInput = external_exports.object({
|
|
14863
14853
|
slug: ThreadSlug,
|
|
14864
14854
|
deliveryId: external_exports.string().min(1).max(200)
|
|
@@ -21199,11 +21189,13 @@ function readRegistry(home = homedir9()) {
|
|
|
21199
21189
|
try {
|
|
21200
21190
|
const parsed = JSON.parse(raw);
|
|
21201
21191
|
if (parsed?.version !== 1 || !Array.isArray(parsed.projects)) return { ...EMPTY, projects: [] };
|
|
21192
|
+
const forgotten = Array.isArray(parsed.forgotten) ? parsed.forgotten.filter((id) => typeof id === "string") : [];
|
|
21202
21193
|
return {
|
|
21203
21194
|
version: 1,
|
|
21204
21195
|
projects: parsed.projects.filter(
|
|
21205
21196
|
(p) => p && typeof p.id === "string" && typeof p.path === "string" && typeof p.slug === "string"
|
|
21206
|
-
)
|
|
21197
|
+
),
|
|
21198
|
+
...forgotten.length > 0 ? { forgotten } : {}
|
|
21207
21199
|
};
|
|
21208
21200
|
} catch {
|
|
21209
21201
|
return { ...EMPTY, projects: [] };
|
|
@@ -21267,7 +21259,12 @@ function canonicalPath(dir) {
|
|
|
21267
21259
|
}
|
|
21268
21260
|
function registerProject(input, home = homedir9()) {
|
|
21269
21261
|
input = { ...input, dir: canonicalPath(input.dir) };
|
|
21262
|
+
if (input.dir === canonicalPath(launchHostDir(home))) return { action: "unlisted" };
|
|
21270
21263
|
const registry = readRegistry(home);
|
|
21264
|
+
if (registry.forgotten) {
|
|
21265
|
+
registry.forgotten = registry.forgotten.filter((id) => id !== input.id);
|
|
21266
|
+
if (registry.forgotten.length === 0) delete registry.forgotten;
|
|
21267
|
+
}
|
|
21271
21268
|
const at = (input.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
|
|
21272
21269
|
const byId = registry.projects.find((p) => p.id === input.id);
|
|
21273
21270
|
if (byId) {
|
|
@@ -25461,6 +25458,7 @@ init_boot_progress();
|
|
|
25461
25458
|
init_frizz_paths();
|
|
25462
25459
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
25463
25460
|
import { createServer as createServer2 } from "node:net";
|
|
25461
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
25464
25462
|
import { existsSync as existsSync6, mkdirSync as mkdirSync10, mkdtempSync, readdirSync as readdirSync3, readFileSync as readFileSync10, realpathSync as realpathSync5, rmSync as rmSync8, symlinkSync as symlinkSync2, writeFileSync as writeFileSync10 } from "node:fs";
|
|
25465
25463
|
import { homedir as homedir10, tmpdir as tmpdir2 } from "node:os";
|
|
25466
25464
|
import { basename as basename5, dirname as dirname10, join as join13, resolve as resolve4 } from "node:path";
|
|
@@ -25600,6 +25598,7 @@ function prepareSandbox(env = process.env, realHome = homedir10()) {
|
|
|
25600
25598
|
} catch {
|
|
25601
25599
|
throw new Error("--sandbox mints a throwaway git repository and git is not available \u2014 install git, or play in a repo of your own with a temp HOME");
|
|
25602
25600
|
}
|
|
25601
|
+
writeProjectIdFile(project, randomUUID5());
|
|
25603
25602
|
process.chdir(project);
|
|
25604
25603
|
return { home, project };
|
|
25605
25604
|
}
|
|
@@ -25643,13 +25642,19 @@ function cleanupSandbox(home) {
|
|
|
25643
25642
|
function resolveLaunchIntent(cwd = process.cwd(), home = homedir10(), env = process.env) {
|
|
25644
25643
|
const candidate = realpathSync5(discoverProjectRoot(cwd, home));
|
|
25645
25644
|
const known = isExistingProjectRoot(candidate) || findByPath(candidate, home) !== void 0;
|
|
25646
|
-
const refused = isHomeDirectory(candidate, home)
|
|
25647
|
-
if (
|
|
25648
|
-
|
|
25649
|
-
|
|
25650
|
-
|
|
25651
|
-
|
|
25652
|
-
|
|
25645
|
+
const refused = isHomeDirectory(candidate, home) || isWorldWritable(candidate);
|
|
25646
|
+
if (known && !refused) return { kind: "open", workspace: resolveWorkspace(cwd, home, env) };
|
|
25647
|
+
const host = mostRecentProject(home, env) ?? hostWorkspace(home);
|
|
25648
|
+
return !refused && hasProjectMarker(candidate) ? { kind: "offer", workspace: host, directory: candidate } : { kind: "grid", workspace: host };
|
|
25649
|
+
}
|
|
25650
|
+
function hostWorkspace(home = homedir10()) {
|
|
25651
|
+
const dir = launchHostDir(home);
|
|
25652
|
+
mkdirSync10(dir, { recursive: true });
|
|
25653
|
+
const root = realpathSync5(dir);
|
|
25654
|
+
const id = ensureProjectIdFile(root, home);
|
|
25655
|
+
const stateDir = projectStateDir(id, home);
|
|
25656
|
+
mkdirSync10(stateDir, { recursive: true });
|
|
25657
|
+
return { root, id, stateDir, name: basename5(root), identityScope: "repository" };
|
|
25653
25658
|
}
|
|
25654
25659
|
function mostRecentProject(home, env) {
|
|
25655
25660
|
for (const entry of listProjects(home)) {
|
|
@@ -26006,7 +26011,7 @@ init_restart_supervisor();
|
|
|
26006
26011
|
init_logging();
|
|
26007
26012
|
init_boot_progress();
|
|
26008
26013
|
import { fork } from "node:child_process";
|
|
26009
|
-
import { randomUUID as
|
|
26014
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
26010
26015
|
import { existsSync as existsSync7, mkdirSync as mkdirSync11, readFileSync as readFileSync11 } from "node:fs";
|
|
26011
26016
|
import { createServer as createNetServer } from "node:net";
|
|
26012
26017
|
import { basename as basename6, dirname as dirname11, extname as extname2, isAbsolute as isAbsolute4, relative as relative2, resolve as resolve5, sep as sep3 } from "node:path";
|
|
@@ -26251,7 +26256,7 @@ var Supervisor = class {
|
|
|
26251
26256
|
watchSubscribe;
|
|
26252
26257
|
reexec;
|
|
26253
26258
|
supervisorLock;
|
|
26254
|
-
statusPublisherToken =
|
|
26259
|
+
statusPublisherToken = randomUUID6();
|
|
26255
26260
|
processGeneration = currentProcessGeneration();
|
|
26256
26261
|
ownerToken;
|
|
26257
26262
|
launchTarget;
|
|
@@ -27207,7 +27212,7 @@ var npmRegistryReleaseAdapter = createNpmRegistryReleaseAdapter();
|
|
|
27207
27212
|
// src/server-release.ts
|
|
27208
27213
|
init_frizz_paths();
|
|
27209
27214
|
import { execFile as execFile4 } from "node:child_process";
|
|
27210
|
-
import { createHash as createHash4, randomUUID as
|
|
27215
|
+
import { createHash as createHash4, randomUUID as randomUUID7 } from "node:crypto";
|
|
27211
27216
|
import {
|
|
27212
27217
|
closeSync as closeSync5,
|
|
27213
27218
|
existsSync as existsSync9,
|
|
@@ -27363,7 +27368,7 @@ function npmServerPackageInstaller(env = process.env) {
|
|
|
27363
27368
|
}
|
|
27364
27369
|
function atomicJson2(path, value) {
|
|
27365
27370
|
mkdirSync12(dirname13(path), { recursive: true, mode: 448 });
|
|
27366
|
-
const temp = `${path}.${
|
|
27371
|
+
const temp = `${path}.${randomUUID7()}.tmp`;
|
|
27367
27372
|
try {
|
|
27368
27373
|
const fd = openSync6(temp, "wx", 384);
|
|
27369
27374
|
try {
|
|
@@ -27464,7 +27469,7 @@ var ServerReleaseStore = class {
|
|
|
27464
27469
|
const spec = { ...this.spec, version };
|
|
27465
27470
|
assertSpec(spec, this.compatibility);
|
|
27466
27471
|
mkdirSync12(this.generations, { recursive: true, mode: 448 });
|
|
27467
|
-
const id =
|
|
27472
|
+
const id = randomUUID7();
|
|
27468
27473
|
const staging = join15(this.generations, `${id}.staging`);
|
|
27469
27474
|
const destination = join15(this.generations, id);
|
|
27470
27475
|
mkdirSync12(staging, { mode: 448 });
|
|
@@ -27490,7 +27495,7 @@ var ServerReleaseStore = class {
|
|
|
27490
27495
|
// src/server-owner.ts
|
|
27491
27496
|
init_frizz_paths();
|
|
27492
27497
|
init_project_launch();
|
|
27493
|
-
import { randomUUID as
|
|
27498
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
27494
27499
|
import { mkdirSync as mkdirSync13, readFileSync as readFileSync13, realpathSync as realpathSync7 } from "node:fs";
|
|
27495
27500
|
import { join as join16 } from "node:path";
|
|
27496
27501
|
var STABLE_SERVER_OWNER_NAME = "frizz-server";
|
|
@@ -27535,7 +27540,7 @@ function wrapLease(lease) {
|
|
|
27535
27540
|
token: lease.token,
|
|
27536
27541
|
pid: lease.pid,
|
|
27537
27542
|
processStart: lease.processStart,
|
|
27538
|
-
publisherToken:
|
|
27543
|
+
publisherToken: randomUUID8()
|
|
27539
27544
|
};
|
|
27540
27545
|
}
|
|
27541
27546
|
function acquireStableServerOwner(roots) {
|
|
@@ -27666,10 +27671,11 @@ if (options.help) {
|
|
|
27666
27671
|
|
|
27667
27672
|
Usage: npx ${PACKAGE_NAME} [options]
|
|
27668
27673
|
|
|
27669
|
-
Run it
|
|
27670
|
-
|
|
27671
|
-
|
|
27672
|
-
|
|
27674
|
+
Run it anywhere. One server serves EVERY project on this machine, each at its own
|
|
27675
|
+
/project/<name> URL, so a second run joins the one already going. In a folder that is already a
|
|
27676
|
+
project it opens that project's board; anywhere else it opens the dashboard, where projects are
|
|
27677
|
+
added. Runs the npm-resolved immutable Frizz package, then opens it in your default browser. Use
|
|
27678
|
+
frizz-dev only for a source checkout.
|
|
27673
27679
|
|
|
27674
27680
|
Options:
|
|
27675
27681
|
--no-app print the URL without opening a browser
|
|
@@ -27720,10 +27726,6 @@ var workspace = (() => {
|
|
|
27720
27726
|
return workspaceFromLaunchTarget(pinned);
|
|
27721
27727
|
}
|
|
27722
27728
|
const intent = resolveLaunchIntent();
|
|
27723
|
-
if (intent.kind === "empty")
|
|
27724
|
-
throw new Error(
|
|
27725
|
-
intent.reason === "home" ? "frizz cannot open your home directory as a project, and there is no other project to show yet. cd into a repository and run frizz there." : intent.reason === "world-writable" ? `A folder every account can write to cannot be a project: ${intent.directory}. Run frizz in a folder only you can write to.` : `${intent.directory} is not a Frizz project yet, and there is no other project to show. Run frizz inside a repository, or add this one from the projects page once a board is open.`
|
|
27726
|
-
);
|
|
27727
27729
|
launchIntent = intent;
|
|
27728
27730
|
return intent.workspace;
|
|
27729
27731
|
} catch (error) {
|
|
@@ -27869,7 +27871,7 @@ async function openOrPrint(port, reused, path = "") {
|
|
|
27869
27871
|
if (sandbox) warnings.push(`Sandbox: everything here is throwaway (${sandbox.home}) and is deleted when this terminal closes.`);
|
|
27870
27872
|
if (sessionNotice && !reused) warnings.push(sessionNotice);
|
|
27871
27873
|
if (!readout) {
|
|
27872
|
-
console.log(`${reused ? "reusing" : "started"} Frizz for ${workspace.root}`);
|
|
27874
|
+
console.log(`${reused ? "reusing" : "started"} Frizz${launchIntent && launchIntent.kind !== "open" ? "" : ` for ${workspace.root}`}`);
|
|
27873
27875
|
console.log(url);
|
|
27874
27876
|
if (publicOrigin) console.log(activeAccessLink?.url ?? `${publicOrigin}/`);
|
|
27875
27877
|
for (const warning of warnings) console.log(warning);
|
|
@@ -27880,7 +27882,9 @@ async function openOrPrint(port, reused, path = "") {
|
|
|
27880
27882
|
[
|
|
27881
27883
|
{ label: "Local", value: boardAddress(url), accent: true },
|
|
27882
27884
|
...publicOrigin ? [{ label: "Public", value: activeAccessLink?.url ?? `${publicOrigin}/`, accent: true }] : [],
|
|
27883
|
-
|
|
27885
|
+
// Only an `open` launch is ABOUT its workspace; any other is hosted on a project the operator
|
|
27886
|
+
// did not pick (launcher.ts resolveLaunchIntent), and naming it here reads as "you opened this".
|
|
27887
|
+
...launchIntent && launchIntent.kind !== "open" ? [] : [{ label: "Project", value: `${workspace.name} \u2014 ${tildePath(workspace.root, home)}` }],
|
|
27884
27888
|
...logger.file ? [{ label: "Logs", value: tildePath(logger.file, home) }] : []
|
|
27885
27889
|
],
|
|
27886
27890
|
reused ? (
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frizz",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A local web UI for running many coding agents at once",
|
|
6
6
|
"keywords": [
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
},
|
|
67
67
|
"frizzServer": {
|
|
68
68
|
"package": "frizz-server",
|
|
69
|
-
"version": "0.15.
|
|
69
|
+
"version": "0.15.22",
|
|
70
70
|
"protocol": 1,
|
|
71
71
|
"dataEpoch": 1
|
|
72
72
|
}
|