Skip to content

Add AI session storage, resume, and deletion commands to Studio CLI#2767

Open
jverneaut wants to merge 28 commits intoAutomattic:trunkfrom
jverneaut:add-sessions-to-ai-command
Open

Add AI session storage, resume, and deletion commands to Studio CLI#2767
jverneaut wants to merge 28 commits intoAutomattic:trunkfrom
jverneaut:add-sessions-to-ai-command

Conversation

@jverneaut
Copy link
Contributor

Related issues

  • /

How AI was used in this PR

  • AI was used to speed up implementation scaffolding and test case drafting.
  • Final code paths, command UX, and data model choices were manually reviewed.

Proposed Changes

  • Added persistent AI session storage using JSONL.
  • Chose JSONL because it is a common format for chronological structured data and is append-friendly for event streams.
  • Added session lifecycle/event recording (session.started, session.linked, site.selected, user.message, assistant.message, tool.result, tool.progress, agent.question, turn.closed).
  • Added session management commands:
    • studio ai sessions
    • studio ai sessions list
    • studio ai sessions resume [id]
    • studio ai sessions delete [id]
  • Sessions are recorded automatically during studio ai usage by default.
  • Added --no-session-persistence to disable recording for a run (including resumed chats).
  • resume and delete accept:
    • a full session ID
    • an ID prefix
    • latest
    • no ID (interactive picker/session browser in terminal)
  • Session files are stored in appData under date-organized folders to make browsing easier:
    • <appData>/sessions/YYYY/MM/DD/<timestamp>-<uuid>.jsonl
  • Filenames include both timestamp and UUID so ordering is clear in file browsers while remaining uniquely identifiable.
  • Added handling for ambiguous prefixes and missing sessions with explicit errors.
  • Added tests for JSONL persistence, summary generation, ordering (latest semantics), loading/deleting by prefix, and directory pruning behavior.

Command Help Output

studio ai sessions --help

studio ai sessions

Manage AI sessions

Commands:
  studio ai sessions list         List AI sessions
  studio ai sessions resume [id]  Resume an AI session (id, prefix, "latest", or
                                  picker)
  studio ai sessions delete [id]  Delete an AI session (id, prefix, "latest", or
                                  picker)

Options:
  --help                 Show help                                     [boolean]
  --session-persistence  Record this AI chat session to disk
                                                       [boolean] [default: true]

studio ai sessions list --help

studio ai sessions list

List AI sessions

Options:
  --help                 Show help                                     [boolean]
  --session-persistence  Record this AI chat session to disk
                                                       [boolean] [default: true]
  --format               Output format
                      [string] [choices: "compact", "json"] [default: "compact"]

studio ai sessions resume --help

studio ai sessions resume [id]

Resume an AI session (id, prefix, "latest", or picker)

Positionals:
  id  Session id, id prefix, or "latest"                                [string]

Options:
  --help                 Show help                                     [boolean]
  --session-persistence  Record this AI chat session to disk
                                                       [boolean] [default: true]

studio ai sessions delete --help

studio ai sessions delete [id]

Delete an AI session (id, prefix, "latest", or picker)

Positionals:
  id  Session id, id prefix, or "latest"                                [string]

Options:
  --help                 Show help                                     [boolean]
  --session-persistence  Record this AI chat session to disk
                                                       [boolean] [default: true]

Testing Instructions

  1. Build CLI:
    • npm run cli:build
  2. Start one AI chat (creates a session by default):
    • ENABLE_STUDIO_AI=true node apps/cli/dist/cli/main.js ai
    • Send any prompt, then run /exit.
  3. List sessions:
    • ENABLE_STUDIO_AI=true node apps/cli/dist/cli/main.js ai sessions list
    • Expected: your new session appears first.
  4. Resume a session:
    • ENABLE_STUDIO_AI=true node apps/cli/dist/cli/main.js ai sessions resume latest
    • Expected: transcript replays and chat resumes.
  5. Delete a session:
    • ENABLE_STUDIO_AI=true node apps/cli/dist/cli/main.js ai sessions delete latest
    • Expected: command prints Deleted AI session: <id>.
  6. Verify no-persistence mode:
    • ENABLE_STUDIO_AI=true node apps/cli/dist/cli/main.js ai --no-session-persistence
    • Send any prompt, then run /exit.
    • Then run ENABLE_STUDIO_AI=true node apps/cli/dist/cli/main.js ai sessions list and confirm no new session was added for that run.
  7. Validate automated tests:
    • npm test -- apps/cli/lib/tests/ai-sessions.test.ts
    • npm test -- apps/cli/commands/tests/ai.test.ts

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?
  • Ran linter/formatter on modified files
  • Ran npm run typecheck
  • Ran relevant tests for session storage and CLI commands -> Only tested on MacOS

@jverneaut jverneaut changed the title Add sessions storage, resume and deletion to Studio AI command Add AI session storage, resume, and deletion commands to Studio CLI Mar 11, 2026
@youknowriad
Copy link
Contributor

My initial feeling here is that the PR may lack a bit of structural organization, It adds a lot of code without too much separation of concerns to the "ai.ts" command file. I think it would make sense to separate the non-command specific code to separate files (as a preparation to handle sessions in the app later)

The ai-sessions.ts looks to be decent and about sessions persistence. Curious why it's not in the "ai" folder.

