CLI Reference
A command-line interface for managing Stash from your terminal — push session events and manage all resources.
--json for machine-readable output.Install
uv tool install stashaiFirst-time setup
Run the setup wizard. It authenticates you through the browser, turns on session recording (pause anytime with stash stop), lets you pick which coding agents to record, sets up the folder you're standing in, and imports your conversation history in the background. No manual config editing required.
stash signinThe wizard saves everything to ~/.stash/config.json. Re-run it anytime with stash setup — no answer is final. Self-hosting? Point the CLI at your instance with stash signin --api <url>.
stash setupRe-run the setup wizard: session recording, agent hooks, folder context, and history import. Safe to repeat.
stash connectSet up the current folder for Stash: writes .stash and adds Stash instructions to CLAUDE.md so agents working there use your Stash. Works in any folder — a git repo is not required.
stash import-history[--status]Import your historical agent conversations (Claude Code, Codex, Cursor) into Stash with parallel uploads. Safe to re-run — the server skips sessions that already exist. The wizard launches this in the background; --status attaches a live progress bar (Ctrl-C detaches).
--statusflagFollow the running or last-finished import with a live progress bar.
Virtual filesystem
Use stash vfs when an agent needs to browse Stash through one filesystem-shaped interface without mounting anything into the OS. Your Stash exposes files, sessions, skills, tables, and sources — the last surfacing every connected integration (Gmail, GitHub, Slack, Jira, …) as read-only documents you can ls, cat, and grep.
stash vfs ls /
stash vfs "find /me -maxdepth 3 -type f"
stash vfs "rg 'database migration' /me"
stash vfs --cwd "/me/sources" "rg 'incident' ."stash vfs[--cwd PATH] "command"Run bash-shaped read and write commands against the virtual Stash tree.
--cwdstringVirtual working directory. Defaults to /.
commandstringBash-shaped command such as ls, find, rg, cat, sed, tee, or redirection.
Authentication
stash signin[--api <base_url>] [--api-key <key>] [--non-interactive]Authenticate this machine. With no flags it runs the browser flow against managed Stash and, on first run, continues into the setup wizard (recording, agent hooks, folder context, history import). Self-hosters pass --api with their instance URL. On SSH/headless it prints a URL to open instead of launching a browser. Pass --api-key to store a pre-minted key directly (no browser) on an unattended, browser-less machine — typically a self-hosted CI runner; get the key from your self-hosted instance's API-key page.
--apistringBase URL of the Stash server. Override for self-hosted deployments.
--api-keystringA pre-minted key to store directly, skipping the browser. For unattended, browser-less machines.
--non-interactiveflagSkip the setup wizard; just authenticate. Implied when stdin isn't a terminal.
STASH_API_KEY / STASH_URL in the environment authenticates CLI commands for CI and scripts — but it does not reach the streaming hooks, which read ~/.stash/config.json. To make an unattended machine stream, use stash signin --api-key. Change the endpoint or streaming agents later from stash settings.stash whoamiDisplay the currently authenticated user.
stash disconnectSign out and clear all stored credentials so the next stash signin starts fresh.
stash settings[--json]Interactive settings page — change the endpoint, toggle which agents stream, and view config. Pass --json for a read-only snapshot.
--jsonflagPrint a read-only snapshot instead of the interactive page.
stash signin, your defaults are stored. Change the endpoint any time from stash settings, or set STASH_API_KEY / STASH_URL as environment variables for CI and scripts.Files
stash files pagesList pages in your Stash.
stash files treeShow the folder and page tree for your Stash.
stash files create-folder<name> [--parent FOLDER_ID]Create a folder in the files.
<name>stringREQUIREDFolder name.
--parentstringParent folder ID.
stash files add-page<name> [--folder FOLDER_ID] [--content '...']Add a new page to the files.
<name>stringREQUIREDPage title.
--folderstringFolder ID.
--contentstringInitial page content.
stash files read-page<page_id>Read a page.
<page_id>stringREQUIREDID of the page.
stash files edit-page<page_id> --content '...'Update a page. Reads from stdin if --content is not given.
<page_id>stringREQUIREDID of the page.
--contentstringNew page content. Reads from stdin if omitted.
Sessions
stash sessions push<content> [--agent cli] [--type message] [--session ID] [--attach FILE]Push a new event to your session stream.
<content>stringREQUIREDEvent content to push.
--agentstringAgent identifier. Defaults to "cli".
--typestringEvent type. Defaults to "message".
--sessionstringSession ID to group events under.
--toolstringTool identifier.
--attachpathLocal file path to upload and attach. Repeatable.
--attach-idstringPre-uploaded file ID to attach. Repeatable.
stash sessions query[--agent X] [--type Y] [-n 50]Query recent session events with optional filters.
--agentstringFilter by agent identifier.
--typestringFilter by event type.
-n, --limitnumberMaximum number of results. Defaults to 50.
stash search with --source sessions (see Sources & search below). It replaces the old per-resource search commands.stash sessions foldersList session folders — shareable groupings of sessions.
stash sessions new-folder<name>Create a session folder.
<name>stringREQUIREDFolder name.
stash sessions agentsList distinct agent names that have logged events in your Stash.
stash vfs "cat '/sessions/<title>/transcript.md'". List the titles with stash vfs "ls /sessions".Memory
Your Memory wiki lives in a reserved folder that the Memory curator — and, since stash memory write, any agent — maintains. Pages are addressed by path.
stash memory[--recompute] [--curator on|off] [--json]Show your reserved Memory folder and the nightly curator's schedule state. --recompute runs the curator now; --curator off|on toggles the nightly cloud run (on-demand runs keep working).
--recomputeflagRun the Memory curator now.
--curatorstringTurn the nightly cloud curator run off or on.
--jsonflagMachine-readable output.
stash memory write"<Path>" [--content TEXT] [--json]Create or update a Memory wiki page at a path (e.g. 'Customers/Chainbase'). Missing subfolders are created; a trailing .md is stripped. Long bodies pipe on stdin.
--contentstringPage body. Reads stdin if omitted.
--jsonflagMachine-readable output.
stash memory ls[--json]Print the Memory wiki tree with folder and page ids.
--jsonflagMachine-readable output.
Sources & search
A source is anything the agent can read, exposed as a virtual file system: the two native sources — files and sessions — plus your connected sources (GitHub, Google Drive, Gmail, Notion, Slack, Granola). Pick a source like a drive, browse it by path, read a document, or search one source — or everything at once.
stash sources lsList every source you can read here: the native files and sessions sources plus your connected sources. Each row prints a source handle to use with the other commands.
stash sources add<source_type> [--ref REF] [--name NAME]Connect a source. Slack and Granola resolve their reference from your connected token; Gmail uses the mailbox email as --ref; the others need a --ref (e.g. a repo 'owner/name').
<source_type>stringREQUIREDgithub_repo | google_drive | gmail | notion | slack | granola.
--refstringExternal reference, e.g. a repo 'owner/name' or Gmail address.
--namestringDisplay name for the source.
stash sources browse<source> [path]List a source's entries like a file system.
<source>stringREQUIREDA source handle from stash sources ls.
pathstringPath prefix (connected sources only).
stash sources read<source> <ref>Read one document from a source.
<source>stringREQUIREDA source handle from stash sources ls.
<ref>stringREQUIREDPage id (files), session id (sessions), or document path (connected sources).
stash sources sync<source_id>Trigger an immediate re-index of a connected source you own.
<source_id>stringREQUIREDID of the connected source.
stash sources rm<source_id>Disconnect a source you own. Its indexed documents are removed.
<source_id>stringREQUIREDID of the connected source.
stash search<query> [--source HANDLE] [-n 20]Search across everything you can see — files, sessions, and connected sources. Pass --source to scope to one; omit it to search everything.
<query>stringREQUIREDSearch query.
--sourcestringScope to one source handle (from stash sources ls). Omit to search everything.
--modified-afterstringOnly results last modified after this ISO timestamp (e.g. 2026-01-01). Results with no known modification time are excluded.
--modified-beforestringOnly results last modified before this ISO timestamp. Results with no known modification time are excluded.
-n, --limitnumberMaximum number of results. Defaults to 20.
Tables
stash tables listList tables in your Stash.
stash tables create<name> [--columns JSON]Create a new table with optional column definitions.
<name>stringREQUIREDName for the table.
--columnsJSONColumn definitions as a JSON array of {name, type, options?}.
stash tables update<table_id> [--name TEXT] [--description TEXT]Update a table's name or description.
<table_id>stringREQUIREDID of the table.
--namestringNew table name.
--descriptionstringNew table description.
stash tables schema<table_id>Show a table's column schema.
<table_id>stringREQUIREDID of the table.
stash tables rows<table_id> [--sort COL] [--filter COL]Fetch rows from a table. Sort and filter accept column names, which are auto-resolved.
<table_id>stringREQUIREDID of the table.
--sortstringColumn name to sort by.
--filterstringColumn name to filter on.
stash tables insert<table_id> <data_json>Insert a new row. Data is a JSON object with column names as keys.
<table_id>stringREQUIREDID of the table.
<data_json>JSONREQUIREDRow data as a JSON object.
stash tables import<table_id> <file> [--format csv|json]Bulk import rows from a file. Auto-chunks into batches of 5000. CSV uses the first row as column headers. Supports piping: cat data.csv | stash tables import <id> --format csv.
<table_id>stringREQUIREDID of the table.
<file>pathREQUIREDPath to the import file.
--formatstringFile format: "csv" or "json". Auto-detected if omitted.
stash tables update-row<table_id> <row_id> <data_json>Update an existing row with a partial merge. Data is a JSON object with column names as keys.
<table_id>stringREQUIREDID of the table.
<row_id>stringREQUIREDID of the row to update.
<data_json>JSONREQUIREDUpdated row data as a JSON object.
stash tables delete-row<table_id> <row_id>Delete a row from a table.
<table_id>stringREQUIREDID of the table.
<row_id>stringREQUIREDID of the row to delete.
stash tables add-column<table_id> <name> [--type text] [--options TEXT]Add a column to a table.
<table_id>stringREQUIREDID of the table.
<name>stringREQUIREDColumn name.
--typestringColumn type. Defaults to "text".
--optionsstringComma-separated options for select/multiselect columns.
stash tables delete-column<table_id> <column_id>Delete a column from a table.
<table_id>stringREQUIREDID of the table.
<column_id>stringREQUIREDColumn ID (col_xxx) or column name.
stash tables count<table_id>Count rows in a table, optionally with filters.
<table_id>stringREQUIREDID of the table.
stash tables export<table_id>Export all rows from a table as CSV.
<table_id>stringREQUIREDID of the table.
stash tables delete<table_id> [-y]Delete a table and all its data.
<table_id>stringREQUIREDID of the table.
-y, --yesflagSkip confirmation prompt.
Uploaded Files
stash upload<path> [--skill TITLE]Upload a single file (Markdown/HTML become pages, everything else a binary file) or a folder into your Stash. Pass --skill to also bundle it into a shareable Skill.
<path>pathREQUIREDFile or directory to upload.
--skillstringAlso publish the upload as a Skill with this title.
stash files listList your files.
stash files text<file_id>Print extracted text for a file (PDF, image OCR, or plain text).
<file_id>stringREQUIREDID of the file.
Object operations
One set of verbs across every object type. Pass items as type:id tokens (e.g. page:abc, file:def, session:ghi); each verb accepts several at once.
stash rm<type:id>... [--permanent]Move pages, files, or sessions to trash. Pass --permanent to skip the trash window and delete immediately.
<type:id>stringREQUIREDItems to delete, e.g. page:<id> session:"<title>". A session may be named by its title as well as its id.
--permanentflagDelete immediately instead of trashing.
stash restore<type:id>...Restore pages, files, or sessions from trash.
<type:id>stringREQUIREDItems to restore, e.g. page:<id> session:"<title>", naming a session as `stash trash list` prints it.
stash mv<type:id>... (--to-folder ID | --to-root)Move pages, files, folders, tables, or sessions into a folder, or to the root.
<type:id>stringREQUIREDItems to move. A session may be named by its title as well as its id.
--to-folderstringTarget folder id.
--to-rootflagMove to the root.
stash cp<type:id>... [--to-folder ID]Duplicate pages, files, or folders as 'Copy of <name>'.
<type:id>stringREQUIREDItems to copy.
--to-folderstringTarget folder id for the copies.
Skills
A Skill is a special folder — one containing a SKILL.md — of pages, files, and tables. Publishing a skill makes it publicly readable at its link (optionally listed in Discover); to share privately with a specific person, share its folder like any other folder. (The stash CLI name is unchanged.)
stash skills listList Skills in your Stash.
stash skills create<name> [--public] [--discover]Create a skill: a folder with a SKILL.md template. Pass --public to publish immediately.
<name>stringREQUIREDSkill name (becomes the folder name).
--publicflagPublish immediately and mint a shareable link.
--discoverflagList the public Skill in the Discover catalog (requires --public).
stash skills publish<folder_id> [--discover]Publish an existing skill folder: mint its share record and print the public URL.
<folder_id>stringREQUIREDThe skill folder to publish.
--discoverflagList the public Skill in Discover.
stash skills snapshot-source<skill_id> --source ID --path PATHCopy a point-in-time snapshot of one connected-source document into the Skill as a page, so the skill stays self-contained.
<skill_id>stringREQUIREDID of the Skill.
--sourcestringREQUIREDConnected-source id (from stash sources ls).
--pathstringREQUIREDDocument path within the source.
stash skills fork<slug>Fork a public Skill: deep-copy its folder into your Stash.
<slug>stringREQUIREDPublic Skill slug.
stash skills unpublish<skill_id>Stop sharing a Skill: delete its publish record. The folder stays.
<skill_id>stringREQUIREDID of the published Skill.
stash skills install<slug> [--project] [--dir PATH]Install a public Skill into your agent's skills directory. Installed skills are tracked and auto-update whenever skills sync runs (the plugin runs one at every session start); a one-shot notice at the next session start lists what changed.
<slug>stringREQUIREDPublic Skill slug.
--projectflagInstall into ./.claude/skills (this repo only) instead of ~/.claude/skills.
--dirstringCustom skills directory.
stash skills uninstall<slug-or-name> [--project] [--dir PATH]Remove an installed Skill and stop auto-updating it.
<slug-or-name>stringREQUIREDThe installed skill's slug or folder name.
stash skills follow[--project] [--dir PATH]Auto-install skills people share with you. New shared skills land at the next skills sync and update like any installed skill; stash skills unfollow turns it off (already-installed skills stay).
stash skills sync[--project] [--dir PATH]Two-way sync between the local skills directory and your Stash: your own skills three-way sync (conflicts are skipped loudly), installed skills refresh from their cloud copy. The plugin runs this automatically at session start.
MCP servers
Register MCP servers once and every agent gets them: your cloud agent's .mcp.json is refreshed on each turn, and stash tools install writes an entry into a local repo's .mcp.json. Header and env secrets are stored encrypted.
stash tools add<name> (--url URL | --command CMD) [--header K=V] [--env K=V]Register an MCP server: --url for a remote (HTTP) server, --command for a local (stdio) one.
<name>stringREQUIREDServer name, unique in your account.
--urlstringHTTP MCP endpoint (remote transport).
--commandstringCommand line to launch a stdio server.
--headerstringHTTP header as KEY=VALUE (repeatable; stored encrypted).
--envstringEnv var for stdio servers as KEY=VALUE (repeatable; stored encrypted).
stash tools install<name>Write a registered server into this repo's .mcp.json (merged — your own entries are never touched; re-runs are idempotent).
<name>stringREQUIREDA server from stash tools list.
stash tools remove<name>Delete a registered MCP server.
<name>stringREQUIREDServer name.
Workspaces
A workspace is a shared team scope: members' sessions, events, and searches can run against it instead of their personal Stash. Switching applies everywhere on your machine — the CLI, every agent plugin, and the MCP server. Team workspaces are set up for you — email sam@joinstash.ai.
stash workspace listList workspaces you belong to, marking the active scope.
stash workspace switch<name>Route sessions, events, transcripts, and searches to this workspace — or back with stash workspace switch personal.
<name>stringREQUIREDWorkspace name or domain, or 'personal'.
Shares
Share a single object — a folder, page, file, session, or table — with a specific person by email. If they don't have an account yet the share is recorded as pending and converts when they sign up. (To share a whole folder of related work, convert it to a Skill.)
stash shares ls<object_type> <object_id>List who an object is shared with.
<object_type>stringREQUIREDfolder | page | file | session | table.
<object_id>stringREQUIREDID of the object, or a session's title.
stash shares add<object_type> <object_id> <email> [--permission read]Share an object with a person by email.
<object_type>stringREQUIREDfolder | page | file | session | table.
<object_id>stringREQUIREDID of the object, or a session's title.
<email>stringREQUIREDRecipient email (pending until they sign up).
--permissionstringread | write | admin. Defaults to read.
stash shares rm<object_type> <object_id> <principal_id> [--principal-type user]Revoke a person's access to an object.
<object_type>stringREQUIREDfolder | page | file | session | table.
<object_id>stringREQUIREDID of the object, or a session's title.
<principal_id>stringREQUIREDThe user id to revoke (from stash shares ls).
--principal-typestringPrincipal kind. Defaults to "user".
Keys
stash keys listList your active API keys (one per device / login).
stash keys revoke<key_id>Revoke an API key by ID. Any device using it will receive a 401 on the next call.
<key_id>stringREQUIREDID of the key to revoke.
Streaming & hooks
Install Stash hooks for all supported coding agents on your $PATH, then enable or disable streaming per repo.
stash installInstall hook plugins for all supported coding agents on your PATH.
stash enableRe-enable activity streaming for the current repository.
stash disableStop streaming for this repo without touching the committed manifest.
stash settings[--json]Open the interactive settings page.
--jsonflagPrint a read-only snapshot of settings instead of opening the interactive page.