Skip to content

Commit dfe1856

Browse files
Remove the inert --force CLI flag (#888)
The flag was parsed into Config but never changed resume or run behavior. Reject it as unrecognized and drop the dead field.
1 parent b3b1233 commit dfe1856

12 files changed

Lines changed: 46 additions & 57 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
1313

1414
## [Unreleased]
1515

16+
### Removed
17+
18+
- `--force` is no longer accepted. It had no runtime effect; resume and the
19+
session picker already include failed and done sessions without it.
20+
1621
## [0.3.20] - 2026-09-10
1722

1823
### Added
@@ -376,8 +381,8 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
376381
reply. `send_input` steers only an in-flight running turn. Closed workers
377382
stay closed.
378383
- `corbits resume` orders sessions by last persist. The picker shows the 10
379-
most recent sessions and type-to-filter narrows that list. Default rows are
380-
running and cancelled; `--force` includes failed and done.
384+
most recent sessions across all statuses and type-to-filter narrows that
385+
list.
381386

382387
### TUI
383388

docs/ARCHITECTURE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ In TUI chat mode there is no completion gate — the session stays open across t
7272
- `--config <path>` replaces the global settings file as the provider source (useful for CI per-run injection). A provider must be defined in a settings file; there is no env fallback.
7373
- `settings.ts` owns the schema, validators (the per-repo file rejects credentials), file loaders, and the pure `resolveProvider` precedence function.
7474
- `providers.ts` defines the `ProviderCatalogEntry` type and helpers for building TUI provider lists; `profiles.ts` handles profile-level selection logic.
75-
- `loadConfig` is async (it reads settings files). Parses a leading `exec`/`run` subcommand, flags `--cwd`, `--config`, `--provider`, `--model`, `--force`, `--dangerously-skip-permissions` (forces this process; TUI `/yolo` persists as the user-global default), `--auto` / `--no-auto` (auto mode defaults on); collects positional arguments as the optional initial task for the TUI or the required prompt for exec.
75+
- `loadConfig` is async (it reads settings files). Parses a leading `exec`/`run` subcommand, flags `--cwd`, `--config`, `--provider`, `--model`, `--dangerously-skip-permissions` (forces this process; TUI `/yolo` persists as the user-global default), `--auto` / `--no-auto` (auto mode defaults on); collects positional arguments as the optional initial task for the TUI or the required prompt for exec.
7676
- Both settings files are on the secret-guard denylist for path-keyed tools, so the agent cannot `read_file` its own credentials. Shell commands that reference them still require explicit operator approval.
7777

7878
### TUI Runner (`src/tui/runner.ts`)

docs/IMPLEMENTATION.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ Printed by `corbits --help` / `-h` from `CLI_HELP_TEXT` in `src/config/index.ts`
366366
| -------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
367367
| _(no verb)_ || Interactive session; optional trailing task text |
368368
| `exec` / `run` || Run a prompt (non-interactive / one-shot) |
369-
| `resume` / `continue` || Open the session picker for this folder (project-keyed to this checkout's git toplevel). Lists the 10 most recently persisted sessions, completed included. Type to filter. `--force` is not required to see finished threads. |
369+
| `resume` / `continue` || Open the session picker for this folder (project-keyed to this checkout's git toplevel). Lists the 10 most recently persisted sessions, completed included. Type to filter. |
370370
| `--resume` || Open the interactive session picker |
371371
| `resume <session-id>` || Reopen a specific session |
372372
| `resume --pick` / `--list` || Interactive session picker |
@@ -375,7 +375,6 @@ Printed by `corbits --help` / `-h` from `CLI_HELP_TEXT` in `src/config/index.ts`
375375
| `--provider <name>` | from settings | Select a configured provider |
376376
| `--model <id>` | provider default | Select a model for the active provider |
377377
| `--profile <name>` || Settings profile |
378-
| `--force` | false | Override an existing run state |
379378
| `--dangerously-skip-permissions` | false | Auto-allow anything not denied by the authorization layer (gate + pre-gate workspace sandboxes; secret-guard / authz hard denies remain). This launch flag still forces this process; `/yolo [on\|off\|toggle]` persists as the user-global default via `setSkipPermissions` |
380379
| `--auto` | true (default) | Force auto mode on (workspace writes + unconstrained shell without prompts) |
381380
| `--no-auto` | false | Start with auto mode off (ask on every consequential action); no in-session key toggles it |

docs/TUI.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,7 @@ terminal's own text selection and copy work by default, with no Alt+M dance
542542
required. The resume picker lists the 10 most recently persisted sessions
543543
for this checkout — completed, failed, and crashed included. Recency is
544544
the last write to `run.json`, not start time. Type to filter by name
545-
(printable keys claim the `>` row, same as the model picker); `--force`
546-
is not a list filter.
545+
(printable keys claim the `>` row, same as the model picker).
547546

548547
## The prompt box
549548

scripts/eval-capability.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ function sampleConfig(over: Partial<Config> = {}): Config {
2626
providerName: "openai",
2727
cwd: process.cwd(),
2828
task: "do it",
29-
force: true,
3029
dangerouslySkipPermissions: true,
3130
skipPermissionsFromSettings: false,
3231
auto: false,

scripts/eval-capability.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ async function resolveVariantLabels(
601601
probe.push("--provider", variant.provider);
602602
if (variant.model !== undefined) probe.push("--model", variant.model);
603603
if (opts.configPath !== undefined) probe.push("--config", opts.configPath);
604-
probe.push("--force", "probe");
604+
probe.push("probe");
605605
const cfg = await loadConfig(probe, { allowUnconfigured: true });
606606
if (cfg.configured) {
607607
return { provider: cfg.providerName, model: cfg.model };
@@ -777,7 +777,6 @@ async function runCase(
777777
if (requested.model !== undefined) argv.push("--model", requested.model);
778778
if (opts.configPath !== undefined) argv.push("--config", opts.configPath);
779779
if (opts.skipPermissions) argv.push("--dangerously-skip-permissions");
780-
argv.push("--force");
781780
if (opts.director !== undefined) argv.push("--director", opts.director);
782781

783782
argv.push(prompt);

scripts/eval-public-swe-one.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,6 @@ async function main(): Promise<void> {
403403
"--model",
404404
opts.model,
405405
"--dangerously-skip-permissions",
406-
"--force",
407406
prompt,
408407
];
409408

src/config.test.ts

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ describe("loadConfig", () => {
135135
expect(config.providerName).toBe("fireworks");
136136
expect(config.globalSettingsPath).toBe(globalPath);
137137
expect(config.globalDefaultProvider).toBe("fireworks");
138-
expect(config.force).toBe(false);
139138
} finally {
140139
await rm(cwd, { recursive: true, force: true });
141140
}
@@ -450,16 +449,26 @@ describe("loadConfig", () => {
450449
}
451450
});
452451

453-
test("parses --force", async () => {
452+
test("rejects --force as unrecognized for tui, exec, and resume", async () => {
454453
const cwd = await emptyCwd();
455454
try {
456455
const globalPath = await writeGlobalSettings(cwd);
457-
const config = await loadConfig(["--cwd", cwd, "--force", "run task"], {
458-
globalSettingsPath: globalPath,
459-
});
460-
expect(config.force).toBe(true);
461-
expect(config.task).toBe("run task");
462-
expect(config.command).toBe("tui");
456+
await expect(
457+
loadConfig(["--cwd", cwd, "--force", "run task"], {
458+
globalSettingsPath: globalPath,
459+
}),
460+
).rejects.toThrow("unrecognized flag: --force");
461+
await expect(
462+
loadConfig(["exec", "--cwd", cwd, "--force", "ship it"], {
463+
globalSettingsPath: globalPath,
464+
}),
465+
).rejects.toThrow("unrecognized flag: --force");
466+
const sessionId = generateSessionId();
467+
await expect(
468+
loadConfig(["resume", sessionId, "--force", "--cwd", cwd], {
469+
globalSettingsPath: globalPath,
470+
}),
471+
).rejects.toThrow("unrecognized flag: --force");
463472
} finally {
464473
await rm(cwd, { recursive: true, force: true });
465474
}
@@ -470,15 +479,15 @@ describe("loadConfig", () => {
470479
try {
471480
const globalPath = await writeGlobalSettings(cwd);
472481
const config = await loadConfig(
473-
["exec", "--cwd", cwd, "--force", "ship it"],
482+
["exec", "--cwd", cwd, "--auto", "ship it"],
474483
{
475484
globalSettingsPath: globalPath,
476485
},
477486
);
478487
assertConfigured(config);
479488
expect(config.command).toBe("exec");
480489
expect(config.task).toBe("ship it");
481-
expect(config.force).toBe(true);
490+
expect(config.auto).toBe(true);
482491
} finally {
483492
await rm(cwd, { recursive: true, force: true });
484493
}
@@ -654,7 +663,7 @@ describe("loadConfig", () => {
654663
}
655664
});
656665

657-
test("resume <id> --force reopens a failed session that recorded an error", async () => {
666+
test("resume <id> reopens a failed session that recorded an error", async () => {
658667
const cwd = await emptyCwd();
659668
const home = await mkdtemp(join(tmpdir(), "ic-resume-home-"));
660669
try {
@@ -674,26 +683,22 @@ describe("loadConfig", () => {
674683
},
675684
home,
676685
);
677-
const config = await loadConfig(
678-
["resume", sessionId, "--force", "--cwd", cwd],
679-
{
680-
globalSettingsPath: globalPath,
681-
home,
682-
},
683-
);
686+
const config = await loadConfig(["resume", sessionId, "--cwd", cwd], {
687+
globalSettingsPath: globalPath,
688+
home,
689+
});
684690
assertConfigured(config);
685691
expect(config.resumeMode).toBe("id");
686692
expect(config.sessionId).toBe(sessionId);
687693
expect(config.skipInitialTask).toBe(true);
688694
expect(config.task).toBe("ship resume after failure");
689-
expect(config.force).toBe(true);
690695
} finally {
691696
await rm(cwd, { recursive: true, force: true });
692697
await rm(home, { recursive: true, force: true });
693698
}
694699
});
695700

696-
test("resume <id> --force among failed siblings stays silent and reopens the target", async () => {
701+
test("resume <id> among failed siblings stays silent and reopens the target", async () => {
697702
const cwd = await emptyCwd();
698703
const home = await mkdtemp(join(tmpdir(), "ic-resume-home-"));
699704
try {
@@ -719,13 +724,10 @@ describe("loadConfig", () => {
719724

720725
let config: Awaited<ReturnType<typeof loadConfig>> | undefined;
721726
const logged = await withFileLogSink(async () => {
722-
config = await loadConfig(
723-
["resume", targetId, "--force", "--cwd", cwd],
724-
{
725-
globalSettingsPath: globalPath,
726-
home,
727-
},
728-
);
727+
config = await loadConfig(["resume", targetId, "--cwd", cwd], {
728+
globalSettingsPath: globalPath,
729+
home,
730+
});
729731
});
730732
const loaded = defined(config, "config");
731733
assertConfigured(loaded);
@@ -843,7 +845,7 @@ describe("loadConfig", () => {
843845
let thrown: unknown;
844846
const logged = await withFileLogSink(async () => {
845847
try {
846-
await loadConfig(["resume", sessionId, "--force", "--cwd", cwd], {
848+
await loadConfig(["resume", sessionId, "--cwd", cwd], {
847849
globalSettingsPath: globalPath,
848850
home,
849851
});
@@ -923,8 +925,8 @@ describe("loadConfig", () => {
923925
});
924926

925927
test("--help after flags throws CliHelpError", async () => {
926-
await expectCliHelp(["--force", "--help"]);
927-
await expectCliHelp(["--force", "-h"]);
928+
await expectCliHelp(["--auto", "--help"]);
929+
await expectCliHelp(["--auto", "-h"]);
928930
});
929931

930932
test("--help after a positional throws CliHelpError", async () => {
@@ -967,7 +969,7 @@ describe("loadConfig", () => {
967969

968970
test("value flags reject other flag-shaped tokens as values", async () => {
969971
await expect(
970-
loadConfig(["--provider", "--force"], {
972+
loadConfig(["--provider", "--auto"], {
971973
globalSettingsPath: NO_SETTINGS,
972974
}),
973975
).rejects.toThrow("--provider requires a value");
@@ -978,7 +980,7 @@ describe("loadConfig", () => {
978980
loadConfig(["--cwd", "--tmp"], { globalSettingsPath: NO_SETTINGS }),
979981
).rejects.toThrow("--cwd requires a value");
980982
await expect(
981-
loadConfig(["exec", "--director", "--force", "ship it"], {
983+
loadConfig(["exec", "--director", "--auto", "ship it"], {
982984
globalSettingsPath: NO_SETTINGS,
983985
}),
984986
).rejects.toThrow("--director requires a value");

src/config/index.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,6 @@ export interface Config {
458458
verified?: boolean;
459459
cwd: string;
460460
task: string;
461-
force: boolean;
462461
dangerouslySkipPermissions: boolean;
463462
// True when dangerouslySkipPermissions came from the persisted global
464463
// default rather than this invocation's CLI flag. Entry points use this to
@@ -529,7 +528,6 @@ export interface UnconfiguredConfig {
529528
configured: false;
530529
cwd: string;
531530
task: string;
532-
force: boolean;
533531
dangerouslySkipPermissions: boolean;
534532
skipPermissionsFromSettings: boolean;
535533
auto: boolean;
@@ -573,7 +571,6 @@ Flags:
573571
--model <id> model for the active provider
574572
--profile <name> settings profile
575573
--resume interactive session picker
576-
--force override an existing run state
577574
--director <id> exec-only: run as this director (default: skywalker)
578575
--dangerously-skip-permissions
579576
skip permission prompts for this run only;
@@ -684,7 +681,6 @@ export async function loadConfig(
684681
}
685682

686683
let cwd = process.cwd();
687-
let force = false;
688684
let dangerouslySkipPermissions = false;
689685
// Auto mode is the default: non-destructive consequential actions (file
690686
// writes/edits and unconstrained shell) run without prompting, while shell
@@ -702,7 +698,7 @@ export async function loadConfig(
702698
const positional: string[] = [];
703699

704700
const requireValue = (flag: string, value: string | undefined): string => {
705-
// Flag-shaped tokens are never option values. `--provider --force` and a
701+
// Flag-shaped tokens are never option values. `--provider --auto` and a
706702
// trailing `--provider` both surface as a missing value rather than binding
707703
// the next flag (or accepting `--help`, which is already handled above).
708704
if (value === undefined || isFlagToken(value)) {
@@ -734,10 +730,6 @@ export async function loadConfig(
734730
profileFlag = requireValue("--profile", args[++i]);
735731
continue;
736732
}
737-
if (arg === "--force") {
738-
force = true;
739-
continue;
740-
}
741733
if (arg === "--director") {
742734
const value = requireValue("--director", args[++i]);
743735
if (command !== "exec") {
@@ -914,7 +906,6 @@ export async function loadConfig(
914906
configured: false,
915907
cwd,
916908
task,
917-
force,
918909
dangerouslySkipPermissions,
919910
skipPermissionsFromSettings,
920911
auto,
@@ -984,7 +975,6 @@ export async function loadConfig(
984975
...resolved,
985976
cwd,
986977
task: resumeTask,
987-
force,
988978
dangerouslySkipPermissions,
989979
skipPermissionsFromSettings,
990980
auto,

src/tui/onboarding.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ export async function runOnboarding(
7373
argv.push("--config", config.cliConfigPath);
7474
if (config.dangerouslySkipPermissions)
7575
argv.push("--dangerously-skip-permissions");
76-
if (config.force) argv.push("--force");
7776
if (config.task.length > 0) argv.push(config.task);
7877

7978
// Preserve programmatic isolation independently of the path that won settings

0 commit comments

Comments
 (0)