Skip to main content
The session command manages conversation sessions, allowing you to save, resume, and organize multi-turn interactions. Every sub-command (list, resume, show, delete, export, share, unshare) and every --continue / --session <id> flag resolves the same session by the same id through a single resolver.

Quick Start

List conversation sessions example

Commands

Start a Session

Expected Output:

List Sessions

Expected Output:
The header line now includes an identity: tag showing which resolver was used (see Project Sessions → How It Works). Sessions that have not yet accumulated any usage show - in the Tokens and Cost columns.
Updated columns (praisonaiagents 1.6.85+): The table now shows ID | Name | Status | Events | Tokens | Cost | Parent | Updated. Tokens are formatted with thousands separators (e.g. 12,345); Cost is formatted as $0.0140. Sessions with no recorded usage show - for both. The Parent column shows an 8-character parent id prefix for a forked session, or - for a root session.
JSON output — pass --json to get machine-readable output with usage data per session:
session list (no --project, no --all) merges the current project’s session store with the global default store — every session --continue/resume could see, in one list, deduped by session id (freshest updated_at wins when the same id lives in both stores). Use --all to include every project’s sessions, or --project <id> to restrict to one project’s store only. Cross-store merge landed with the fix for PraisonAI #2655.

What shows up

Without --all or --project, the default listing surfaces:
  • Sessions created by praisonai run (project store) ✅
  • Sessions created by chat, code, gateway, TUI, API, or a bare Agent(memory={"session_id": "..."}) (global default store) ✅ new
  • Sub-agent / forked child sessions still appear here (with their parent shown in the Parent column), but --continue skips them in favour of the last root session.
Passing --project <id> stays project-scoped only; --all widens to every project.

Token / Cost columns

The Tokens and Cost columns show cumulative totals across all runs for each session. Totals are persisted in session-store metadata under usage and updated automatically by praisonai run / direct prompts whenever --session is set or a default project session is active. A - is rendered when no usage has been recorded yet. JSON output (--json):
See Cost Tracking for how per-session totals accumulate across runs. For roll-ups across sessions see Usage. List sessions across all projects:
List sessions for a specific project:

Rename a Session

session rename gives a session a human-readable title so session list reads like a menu of tasks instead of an agent name or message snippet. The title is display-only metadata — the session id never changes. See Session Rename for the full feature page.
Expected Output:
Clear a previously set title by passing an empty string:
Practical example — before and after:
An id that resolves nowhere exits 1 with the same remediation text as the other session commands:
A failed metadata write prints Failed to rename session: <id> and also exits 1. JSON output — pass the global --json flag for a machine-readable result instead of the human-readable line:
session list displays a title using this order (_session_title()):
  1. The explicit stored title, if set
  2. The agent name
  3. A message snippet
Any id that resolve_session accepts is renameable — including legacy-only sessions listed in session list but not yet migrated to the canonical store. The canonical store stores the title in metadata["title"]; the legacy fallback (SessionManager.rename) persists it in metadata["name"]. Both paths persist so any id you can list, resume, show, delete, or export can also be renamed. Renaming is currently CLI-only — there is no /rename bot chat command. Titles set here surface in session list and every resolver-backed sub-command. See Bot Commands for the chat-side command set.

Fork a Session

session fork copies a saved session into a new child session, keeping both timelines resumable. It mirrors praisonai run --fork but works on any saved session without entering the REPL. See Session Forking for the full feature page, including the interactive /branch command.
Expected Output:
An unknown id exits 1 with the same remediation text as the other session commands:
An out-of-range --at-message is rejected up front (no silent slice wrap):
JSON output — pass the global --json flag for a machine-readable result:
from_message_index and title are null when not passed.

Resume a Session

session resume restores chat history, model, and agent name from a previous session. History is preserved by default via compact retention — older turns are summarised and archived rather than dropped. See Session Persistence — Retention Policies.
Expected Output:
The Usage: line shows cumulative tokens and cost accumulated across all previous prompts in this session. If no usage has been recorded yet, the line is omitted.

Resume and continue with a prompt

State is rehydrated, then the prompt runs through the shared praisonai run --session <id> path. The resume panel is suppressed when a prompt is provided — the run pipeline emits the only top-level output.

Show transcript only (legacy view)

Use --transcript to inspect a session without restoring state. The panel title shows “Session Transcript”.

Cross-store lookup

session resume finds a session whether it was created via praisonai run --continue (project store) or via the gateway/TUI (global store). See Storage Backends.
When you pass a continuation prompt, the resume panel is suppressed — the run pipeline emits the only top-level output. To inspect a session without continuing, use --transcript or omit the prompt.

Cost & Token Tracking

PraisonAI accumulates input/output/cached tokens and dollar cost on every session run, so you can see exactly what a conversation has spent.

