Summary
@ff-labs/pi-fff currently blocks Pi session replacement (/new and /resume) because the session_start handler eagerly initializes FileFinder and awaits the initial scan.
In packages/pi-fff/src/index.ts:
pi.on("session_start", async (_event, ctx) => {
try {
activeCwd = ctx.cwd;
if (shouldEnableMentions()) applyEditorMode(ctx);
await ensureFinder(activeCwd);
} catch (e: unknown) {
ctx.ui.notify(...);
}
});
ensureFinder() calls:
const result = FileFinder.create({ basePath: cwd, ... });
...
await finder.waitForScan(15000);
Because Pi recreates/reloads the session runtime when switching sessions, this means /new and selecting a session from /resume can hang until FileFinder.create() / waitForScan(15000) finishes.
Impact
/resume: after selecting a session, Pi appears stuck before the resumed session is usable.
/new: after pressing Enter, Pi appears stuck before the new session is usable.
- This is especially noticeable in larger workspaces where scanning/watching takes non-trivial time.
- Disabling
@ff-labs/pi-fff makes /new and /resume fast again.
Expected behavior
Pi session startup should not be blocked by a file index warmup. The finder can still be warmed in the background, and actual fff tool calls / @-mention autocomplete can await the same in-flight initialization if needed.
Suggested fix
Make the session_start warmup non-blocking, e.g. schedule it after the session start event returns:
let lifecycleId = 0;
pi.on("session_start", async (_event, ctx) => {
try {
activeCwd = ctx.cwd;
const sessionLifecycleId = ++lifecycleId;
if (shouldEnableMentions()) applyEditorMode(ctx);
setTimeout(() => {
if (sessionLifecycleId !== lifecycleId) return;
ensureFinder(activeCwd).catch((e: unknown) => {
if (sessionLifecycleId !== lifecycleId) return;
ctx.ui.notify(
`FFF init failed: ${e instanceof Error ? e.message : String(e)}`,
"error",
);
});
}, 0);
} catch (e: unknown) {
ctx.ui.notify(
`FFF init failed: ${e instanceof Error ? e.message : String(e)}`,
"error",
);
}
});
pi.on("session_shutdown", async () => {
lifecycleId++;
destroyFinder();
});
I also found it safer for ensureFinder() to return the local createdFinder after waitForScan() rather than the mutable global finder, so a shutdown during warmup cannot accidentally return a destroyed/replaced finder.
Local validation
I tested a local patch with:
cd packages/pi-fff
npx tsc --noEmit
and verified that importing the extension still returns a valid factory. With the patch, /new and /resume are no longer blocked by the scan warmup; the first actual fff operation may still await initialization, which seems like the expected tradeoff.
Related issues I found
I did not find an exact duplicate for pi-fff blocking Pi /new or /resume. Some related pi-fff/watcher issues:
This issue seems specifically about lifecycle behavior in the Pi extension: doing blocking index warmup inside session_start.
Environment
@ff-labs/pi-fff: 0.8.1
- Pi: 0.75.1
- Node.js: v24.13.1
- OS: macOS / Darwin arm64
Summary
@ff-labs/pi-fffcurrently blocks Pi session replacement (/newand/resume) because thesession_starthandler eagerly initializesFileFinderand awaits the initial scan.In
packages/pi-fff/src/index.ts:ensureFinder()calls:Because Pi recreates/reloads the session runtime when switching sessions, this means
/newand selecting a session from/resumecan hang untilFileFinder.create()/waitForScan(15000)finishes.Impact
/resume: after selecting a session, Pi appears stuck before the resumed session is usable./new: after pressing Enter, Pi appears stuck before the new session is usable.@ff-labs/pi-fffmakes/newand/resumefast again.Expected behavior
Pi session startup should not be blocked by a file index warmup. The finder can still be warmed in the background, and actual fff tool calls / @-mention autocomplete can await the same in-flight initialization if needed.
Suggested fix
Make the
session_startwarmup non-blocking, e.g. schedule it after the session start event returns:I also found it safer for
ensureFinder()to return the localcreatedFinderafterwaitForScan()rather than the mutable globalfinder, so a shutdown during warmup cannot accidentally return a destroyed/replaced finder.Local validation
I tested a local patch with:
cd packages/pi-fff npx tsc --noEmitand verified that importing the extension still returns a valid factory. With the patch,
/newand/resumeare no longer blocked by the scan warmup; the first actual fff operation may still await initialization, which seems like the expected tradeoff.Related issues I found
I did not find an exact duplicate for
pi-fffblocking Pi/newor/resume. Some relatedpi-fff/watcher issues:ffgrepcalls andensureFindersingleton synchronizationaiMode: truewatcher file descriptor usage on macOSThis issue seems specifically about lifecycle behavior in the Pi extension: doing blocking index warmup inside
session_start.Environment
@ff-labs/pi-fff: 0.8.1