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 interactive setup wizard. It configures the API endpoint, authenticates you through the browser, and sets up your Stash — all in one shot. No manual config editing required.
stash connectThe wizard saves everything to ~/.stash/config.json. Once complete, commands like stash sessions push work without extra flags.
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: on first run it also picks the endpoint (managed or self-host) and offers to install streaming hooks for your coding agents. 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 connect re-onboards.
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 connect, 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 sessions transcript<session_id> [--save PATH]Fetch a full session transcript and print or save it. Transcripts are stored gzipped on the server and decompressed automatically.
<session_id>stringREQUIREDID of the session.
--savepathSave the transcript to a file instead of printing.
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.
-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:<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> file:<id>.
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.
--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.
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.
<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.
<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.