Quick Start

1

Run with a session

After the answer, the CLI prints a one-line footer:
2

Check cumulative usage

3

Continue — totals keep accumulating

Totals continue from where you left off — they do not reset.

What gets persisted

Each session stores a usage object in its metadata: The persisted total_tokens and cost fields are exactly what praisonai usage aggregates across sessions by day, model, or project.
After each prompt run with an active session, the CLI prints:
Format: "{input:,} in / {output:,} out · ${cost:.4f}" — locale-formatted integers, 4-decimal cost. The footer is suppressed in --json mode but usage is still persisted.

Resume behaviour

Totals are rehydrated on --continue / --session <id> and keep accumulating — they do not reset. The resume panel shows a usage summary line:

How it works

Reading usage programmatically

Notes

Any failure (pricing lookup, persistence error, missing collector) leaves the session untouched. Usage accounting never breaks a run.
When a run uses more than one model, each model’s tokens are priced individually with get_pricing(model_name).
Provider-reported cached reads are accumulated in cached_tokens but excluded from cost — the provider already discounts them.

Show Session Details

session show resolves against the same stores as list / resume, so any id you can list or resume is also showable.
Expected Output:
session show now resolves through the same shared session resolver as list / resume, so its output includes the persisted agent, model, created / updated times, and message count for the resolved session.
Identity invariant (praisonai #3133): any id shown by praisonai session list — or resumable via praisonai run --continue — can be inspected with session show, exported with session export, and deleted with session delete using the same id. There is no hidden second store: show / delete / export now route through the same DefaultSessionStore (project-scoped + global) that list / resume use, so id → session is unambiguous. praisonai/PraisonAI#3201 made this an invariant by construction: both the list-path and the show/delete/export-path now delegate to a single canonical_cli_stores() helper, and a regression test asserts they enumerate identical store instances.
Legacy store deprecation: the legacy per-session directory store (SessionManager) is still consulted as a best-effort fallback during the deprecation window, but new sessions land in DefaultSessionStore. If you’re on an old version with sessions only in the legacy store, re-create or session export them so they migrate cleanly.

Show a Read-Only Recap

Render a “where were we” block instead of raw session details. Non-destructive — never modifies the session or triggers compaction.
The recap prints in a Session Recap panel:
Combine with the global --json flag for structured output:
This is the CLI counterpart of the /recap bot chat command — same read-only recap, surfaced from the terminal.

Hand off a Session (Continuation Prompt)

Assemble a self-contained continuation prompt from durable state — recap describes where we were; handoff is a prompt a fresh context can act on.
The prompt prints in a Session Handoff panel:
Combine with the global --json flag for structured output:
Defaults to the most recent session when no id is given. See Session Handoff for the full feature, options, and Python API.

Export a Session

session export resolves the id through the same shared resolver, so an id from session list always exports the same session — with a legacy-store fallback for legacy-only ids.

Delete a Session

Delete targets the single canonical store that owns the id — a project-scoped session delete never removes an unrelated same-id session that lives only in the global store.
Expected Output:
Skip the confirmation prompt with --yes / -y:
An I/O failure is now surfaced instead of a fake success — the command exits non-zero:
Legacy SessionManager sessions created before 2026-07-17 are also swept on delete, so a duplicate legacy record can’t resurface a session you already deleted.

Export a Session

session export writes a resolved session as markdown (default) or JSON.
Expected Output (markdown):
When --output is set, the CLI writes the file and prints:
The interactive /export slash command uses this same renderer — when a session id resolves, the REPL’s /export [file] is byte-for-byte identical to praisonai session export <id>. It falls back to the in-memory transcript when no session is persisted yet, so /export works without --session.
Legacy-only sessions fall back to the SessionManager exporter automatically — and legacy sessions also honour --sanitise now, so a raw transcript is never leaked through the fallback (see Sanitise before sharing).

Sanitise before sharing

praisonai session export <id> --sanitise (alias --sanitize) redacts secrets, absolute file paths, the working directory, and file contents embedded in tool I/O — replacing them with stable [redacted:<category>:<n>] placeholders — so a session is safe to paste into a bug report, share with a teammate, or attach to an audit trail. The default export (no flag) is byte-for-byte unchanged; sanitisation is strictly opt-in.
Every masked span becomes [redacted:<category>:<n>], where the same source value maps to the same placeholder within one export — so the reader still follows which value recurs where, without ever seeing it.
The same path appearing three times becomes [redacted:path:1] three times, not :1, :2, :3. Redaction levels. An unknown value is rejected up front (exit 1):
The redactor is a small, self-contained helper (praisonai_code/cli/state/redact.py, stdlib only — no new dependencies). It reuses praisonaiagents.secrets when available, so any value registered via the process-wide secret registry is masked first, even if it does not match a built-in token shape.
--sanitise is a best-effort safety net, not a compliance guarantee. It masks the shapes above deterministically, but a novel secret shape that matches no built-in pattern and was never registered can still slip through. Before publishing a redacted transcript widely, skim the output for anything that looks like a credential and consider --redact-level strict.
Legacy SessionManager sessions (created before 2026-07-17) also honour --sanitise — they used to return a raw verbatim transcript ignoring the flag, a secret-leak gap closed by praisonai/PraisonAI#3434.
To hand a redacted transcript straight to someone, use session share instead — it runs this same redactor, wraps the result in a self-contained HTML file, and returns a file:// link, so there’s no manual export --sanitise > out.md plus attach step.
Python API. The same redaction is available on the resolver helper — handy when scripting an export from a notebook or CI job:
And directly against a resolved payload (dict → dict, input never mutated):

Share a Session

session share publishes a redacted, read-only HTML transcript to ~/.praisonai/shares/ and returns a file:// link — no external service or dependency.
share resolves session_id through the same shared resolver as list / resume / show / export (project store first, then global default store, then a best-effort legacy SessionManager fallback for pre-2026-07-17 ids), then calls export_session(session_id, format="md", redact=True, redact_level=<level>). Sharing is always redacted — there is intentionally no --no-redact escape hatch. The redacted Markdown is wrapped in a single self-contained HTML file (inline CSS, no external assets), with the transcript inserted via html.escape inside a <pre> block so no session text can be interpreted as markup. Expected Output:
JSON output — pass --json for a machine-readable link and on-disk path:
An id that resolves nowhere exits 1 with the same remediation text as the other session commands:
The .html file lands under the canonical data home alongside sessions/, so shares never split across a second home root:
The filename is sha256(id)[:16] — a stable per-session path. Re-sharing the same id overwrites the same file, and the write is atomic: the HTML is written to a sibling temp file, then os.replace() swaps it in, so a failed or interrupted write never truncates a previously published transcript. On an OSError the temp file is cleaned up and the command exits non-zero.
Redaction is a best-effort safety net, not a compliance guarantee — the same caveat as export --sanitise. A novel secret shape that matches no built-in pattern and was never registered via praisonaiagents.secrets can still slip through. Skim the published HTML before sharing widely; use --redact-level strict for anything public.
The shared file is a plain file:// link on the local filesystem. It is not uploaded to any server — only people who can read ~/.praisonai/shares/ (or receive the file itself) can open it. To share externally, attach or upload the file separately.
The .html filename is sha256(id)[:16], not the session id — so ids containing /, .., or shell metacharacters are safe on every filesystem.
share is idempotent: re-running it overwrites the same file atomically, so an updated transcript never coexists with a stale copy at a second URL.

Unshare a Session

session unshare revokes a previously published transcript by deleting the shared HTML file.
unshare resolves the shared path deterministically via the same sha256(id)[:16] mapping — no session lookup — so it works even if the underlying session has since been deleted. A missing file is a clean no-op, not an error, so the command is idempotent and safe to script. A real OSError (permission denied, disk error) exits 1 with an actionable message. Expected Output (a file was removed):
Expected Output (nothing was published):
JSON output:
revoked: false means nothing was there to revoke — not that the operation failed.
unshare on a session that was never shared is a clean no-op, not an error. Safe to script.
  • Sanitise before sharing — the underlying redactor is shared; share = export --sanitise + HTML wrap + atomic publish. Same standard vs strict table.
  • List sessions — how to find the id to share.
  • Upstream: PraisonAI issue #3590, commits 9c27592 + cdd41eb.

Import a Session

session import reads a previously-exported JSON file and prints the resulting id.
Expected Output:
Only JSON files are accepted. The imported id is printed and can then be resumed with praisonai --continue or praisonai session resume.

Help

Expected Output:

Token and Cost Tracking

Every session accumulates cumulative token usage and cost across all prompts, visible in session list and the resume panel. After each run, a single-line footer is printed:
The middle dot is U+00B7 (·). The footer reflects cumulative totals since session start, not just the last prompt. It is silently suppressed in JSON mode (--json / --output json) — there is no --no-usage flag. When you resume a session, the cumulative totals are rehydrated so subsequent prompts keep accumulating:

Working with praisonai run

The same project-scoped store powers --continue and --session on praisonai run. As of PR #1963, every surface restores history from and saves to this store: As of the fix for issue #2700, the actions-mode row is fully honoured for --auto-save, --session, --continue, and --fork. If you hit a TypeError about auto_save on an older praisonai-code build, upgrade and retry — see the run.mdx troubleshooting section. As of PR #2277, --session <id> and --continue now persist model and agent_name into session metadata so a later session resume reproduces the same configuration deterministically. For advanced programmatic use, the rehydrate_session helper in praisonai.cli.session returns a RehydratedSession with session_id, chat_history, model, agent_name, metadata, and found fields — see the SDK reference for details.
See Run for complete session continuity documentation.

Using Sessions with Prompts

Continue a Conversation

Expected Output (third message):

Session with Other Features

Use Cases

Project-Based Conversations

Learning Sessions

Code Review Sessions

Auto-Save Sessions

Automatically save sessions after each agent run using the --auto-save flag:

Python API

History in Context

Load conversation history from previous sessions into the current context:

Python API

Workflow Checkpoints

Save and resume workflow execution at any step:

Checkpoint Storage

Project-Scoped Sessions

Sessions are automatically scoped to your current project. PraisonAI detects your project by finding the git repository root, or uses the current working directory as a fallback. Project identification:
  • Project ID: First 8 characters of SHA256 hash of project root path
  • Git detection: Uses git rev-parse --show-toplevel with 5-second timeout
  • Fallback: Current working directory if not in a git repository
Storage structure:

Session Storage

Sessions are stored in a project-scoped layout when using the default behavior:
With project-scoped sessions, your sessions are organized by project automatically. Legacy sessions remain accessible via the --all flag:

Storage Backend Options

Store sessions in different backends for production deployments:
When --storage-path is omitted, --storage-backend file writes to ~/.praisonai/sessions/ and --storage-backend sqlite writes to ~/.praisonai/sessions.db (both under the canonical ~/.praisonai/ data home). Prior releases anchored these defaults under ~/.praison/ — any existing sessions there are still readable via the same code paths, but new sessions land under the canonical root. See praisonai/PraisonAI#3203.
See Storage Backends for more details.

Concurrent Sessions

Multiple praisonai processes can safely share the same session — the CLI store reloads, merges, and writes under an exclusive lock so no messages are lost when the TUI, --interactive mode, and praisonai "…" --session all touch the same file.

Merge Strategy

When two writers race, the session store merges their changes:

Lost-Update Prevention

praisonai session show and praisonai session resume always reflect the latest on-disk state — the in-process cache is invalidated automatically when another process writes (mtime-based check). This concurrent-save safety was added in PR #1854. For the equivalent feature in the SDK-level store, see Multi-Process Safety.
This applies to the default file-backed session store. The sqlite / redis:// backends in the Storage Backend Options table above handle concurrency via the database itself; the CLI does not add its own merge layer there.

How Session IDs Resolve

Every session sub-command and every --continue / --session <id> flag resolves the same session by the same id through a single session_resolver.

Session Identity

show, delete, and export now read the same project-scoped + global DefaultSessionStore that list, resume, and --continue already use — so any id you can list or resume is also showable, deletable, and exportable by the same id.
Delete targets the single store that owns the id and honours that store’s confirmation — an I/O failure exits non-zero instead of reporting a fake success. The legacy store is always swept so a shadow record can’t resurface a deleted session.

Cross-Platform Support

The praisonai session commands work on Windows, macOS, and Linux — file locking is automatic and platform-appropriate.
If you see this warning: File locking unavailable on this platform (fcntl not available); concurrent writers may corrupt session files.This means you’re running on an environment without native file locking. Restrict to a single process, or migrate to a DB-backed storage backend (link to the sqlite / redis options in the Storage Backend Options table above).
On Windows, sessions are stored under %USERPROFILE%\.praisonai\sessions\{session_id}.json following the OS convention via Path.home(). (Legacy pre-canonical installs may still read from %USERPROFILE%\.praison\sessions\ as a fallback — see Storage Paths.) The same directory is shared by praisonai code, praisonai run, and the gateway/TUI, so a session written by one surface is readable by the others. Cross-platform locking was added in PR #1837. Concurrent multi-process writes (e.g. TUI + praisonai --interactive sharing the same session directory) are preserved without message loss as of PR #1885 and PR #1892. For the SDK-level session store with the same cross-platform guarantees, see Session Persistence. Example usage across platforms:

Best Practices

Use descriptive session names that reflect the project or task for easy identification.
Long sessions accumulate tokens. Consider starting fresh sessions for unrelated topics.

Naming

Use descriptive names like project-auth-feature

Organization

Create separate sessions for different projects

Cleanup

Delete old sessions to free up storage

Context

Start new sessions when changing topics significantly

Run Command

Session flags and usage footer for praisonai run

Session Persistence

SDK-level session management

Session Forking

Fork mid-session with /branch or session fork

Cost Tracking

Per-session persistence and /cost slash command

Project Sessions

Persisted usage shape and project scoping

Usage

Aggregate token and cost reporting across all sessions