Skip to content
Closed
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
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ fx session resume last
fx session resume --id <id>
```

`fx session <id>` prints the saved conversation with a `[turn N]` label above every turn. Those labels are the boundaries the branch and undo commands take:

```bash
fx session fork <id> --at 7
fx session rewind <id> --by 2
```

`fork` copies the first 7 turns into a brand-new session and prints the new ID to resume. The source session is left exactly as it was. `rewind` drops the last 2 turns from the session in place, keeping its ID. Both accept `--id <id>` and `--json`.

Rewound turns are not erased. The rewind is recorded as a new revision in the session's event log, and the files those turns referenced stay on disk.

Each interactive session names its terminal tab. The title prefers the session name, falls back to the workspace name, and keeps the active model as secondary context. Renaming or resuming a session updates the tab, and exiting clears the fx-owned title. Noninteractive commands do not emit terminal-title controls.

Run `/feedback` to open the feedback form at `fx.sh/feedback`. It does not create a diagnostic or change the clipboard.
Expand Down
1 change: 1 addition & 0 deletions scripts/pgso/corpus.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
],
"verification_scenarios": [
{"name": "verify-auto-mode-reliability", "argv": ["bun", "test", "--max-concurrency", "1", "./auto-mode-reliability.test.ts"], "test_file": "auto-mode-reliability.test.ts"},
{"name": "verify-session-fork", "argv": ["bun", "test", "--max-concurrency", "1", "./session-fork.test.ts"], "test_file": "session-fork.test.ts", "requires_tmux": false},
{"name": "verify-oauth-keychain-migration", "argv": ["bun", "test", "--max-concurrency", "1", "./oauth-keychain-migration.test.ts"], "test_file": "oauth-keychain-migration.test.ts", "allow_keychain": true},
{"name": "verify-tui-auth-source-selection", "argv": ["bun", "test", "--max-concurrency", "1", "./tui-auth-source-selection.test.ts"], "test_file": "tui-auth-source-selection.test.ts"},
{"name": "verify-tui-composer-edit-contracts", "argv": ["bun", "test", "--max-concurrency", "1", "./tui-composer-edit-contracts.test.ts"], "test_file": "tui-composer-edit-contracts.test.ts"},
Expand Down
8 changes: 6 additions & 2 deletions src/builtins/commands.zig
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,16 @@ pub const top_level_specs = [_]TopLevelSpec{
.{
.kind = .session,
.token = "session",
.usage = "session <last|id>|--id <id> [--json] | session resume [last|<id>] | session resume --id <id> | session migrate <id>|--id <id> [--allow-large] [--json] | session recover <id>|--id <id> [--json]",
.summary = "Inspect, resume, migrate, or recover saved sessions",
.usage = "session <last|id>|--id <id> [--json] | session resume [last|<id>] | session resume --id <id> | session migrate <id>|--id <id> [--allow-large] [--json] | session recover <id>|--id <id> [--json] | session fork <id>|--id <id> --at <turn> [--json] | session rewind <id>|--id <id> --by <count> [--json]",
.summary = "Inspect, resume, migrate, recover, fork, or rewind saved sessions",
.options = &.{
.{ .flag = "last", .description = "Inspect the current workspace session" },
.{ .flag = "--id <id>", .description = "Inspect a saved session by exact id" },
.{ .flag = "resume [last|<id>]", .description = "Resume the latest workspace session or a session by id" },
.{ .flag = "migrate <id>", .description = "Migrate a saved session to the current format" },
.{ .flag = "recover <id>", .description = "Copy a recoverable corrupt session into a new session" },
.{ .flag = "fork <id> --at <turn>", .description = "Branch a session into a new session holding its first <turn> turns" },
.{ .flag = "rewind <id> --by <count>", .description = "Drop the last <count> turns from a session in place" },
.{ .flag = "--allow-large", .description = "Permit migrating an oversized session" },
json_option,
},
Expand Down Expand Up @@ -312,6 +314,8 @@ pub const top_level_help_groups = [_]TopLevelHelpGroup{
.{ .usage = "session resume [last|id]", .summary = "Resume the latest workspace session or a session by id" },
.{ .usage = "session migrate <id>", .summary = "Migrate a saved session to the current format" },
.{ .usage = "session recover <id>", .summary = "Copy a recoverable corrupt session" },
.{ .usage = "session fork <id> --at <turn>", .summary = "Branch a session at a turn into a new session" },
.{ .usage = "session rewind <id> --by <count>", .summary = "Drop the last turns from a session in place" },
} },
.{ .entries = &.{
.{ .kind = .login, .usage = "login [vercel|codex|grok]" },
Expand Down
Loading