What do you think about this assessment, does it make sense?

In terms of behavior, I wonder if we should restore the "model" and the "cwd" when resuming sessions.

@jverneaut
Copy link
Contributor Author

I agree.

I think we should move apps/cli/commands/ai.ts into its own apps/cli/commands/ai/ folder like the other commands, and split responsibilities there.

For ai-sessions.ts, I put it in cli/lib intentionally since it handles session persistence and isn’t command-specific. We also expect to reuse it from the app side later.

On cwd: there’s ongoing discussion in #2764 about switching to ~/Studio as the default, but in the meantime I agree we should restore the previous cwd when resuming. I also agree with saving the model.

Should I go ahead with those changes?

@youknowriad
Copy link
Contributor

Maybe we should consider the apps/cli/ai folder as the "ai agent lib" and move the agnostic stuff there. At least that's how I've been thinking about it at the moment. And the "ai command" is just hooking the agent to the CLI too.

@jverneaut
Copy link
Contributor Author

I agree, here is what I plan to do:

apps/cli
├── ai
│   ├── agent.ts
│   ├── sessions.ts
│   ├── slash-commands.ts
│   ├── system-prompt.ts
│   ├── tools.ts
│   └── ui.ts
└── commands
    └── ai
        ├── index.ts
        ├── sessions.ts
        └── tests
            ├── ai-sessions.test.ts
            └── ai.test.ts

This moves the sessions logic to the ai folder and separates the ai and ai sessions commands handlers, also moves the tests closer to the command.

@youknowriad
Copy link
Contributor

That looks decent 👍

@jverneaut
Copy link
Contributor Author

jverneaut commented Mar 13, 2026

@youknowriad I rebased this branch to trunk to work with the latest AI CLI changes.

Here is what I ended up doing:

I moved the ai sessions CLI registration into apps/cli/index.ts so it follows the same registration pattern as the other CLI commands. I also split the ai.ts command into a dedicated apps/cli/commands/ai/ folder, with ai/index.ts for the main ai command and ai/sessions/* for the sessions command wiring.

The ai sessions command itself was split into dedicated files: apps/cli/commands/ai/sessions/(list|resume|delete).ts.

I moved session-related internals under apps/cli/ai/sessions/*.

I also updated the session event pipeline to rely on SDK event data (notably sdk.message and related tool events), so replay/resume rendering stays aligned with live chat output. Resume output is now closer to live chat output.

I also implemented these updates:

  • Provider/model/cwd context is now stored and restored on resume.
  • Replay no longer shows blinking in-transit tool steps from persisted history.

@taipeicoder
Copy link
Contributor

The slash command /browser doesn't seem to work with session. Steps to reproduce:

  1. Start the CLI
  2. Select a site
  3. /exit
  4. Resume the session
  5. Type /browser
  6. It'll say No site selected. Use ↓ to select a site first. even if the prompt shows that a site was selected

@taipeicoder
Copy link
Contributor

Nit: Is it necessary to save sessions where nothing has happened yet?

  1. Open the CLI
  2. /exit
  3. There will be a session created even though nothing really happened

@jverneaut
Copy link
Contributor Author

Thanks for the review @taipeicoder!

  • /browser on resumed sessions is now fixed.
  • Session recording is now lazy: the recorder is created on the first persisted interaction, so exiting immediately no longer creates an empty session.

@jverneaut jverneaut force-pushed the add-sessions-to-ai-command branch from edd25a6 to ed248ae Compare March 17, 2026 10:31
@jverneaut
Copy link
Contributor Author

Rebased the branch to work with the latest changes on trunk, most notably the commands registration in cli/index.ts.

@youknowriad
Copy link
Contributor

I'll take a look at the PR in a few. @taipeicoder also would appreciate a review when you have time.

@jverneaut
Copy link
Contributor Author

Thanks!

We now have a conflict in agent.ts since #2764 changed the cwd to ~/Studio to enforce stricter security and require explicit user permission for operations outside that scope.

In this PR, we’re introducing session persistence that saves and restores the user’s cwd (based on the original pwd), which now conflicts with that behavior.

Curious to get your thoughts on how we should handle this. Would it make sense to drop cwd persistence entirely and avoid exposing it to the user?

@youknowriad
Copy link
Contributor

Would it make sense to drop cwd persistence entirely and avoid exposing it to the user?

What do you mean? My expectations is that the way we persist the sessions is an implementation detail that the user shouldn't care about. We should be able to store the sessions in the app data folder without requiring users for permissions.

@jverneaut
Copy link
Contributor Author

@youknowriad This is not related to the session persistence layer, but to the change introduced in #2764 where the cwd is now always ~/Studio instead of being set to the user’s pwd.

This PR includes a feature that saves and restores the cwd, which now conflicts with that security model. Restoring a previous cwd could point outside of ~/Studio and effectively bypass the restriction.

When I mentioned “avoiding exposing it to the user”, I was referring to the TUI header for example. We currently display the cwd there, even though it’s no longer meaningful since the agent always operates within ~/Studio.

@youknowriad
Copy link
Contributor

Ah I see, it makes sense to avoid the switching of cwd then now indeed. Surfacing to the user is probably not that important either, although the user might ask where my sites are created.

@jverneaut jverneaut force-pushed the add-sessions-to-ai-command branch from ed248ae to ecbaa21 Compare March 17, 2026 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants