Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/coding-agent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@

### Fixed

- Windows spawns no longer flash a console: every `spawn`/`spawnSync`/`execFile` site now passes `windowsHide:true`, with `utils/child-process.ts` forcing it on win32 for all current and future `spawnProcess` callers ([#927](https://github.com/code-yeongyu/senpi/pull/927)).

- Goals no longer stall after a settings hot-reload: a reload `session_start` now re-engages an active goal (re-arming the monitor backstop while wake sources are live, or queueing a continuation through the existing sessionStart admission) instead of parking it until the next user message; stopped goals still never auto-start on reload ([#936](https://github.com/code-yeongyu/senpi/pull/936)).
- Cursor CLI OAuth is now available by default when its real prerequisites exist: with `cursor-agent` installed and no managed CLI account, a native `cursor` OAuth credential is copied automatically into one canonical `native` slot without modifying the primary credential; explicit `enabled: false` remains a hard opt-out, repeated/concurrent startup is idempotent, and `/login cursor` refreshes the CLI fallback in the same session ([#931](https://github.com/code-yeongyu/senpi/pull/931)).

Expand Down Expand Up @@ -7614,4 +7616,4 @@ Initial public release.
- Git branch display in footer
- Message queueing during streaming responses
- OAuth integration for Gmail and Google Calendar access
- HTML export with syntax highlighting and collapsible sections
- HTML export with syntax highlighting and collapsible sections
1 change: 1 addition & 0 deletions packages/coding-agent/src/beta/omo-local-update-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const defaultSpawnWorker: OmoLocalSpawnWorker = (request) => {
try {
const child = spawn(process.execPath, workerCommandArgs(request.force), {
detached: true,
windowsHide: true,
env: process.env,
stdio: ["ignore", logFd, logFd],
});
Expand Down
23 changes: 23 additions & 0 deletions packages/coding-agent/src/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,29 @@

- `main.ts` model/thinking option resolution block.

## Windows console hide for top-level entry and config helpers (2026-08-18)

### What changed

- `packages/coding-agent/src/cli.ts`: main entry re-spawn now passes `windowsHide:true`.
- `packages/coding-agent/src/config.ts`: `readCommandOutput` via `spawnProcessSync` now passes `windowsHide:true`.
- `packages/coding-agent/src/package-manager-cli.ts`: self-update step via `spawnProcess` now passes `windowsHide:true`.
- `packages/coding-agent/src/self-update-bootstrap.ts`: npm update step via `spawn` now passes `windowsHide:true`.
- `packages/coding-agent/src/beta/omo-local-update-worker.ts`: detached worker spawn now passes `windowsHide:true` alongside `detached:true`.

### Why

- Windows console less parents briefly show a conhost window for every spawn without `windowsHide:true`. Detached/background helpers run periodically, so flashes recur until all sites are hidden.

### Why an extension could not handle it

- Spawn options live inside the caller (helper, daemon, runner). Extensions cannot inject `windowsHide` from outside; the spawn site itself must set it.

### Expected merge conflict zones

- LOW: the spawn options literal in the patched file(s).


## Repository audit baseline for the src tracker (2026-08-17)

### What changed
Expand Down
1 change: 1 addition & 0 deletions packages/coding-agent/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ async function spawnFullCli(): Promise<number> {
const child = spawn(process.execPath, [...process.execArgv, fullCliPath, ...args], {
env: process.env,
stdio: "inherit",
windowsHide: true,
});
child.on("error", (error) => {
reject(error);
Expand Down
1 change: 1 addition & 0 deletions packages/coding-agent/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ function readCommandOutput(
const result = spawnProcessSync(command, args, {
encoding: "utf-8",
stdio: ["ignore", "pipe", "pipe"],
windowsHide: true,
});
if (result.status === 0) return result.stdout.trim() || undefined;
if (options.requireSuccess) {
Expand Down
21 changes: 21 additions & 0 deletions packages/coding-agent/src/core/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,27 @@ Conflict zone: `cursor-exec-bridge.ts` `executeTool`, `cursor-exec-bridge-sessio
- `model-resolver.ts` pattern matching and partial-match ordering, `agent-session.ts` thinking-level setters,
`session-manager.ts` entry schema.

## Windows console hide for core exec and package helpers (2026-08-18)

### What changed

- `packages/coding-agent/src/core/exec.ts`: `execCommand` via `spawn` now passes `windowsHide:true`.
- `packages/coding-agent/src/core/footer-data-provider.ts`: git `spawnSync`/`execFile` probes now pass `windowsHide:true`.
- `packages/coding-agent/src/core/package-manager.ts`: `spawnCommand`/`spawnCaptureCommand`/`runCommandSync` now pass `windowsHide:true` (central wrapper also forces it).

### Why

- Windows console less parents briefly show a conhost window for every spawn without `windowsHide:true`. Detached/background helpers run periodically, so flashes recur until all sites are hidden.

### Why an extension could not handle it

- Spawn options live inside the caller (helper, daemon, runner). Extensions cannot inject `windowsHide` from outside; the spawn site itself must set it.

### Expected merge conflict zones

- LOW: the spawn options literal in the patched file(s).


## Cursor bridge lifecycle events retain run ownership (2026-08-18)

### What changed
Expand Down
1 change: 1 addition & 0 deletions packages/coding-agent/src/core/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export async function execCommand(
cwd,
shell: false,
stdio: ["ignore", "pipe", "pipe"],
windowsHide: true,
});

let stdout = "";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@

## Windows console hide for Cursor CLI probes (2026-08-18)

### What changed

- `packages/coding-agent/src/core/extensions/builtin/cursor-cli-oauth/executable.ts`: `VersionProbeOptions` now allows `windowsHide` and probe `execFile` passes `windowsHide:true`.
- `packages/coding-agent/src/core/extensions/builtin/cursor-cli-oauth/models.ts`: model probe `spawn` now passes `windowsHide:true`.

### Why

- Windows console less parents briefly show a conhost window for every spawn without `windowsHide:true`. Detached/background helpers run periodically, so flashes recur until all sites are hidden.

### Why an extension could not handle it

- Spawn options live inside the caller (helper, daemon, runner). Extensions cannot inject `windowsHide` from outside; the spawn site itself must set it.

### Expected merge conflict zones

- LOW: the spawn options literal in the patched file(s).

# cursor-cli-oauth extension changes

## 2026-08-21 - Cache provider settings loads by mtime+size to cut lock convoy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export type CursorAgentExecutableDeps = {
export type VersionProbeOptions = {
encoding: "utf8";
timeout: number;
windowsHide?: boolean;
};

export type VersionProbeCallback = (error: Error | null, stdout: string, stderr: string) => void;
Expand Down Expand Up @@ -116,7 +117,7 @@ export function probeCursorAgentVersion(
deps: VersionProbeDeps = defaultVersionProbeDeps,
): Promise<string> {
return new Promise((resolve, reject) => {
deps.execFile(executable, ["--version"], { encoding: "utf8", timeout: 10_000 }, (error, stdout) => {
deps.execFile(executable, ["--version"], { encoding: "utf8", timeout: 10_000, windowsHide: true }, (error, stdout) => {
if (error) {
reject(error);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ async function runModelsProbe(executable: string, stdoutPath: string, timeoutMs:
await new Promise<void>((resolve, reject) => {
const child = spawn(executable, ["models"], {
stdio: ["ignore", output.fd, "ignore"],
windowsHide: true,
});
let timedOut = false;
let settled = false;
Expand Down
19 changes: 19 additions & 0 deletions packages/coding-agent/src/core/extensions/builtin/mcp/changes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@

## Windows console hide for MCP diagnostics (2026-08-18)

### What changed

- `packages/coding-agent/src/core/extensions/builtin/mcp/diagnose.ts`: `execFile` diagnostics now pass `windowsHide:true`.

### Why

- Windows console less parents briefly show a conhost window for every spawn without `windowsHide:true`. Detached/background helpers run periodically, so flashes recur until all sites are hidden.

### Why an extension could not handle it

- Spawn options live inside the caller (helper, daemon, runner). Extensions cannot inject `windowsHide` from outside; the spawn site itself must set it.

### Expected merge conflict zones

- LOW: the spawn options literal in the patched file(s).

# mcp Extension Changes

## Explicit pgrep match-all pattern for process-tree collection (2026-08-12)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ function execFileForDiagnostics(
cwd: options.cwd,
env: options.env,
killSignal: "SIGKILL",
windowsHide: true,
maxBuffer: MCP_STDIO_DIAGNOSTIC_MAX_BYTES * 4,
timeout: MCP_STDIO_DIAGNOSTIC_TIMEOUT_MS,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/coding-agent/src/core/footer-data-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function resolveBranchWithGitSync(repoDir: string): string | null {
cwd: repoDir,
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
windowsHide: true,
});
const branch = result.status === 0 ? result.stdout.trim() : "";
return branch || null;
Expand All @@ -67,6 +68,7 @@ function resolveBranchWithGitAsync(repoDir: string): Promise<string | null> {
{
cwd: repoDir,
encoding: "utf8",
windowsHide: true,
},
(error: ExecFileException | null, stdout: string) => {
if (error) {
Expand Down
3 changes: 3 additions & 0 deletions packages/coding-agent/src/core/package-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2668,6 +2668,7 @@ export class DefaultPackageManager implements PackageManager {
cwd: options?.cwd,
stdio: isStdoutTakenOver() ? ["ignore", 2, 2] : "inherit",
env,
windowsHide: true,
});
}

Expand All @@ -2682,6 +2683,7 @@ export class DefaultPackageManager implements PackageManager {
cwd: options?.cwd,
stdio: ["ignore", "pipe", "pipe"],
env,
windowsHide: true,
});
}

Expand Down Expand Up @@ -2749,6 +2751,7 @@ export class DefaultPackageManager implements PackageManager {
stdio: ["ignore", "pipe", "pipe"],
encoding: "utf-8",
env,
windowsHide: true,
});
if (result.error || result.status !== 0) {
throw new Error(
Expand Down
20 changes: 20 additions & 0 deletions packages/coding-agent/src/core/tools/changes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@

## Windows console hide for fd/rg helpers (2026-08-18)

### What changed

- `packages/coding-agent/src/core/tools/find.ts`: fd helper `spawn` now passes `windowsHide:true`.
- `packages/coding-agent/src/core/tools/grep.ts`: rg helper `spawn` now passes `windowsHide:true`.

### Why

- Windows console less parents briefly show a conhost window for every spawn without `windowsHide:true`. Detached/background helpers run periodically, so flashes recur until all sites are hidden.

### Why an extension could not handle it

- Spawn options live inside the caller (helper, daemon, runner). Extensions cannot inject `windowsHide` from outside; the spawn site itself must set it.

### Expected merge conflict zones

- LOW: the spawn options literal in the patched file(s).

# core/tools changes

## Edit tool keeps filesystem policy and themed diff rendering after the 59a71b23 pin (2026-08-19)
Expand Down
2 changes: 1 addition & 1 deletion packages/coding-agent/src/core/tools/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ export function createFindToolDefinition(
}
args.push("--", effectivePattern, searchPath);

const child = spawn(fdPath, args, { stdio: ["ignore", "pipe", "pipe"] });
const child = spawn(fdPath, args, { stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
const rl = createInterface({ input: child.stdout });
let stderr = "";
const lines: string[] = [];
Expand Down
2 changes: 1 addition & 1 deletion packages/coding-agent/src/core/tools/grep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ export function createGrepToolDefinition(
if (glob) args.push("--glob", glob);
args.push("--", pattern, searchPath);

const child = spawn(rgPath, args, { stdio: ["ignore", "pipe", "pipe"] });
const child = spawn(rgPath, args, { stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
const rl = createInterface({ input: child.stdout });
let stderr = "";
let matchCount = 0;
Expand Down
19 changes: 19 additions & 0 deletions packages/coding-agent/src/modes/app-server/changes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# changes

## Windows console hide for app-server daemon (2026-08-18)

### What changed

- `packages/coding-agent/src/modes/app-server/daemon.ts`: daemon `spawn` with `detached:true` now also passes `windowsHide:true`.

### Why

- Windows console less parents briefly show a conhost window for every spawn without `windowsHide:true`. Detached/background helpers run periodically, so flashes recur until all sites are hidden.

### Why an extension could not handle it

- Spawn options live inside the caller (helper, daemon, runner). Extensions cannot inject `windowsHide` from outside; the spawn site itself must set it.

### Expected merge conflict zones

- LOW: the daemon spawn options literal.


## Registry-owned thread teardown (2026-08-13)

### What changed
Expand Down
1 change: 1 addition & 0 deletions packages/coding-agent/src/modes/app-server/daemon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ async function spawnDaemon(paths: DaemonPaths, listen: AppServerListen): Promise
[...process.execArgv, resolveCliMainPath(), "app-server", "--listen", listen.url],
{
detached: true,
windowsHide: true,
env: process.env,
stdio: ["ignore", "ignore", stderr.fd],
},
Expand Down
21 changes: 21 additions & 0 deletions packages/coding-agent/src/modes/interactive/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,27 @@ Conflict zone: `interactive-mode.ts` `message_update` / `message_end`.
`interactive-mode.ts` (adjacent to the paste handler wiring), and
`queueCompactionSubmission()` next to `queueCompactionMessage()`.

## Windows console hide for interactive helpers (2026-08-18)

### What changed

- `packages/coding-agent/src/modes/interactive/external-editor.ts`: both editor `spawn` calls now pass `windowsHide:true`.
- `packages/coding-agent/src/modes/interactive/interactive-mode.ts`: tmux `spawn` and `gh` `spawnSync`/`spawn` helpers now pass `windowsHide:true`.
- `packages/coding-agent/src/modes/interactive/components/session-selector.ts`: `trash` `spawnSync` now passes `windowsHide:true`.

### Why

- Windows console less parents briefly show a conhost window for every spawn without `windowsHide:true`. Detached/background helpers run periodically, so flashes recur until all sites are hidden.

### Why an extension could not handle it

- Spawn options live inside the caller (helper, daemon, runner). Extensions cannot inject `windowsHide` from outside; the spawn site itself must set it.

### Expected merge conflict zones

- LOW: the spawn options literal in the patched file(s).


## Native Cursor login refreshes the CLI fallback lane in the same session (2026-08-18)

### What changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ async function deleteSessionFile(
): Promise<{ ok: boolean; method: "trash" | "unlink"; error?: string }> {
// Try `trash` first (if installed)
const trashArgs = sessionPath.startsWith("-") ? ["--", sessionPath] : [sessionPath];
const trashResult = spawnSync("trash", trashArgs, { encoding: "utf-8" });
const trashResult = spawnSync("trash", trashArgs, { encoding: "utf-8", windowsHide: true });

const getTrashErrorHint = (): string | null => {
const parts: string[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export async function editInExternalEditor(options: ExternalEditorOptions): Prom
const child = spawn(editor, [...editorArgs, filePath], {
stdio: "inherit",
shell: process.platform === "win32",
windowsHide: true,
});
child.on("error", () => resolve({ launched: false }));
child.on("close", (code) => resolve({ launched: true, code }));
Expand Down Expand Up @@ -64,6 +65,7 @@ export async function editFileInExternalEditor(options: { command: string; path:
const child = spawn(editor, [...editorArgs, options.path], {
stdio: "inherit",
shell: process.platform === "win32",
windowsHide: true,
});
child.on("error", () => resolve({ launched: false }));
child.on("close", (code) => resolve({ launched: true, code }));
Expand Down
13 changes: 4 additions & 9 deletions packages/coding-agent/src/modes/interactive/interactive-mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1660,6 +1660,7 @@ export class InteractiveMode {
return new Promise((resolve) => {
const proc = spawn("tmux", args, {
stdio: ["ignore", "pipe", "ignore"],
windowsHide: true,
});
let stdout = "";
const timer = setTimeout(() => {
Expand Down Expand Up @@ -7895,9 +7896,7 @@ export class InteractiveMode {
private async handleShareCommand(): Promise<void> {
// Check if gh is available and logged in
try {
const authResult = spawnSync("gh", ["auth", "status"], {
encoding: "utf-8",
});
const authResult = spawnSync("gh", ["auth", "status"], { encoding: "utf-8", windowsHide: true });
if (authResult.status !== 0) {
this.showError("GitHub CLI is not logged in. Run 'gh auth login' first.");
return;
Expand Down Expand Up @@ -7945,12 +7944,8 @@ export class InteractiveMode {
};

try {
const result = await new Promise<{
stdout: string;
stderr: string;
code: number | null;
}>((resolve) => {
proc = spawn("gh", ["gist", "create", "--public=false", tmpFile]);
const result = await new Promise<{ stdout: string; stderr: string; code: number | null }>((resolve) => {
proc = spawn("gh", ["gist", "create", "--public=false", tmpFile], { windowsHide: true });
let stdout = "";
let stderr = "";
proc.stdout?.on("data", (data) => {
Expand Down
Loading