Skip to content

CLI Reference

Complete reference for all sfs commands.

sfs [OPTIONS] COMMAND [ARGS]...
Option Description
--help Show help and exit
--version, -V Show the installed version (sessionfs X.Y.Z (python …, platform arch)) and exit. Also available as sfs version.

List captured sessions.

sfs list [OPTIONS]
Option Type Default Description
--tool string — Filter by source tool (e.g., claude-code)
--since string — Show sessions since time (7d, 24h, or ISO date)
--tag string — Filter by tag
--sort string recent Sort order: recent, oldest, messages, tokens
--json flag false Output as JSON
--quiet, -q flag false Only print session IDs

Example:

Terminal window
$ sfs list --since 7d --sort tokens
Sessions (5)
┌──────────────┬─────────────┬────────┬──────────┬───────────┐
│ ID │ Tool │ Model │ Messages │ Title │
├──────────────┼─────────────┼────────┼──────────┼───────────┤
│ a1b2c3d4e5f6 │ claude-code │ opus-4 │ 23 │ Debug ... │
└──────────────┴─────────────┴────────┴──────────┴───────────┘

Show session details.

sfs show SESSION_ID [OPTIONS]
Argument Required Description
SESSION_ID yes Session ID or prefix (min 4 chars)
Option Type Default Description
--messages, -m flag false Show conversation messages
--cost, -c flag false Show cost estimate
--page-size int 20 Messages per page (with --messages)

Example:

Terminal window
$ sfs show a1b2 --cost
╭──────────── Session Details ────────────╮
│ Session ID: a1b2c3d4-e5f6-... │
│ Title: Debug auth flow │
│ Tool: claude-code 1.0.23 │
│ Model: claude-opus-4 (anthropic) │
│ Messages: 23 │
│ Input tokens: 34,200 │
│ Output tokens: 12,800 │
╰─────────────────────────────────────────╯
╭──────────── Cost Estimate ──────────────╮
│ Input cost: $0.5130 │
│ Output cost: $0.9600 │
│ Total: $1.4730 │
╰─────────────────────────────────────────╯

Resume a captured session in any supported AI tool.

sfs resume SESSION_ID [OPTIONS]
Argument Required Description
SESSION_ID yes Session ID or prefix
Option Type Default Description
--project path — Target project path (overrides workspace)
--in string claude-code Target tool: claude-code, codex, copilot, or gemini
--model, -m string — Model to use in target tool (e.g. gpt-4.1, claude-sonnet-4, gemini-2.5-pro)
--no-rules-sync flag false Skip preflight of the target tool’s project rules file. Per-invocation only.
--force-rules flag false Overwrite an unmanaged target-tool rules file with SessionFS-managed content. One-time permission — the file becomes SessionFS-managed afterward and subsequent resumes refresh it normally.

Converts the session to the target tool’s native format and injects it into that tool’s session storage. Cursor, Cline, Roo Code, Kilo Code, Antigravity, and Amp are capture-only — --in cursor (and the others) is rejected with an error. Use --in with one of the four supported resume targets instead.

Before launching the target tool, sfs resume preflights the tool’s project rules file from the current canonical SessionFS rules. Missing files are written; SessionFS-managed files are refreshed; unmanaged files are left alone with a warning on stderr unless --force-rules is passed. Preflight failures are non-fatal — resume still exits 0. See Resume-Time Rules Sync for the full policy.

--model support per tool:

  • Claude Code: passed as --model to the claude binary
  • Codex: used in session injection and codex resume --model
  • Gemini: passed as --model to the gemini binary
  • Copilot: not supported (warns, uses Copilot’s default)

If omitted, each tool uses its own default model.

Examples:

Terminal window
$ sfs resume ses_abc123 --in codex
Source session used rules v3 (sessionfs).
Current project rules are v5.
Synced codex.md from SessionFS rules v5.
Launching codex resume ...
Session resumed successfully.
CC Session ID: abc123-def456
JSONL: /Users/me/.claude/projects/.../abc123-def456.jsonl
Messages: 23

Skip preflight for a one-off resume:

Terminal window
$ sfs resume ses_abc123 --in codex --no-rules-sync

Take ownership of a hand-written codex.md:

Terminal window
$ sfs resume ses_abc123 --in codex --force-rules

Create a named checkpoint of a session’s current state.

sfs checkpoint SESSION_ID --name NAME
Argument Required Description
SESSION_ID yes Session ID or prefix
Option Type Default Description
--name string required Checkpoint name

Example:

Terminal window
$ sfs checkpoint a1b2 --name "before-refactor"
Checkpoint 'before-refactor' created for session a1b2c3d4e5f6.

Fork a session into a new independent session.

sfs fork SESSION_ID --name NAME [OPTIONS]
Argument Required Description
SESSION_ID yes Session ID or prefix
Option Type Default Description
--name string required Title for the forked session
--from-checkpoint string — Fork from a named checkpoint instead of current state

Example:

Terminal window
$ sfs fork a1b2 --name "Try different approach"
Forked session created: f6e5d4c3b2a1
Title: Try different approach
Parent: a1b2c3d4e5f6

Export a session to a file.

sfs export SESSION_ID [OPTIONS]
Argument Required Description
SESSION_ID yes Session ID or prefix
Option Type Default Description
--format string sfs Export format: sfs, markdown, claude-code
--output, -o path . Output directory

Example:

Terminal window
$ sfs export a1b2 --format markdown -o ~/exports
Exported to /Users/me/exports/a1b2c3d4-e5f6-....md

Import sessions from external sources.

sfs import [FILE] [OPTIONS]
Argument Required Description
FILE no File to import (for file-based import)
Option Type Default Description
--from string — Import source: claude-code
--format string — Input format (for file import)

Example:

Terminal window
# Import all Claude Code sessions
$ sfs import --from claude-code
Found 47 Claude Code session(s).
Imported 47 new session(s).

Start the SessionFS daemon in the background.

sfs daemon start [OPTIONS]
Option Type Default Description
--config path — Path to config.toml
--log-level string INFO Log level: DEBUG, INFO, WARNING, ERROR

Example:

Terminal window
$ sfs daemon start
Daemon started (PID 12345).
Logs: /Users/me/.sessionfs/daemon.log

Stop the running daemon.

sfs daemon stop

Example:

Terminal window
$ sfs daemon stop
Sent SIGTERM to daemon (PID 12345).

Show daemon status and watcher health.

sfs daemon status

Example:

Terminal window
$ sfs daemon status
SessionFS Daemon Status
┌──────────────────┬────────────────────────┐
│ Field │ Value │
├──────────────────┼────────────────────────┤
│ PID │ 12345 │
│ Running │ Yes │
│ Sessions │ 47 │
│ Watcher: cc │ healthy (47 sessions) │
└──────────────────┴────────────────────────┘

If pushes for a session keep failing (server errors, rate limits, network), the daemon backs off instead of retrying every cycle: after 1 minute, 5 minutes, 15 minutes, then hourly. After a long failing streak (12 attempts over at least six hours) it pauses that session until the session changes, the daemon restarts, or you run sfs daemon retry-sync. sfs daemon status lists these sessions with their failure count and last error, and sfs doctor reports them under “Sync retries”.


Retry sessions whose sync is backing off or paused after failed pushes, on the daemon’s next sync cycle.

sfs daemon retry-sync [SESSION_ID]
Argument / Option Description
SESSION_ID Retry just this session (a unique prefix of its ID also works). Omit to retry every session that is backing off or paused.
--config PATH The config file the daemon was started with, if you started it with sfs daemon start --config.

Example:

Terminal window
$ sfs daemon retry-sync ses_abc12345

Show daemon log output.

sfs daemon logs [OPTIONS]
Option Type Default Description
--lines, -n int 50 Number of lines to show
--follow, -f flag false Follow log output (like tail -f)

Example:

Terminal window
$ sfs daemon logs -n 10
2026-03-20 14:30:00 sfsd INFO sfsd starting with 1 watcher(s)
2026-03-20 14:30:01 sfsd INFO sfsd running (PID 12345)

Show the current configuration.

sfs config show

Example:

Terminal window
$ sfs config show
Config: /Users/me/.sessionfs/config.toml
log_level = "INFO"
scan_interval_s = 5.0
[claude_code]
enabled = true

Set a configuration value.

sfs config set KEY VALUE
Argument Required Description
KEY yes Config key (dotted path, e.g., claude_code.enabled)
VALUE yes Value to set

Example:

Terminal window
$ sfs config set scan_interval_s 10
Set scan_interval_s = 10

Set or clear the server-canonical default organization used when capturing sessions and creating projects. Available starting v0.10.0.

sfs config default-org [ORG_ID | --clear]
Argument Required Description
ORG_ID no Org ID to use as default. Pass --clear to drop the preference.

The value is persisted on the server (users.default_org_id) and returned in GET /auth/me. Membership is validated — non-members cannot set an org as default.

Example:

Terminal window
$ sfs config default-org acme_eng
Default organization set to acme_eng.

Set or clear a session alias for easy reference.

sfs alias SESSION_ID [ALIAS]
Argument Required Description
SESSION_ID yes Session ID or prefix
ALIAS no Alias name (omit to clear)

Example:

Terminal window
$ sfs alias ses_a1b2 auth-debug
Alias set: auth-debug -> ses_a1b2c3d4e5f6
$ sfs show auth-debug # Now works with alias

Full-text search across all local sessions.

sfs search QUERY [OPTIONS]
Argument Required Description
QUERY yes Search text
Option Type Default Description
--tool string — Filter by source tool
--cloud flag false Search cloud sessions instead of local
--json flag false Output as JSON

Example:

Terminal window
$ sfs search "rate limiting middleware"
2 results:
ses_a1b2 claude-code "...added rate limiting middleware to..."
ses_c3d4 codex "...the rate limiter should handle..."

Show a session summary — files changed, tests run, commands executed.

sfs summary SESSION_ID [OPTIONS]
Argument Required Description
SESSION_ID yes Session ID or prefix
Option Type Default Description
--format string — Export format: md for markdown

Example:

Terminal window
$ sfs summary ses_a1b2
Debug auth middleware
2.3h | 327 msgs | 28 tool calls | Claude Code
Branch: feature/auth-fix @ a1b2c3d
Files modified (3):
src/auth/middleware.py
src/auth/tokens.py
tests/test_auth.py
Commands: 34
Tests: 6 runs (5 passed, 1 failed)
Packages: pyjwt, redis

Audit a session for hallucinations using LLM-as-a-Judge.

sfs audit SESSION_ID [OPTIONS]
Argument Required Description
SESSION_ID yes Session ID or prefix
Option Type Default Description
--model string claude-sonnet-4 Judge LLM model
--api-key string — LLM API key (or use config/env)
--provider string auto-detect Provider: anthropic, openai, google, openrouter
--base-url string — Custom OpenAI-compatible endpoint (LiteLLM, vLLM, Ollama)
--consensus flag false Run 3 passes, report where 2+ agree (3x cost)
--report flag false Show existing report only
--json flag false Output as JSON
--format string — Export: json, markdown, csv

Example:

Terminal window
$ sfs audit ses_a1b2 --model gpt-4o --base-url https://litellm.internal/v1
Trust Score: 74%
3 contradictions | 9 unverified | 42 verified
CRITICAL test_result msg #34 "Test passes" -> exit code 1
HIGH file_existence msg #12 "Created validator.py" -> No Write call

Delete a session from the cloud, the local device, or both. Requires an explicit scope flag – there is no default.

sfs delete SESSION_ID [OPTIONS]
Argument Required Description
SESSION_ID yes Session ID or prefix
Option Type Default Description
--cloud flag – Delete from server, keep local copy
--local flag – Remove local copy, keep cloud copy
--everywhere flag – Delete from both server and local
--force flag false Skip confirmation prompt

If no scope flag is provided, the command prints an error and exits.

Examples:

Terminal window
# Remove from cloud only (local copy stays)
$ sfs delete ses_abc123 --cloud
Delete ses_abc123 from cloud? Local copy will be kept. [y/N] y
Deleted from cloud. Recoverable for 30 days.
# Remove from this device only
$ sfs delete ses_abc123 --local
Delete ses_abc123 from this device? Cloud copy is unaffected. [y/N] y
Removed local copy.
# Delete everywhere (recoverable for 30 days)
$ sfs delete ses_abc123 --everywhere --force
Deleted from cloud and local device. Recoverable for 30 days.

See Delete Lifecycle for full details on retention, recovery, and sync behavior.


List soft-deleted sessions in the retention window.

sfs trash

Example:

Terminal window
$ sfs trash
Trash (3 sessions -- purge after 30 days)
ID Deleted Scope Purge after
ses_abc123 2 days ago cloud 2026-05-14
ses_def456 5 days ago everywhere 2026-05-11
ses_ghi789 12 days ago everywhere 2026-04-28

Undo a soft-delete. Clears the server-side deletion flag and removes the session from the local exclusion list.

sfs restore SESSION_ID
Argument Required Description
SESSION_ID yes Session ID or prefix

If the local copy was also removed (scope was everywhere), run sfs pull <id> afterward to re-download it.

Example:

Terminal window
$ sfs restore ses_abc123
Session restored. Run 'sfs pull ses_abc123' to re-download locally.

Push a session to the cloud.

sfs push SESSION_ID [--yes] [--timeout SECONDS]
Option Description
--yes, -y Skip interactive confirmations (DLP findings, cloud-undelete). Findings are still shown.
--timeout SECONDS How long to wait for the server to accept the upload (1–3600). Defaults to SFS_UPLOAD_TIMEOUT, then upload_timeout under [sync] in config.toml, then 300. Raise it for very large sessions on servers that run DLP scans.

If the server doesn’t answer in time, the push stops with a message saying so and how to raise the limit, instead of retrying the same upload.


Pull a session from the cloud.

sfs pull SESSION_ID

Since v0.24.0 the local copy is replaced to match the server: files the server version no longer has are removed, while local-only reports such as the audit report and checkpoints are kept.


Pull a session from a handoff link.

sfs pull-handoff HANDOFF_ID

Example:

Terminal window
$ sfs pull-handoff hnd_x7k9
Session pulled. 47 messages.
Run: sfs resume ses_abc --in claude-code

List sessions stored on the cloud server.

sfs list-remote [OPTIONS]
Option Type Default Description
--page int 1 Page number
--page-size int 20 Results per page

Hand off a session to a teammate with email notification.

sfs handoff SESSION_ID --to EMAIL [OPTIONS]
Option Type Default Description
--to string required Recipient email
--message string — Message to include in the email

Bidirectional sync and autosync management.

Run bidirectional sync — push local changes, pull remote-only sessions.

sfs sync

Set autosync mode.

sfs sync auto --mode MODE
Mode Behavior
off No autosync (default). Manual sfs push only.
all Every new or updated session auto-pushes to cloud.
selective Only sessions in the watchlist auto-push.

Add sessions to the autosync watchlist (selective mode).

sfs sync watch SESSION_ID [SESSION_ID...]

Remove sessions from the autosync watchlist.

sfs sync unwatch SESSION_ID [SESSION_ID...]

Show all sessions in the autosync watchlist.

sfs sync watchlist

Show current autosync mode, counts, and storage usage.

sfs sync status

Manage shared project context — a single document shared across the team via MCP.

Create a project context for the current repo (matched by git remote).

sfs project init [--org ORG_ID | --personal]
Option Type Default Description
--org string — Create the project scoped to the given organization (caller must be a member)
--personal flag default Create the project under the caller’s personal scope

When --org is supplied, the project inherits the org’s knowledge base creation defaults at create time. If neither flag is supplied, the project is personal-scope (pre-v0.10.0 behavior).

Display the current project context with metadata.

sfs project show

Open the context document in $EDITOR. Changes upload on save.

sfs project edit

Set project context from a file.

sfs project set-context FILE

Output raw project context markdown to stdout.

sfs project get-context

Compile pending knowledge entries into the project context document.

sfs project compile

Example:

Terminal window
$ sfs project compile
Compiling pending entries...
Project context updated. 12 entries compiled.

Force a full re-compile of the project context. Resets compiled_at=NULL on all active claims and clears context_document, so the next compile pass pulls every active claim from scratch. Useful on settled projects where normal compile would be a no-op.

sfs project rebuild

Example:

Terminal window
$ sfs project rebuild
Project context reset. Run `sfs project compile` to regenerate.

List knowledge entries for this project.

sfs project entries [OPTIONS]
Option Type Default Description
--pending flag false Show only pending (uncompiled) entries
--type string — Filter by type: decision, pattern, discovery, convention, bug, dependency
--limit int 20 Max entries to show

Example:

Terminal window
$ sfs project entries --type decision --limit 5
┌────┬──────────┬────────────────────────────────────────┬──────────┬──────────────────┬──────────┐
│ ID │ Type │ Content │ Age │ Session │ Status │
├────┼──────────┼────────────────────────────────────────┼──────────┼──────────────────┼──────────┤
│ 42 │ decision │ HTTP + ETags only, no WebSockets │ 3d ago │ ses_a1b2c3d4e5.. │ compiled │
│ 38 │ decision │ Sessions are append-only │ 5d ago │ ses_f6e5d4c3b2.. │ pending │
└────┴──────────┴────────────────────────────────────────┴──────────┴──────────────────┴──────────┘
Showing 2 of 2 entries

Ask a question about the project using the knowledge base.

sfs project ask QUESTION
Argument Required Description
QUESTION yes Question about the project

Searches knowledge entries and project context for relevant answers. Optionally saves the Q&A back to the knowledge base.

Example:

Terminal window
$ sfs project ask "How does session conflict resolution work?"
╭─ Question: How does session conflict resolution work? ─╮
╰────────────────────────────────────────────────────────╯
Matching Knowledge Entries (2):
[decision] Sessions are append-only — conflict resolution appends both sides
Session: ses_a1b2 | 2026-03-15 | confidence: 95%
[pattern] Merge strategy: append both sides rather than 3-way merge
Session: ses_c3d4 | 2026-03-10 | confidence: 90%
Related Sessions:
sfs show ses_a1b2
sfs show ses_c3d4
Save this Q&A to the knowledge base? [y/N]:

List wiki pages for this project.

sfs project pages

Example:

Terminal window
$ sfs project pages
┌──────────────────┬──────────────────────────┬──────────┬───────┬─────────┬──────┐
│ Slug │ Title │ Type │ Words │ Entries │ Auto │
├──────────────────┼──────────────────────────┼──────────┼───────┼─────────┼──────┤
│ session-format │ Session Format (.sfs) │ concept │ 420 │ 8 │ yes │
│ conflict-resolve │ Conflict Resolution │ concept │ 310 │ 5 │ yes │
│ daemon-arch │ Daemon Architecture │ manual │ 850 │ 0 │ no │
└──────────────────┴──────────────────────────┴──────────┴───────┴─────────┴──────┘
3 pages

View a wiki page by slug.

sfs project page SLUG
Argument Required Description
SLUG yes Page slug

Example:

Terminal window
$ sfs project page session-format
╭──────────── Session Format (.sfs) ────────────╮
│ A .sfs session is a directory containing: │
│ manifest.json, messages.jsonl, workspace.json, │
│ tools.json. All file paths within are relative │
│ to workspace root. │
│ ... │
╰──────────── session-format (auto-generated) ──╯
Backlinks:
entry:42 (references)
entry:38 (defines)

Run health checks on the project knowledge base.

sfs project health

Reports entry counts, compilation status, staleness, and a health score.

Example:

Terminal window
$ sfs project health
Project Health: sessionfs
✓ Context document exists (2400 words, 8 sections)
✓ 45 knowledge entries (38 compiled, 2 dismissed)
⚠ 5 entries pending compilation
✓ Last compiled: 2026-03-28
✓ Context appears up to date
Health Score: 90%

Regenerate an auto-generated concept article from the latest knowledge entries.

sfs project regenerate SLUG
Argument Required Description
SLUG yes Page slug to regenerate

Example:

Terminal window
$ sfs project regenerate session-format
Regenerating page 'session-format'...
Article regenerated (420 words from 8 entries).

Update project settings.

sfs project set [OPTIONS]
Option Type Description
--name string Rename the project (project-admin only). Available starting v0.12.1.
--auto-narrative / --no-auto-narrative flag Enable or disable auto-narrative generation on sync

Example:

Terminal window
$ sfs project set --auto-narrative
auto_narrative = True
Terminal window
$ sfs project set --name "Acme Platform"
name = Acme Platform

Dismiss an irrelevant knowledge entry so it is excluded from future compilations.

sfs project dismiss ENTRY_ID
Argument Required Description
ENTRY_ID yes Numeric entry ID

Example:

Terminal window
$ sfs project dismiss 38
Entry 38 dismissed.

Initiate, accept, reject, or cancel a project transfer between scopes (personal ↔ org, or org ↔ org). Available starting v0.10.0.

sfs project transfer (--to TARGET | --accept ID | --reject ID | --cancel ID) [--force]
Option Type Description
--to string Initiate a transfer to the given target. Use personal for personal scope, or an org ID for an org you belong to.
--accept string Accept an incoming pending transfer by ID.
--reject string Reject an incoming pending transfer by ID.
--cancel string Cancel an outgoing pending transfer you initiated.
--force flag With --to (auto-accepted) or --accept: transfer even if open tickets rely on org personas the destination lacks.

The transfer is auto-accepted when the initiator and target are the same user/org (e.g. moving a personal project into your own org). Standing is re-validated on accept/reject, so a member demoted between initiate and accept loses the right to act on the transfer.

Org personas and transfers (GH #70): moving a project into a different org or out of one is refused (409 personas_stranded) when open tickets are assigned to org personas that will not exist in the destination; the error lists each persona and its ticket ids. Project personas move with the project, so a same-named project persona avoids the refusal. Nothing is copied automatically: reassign the tickets, create the personas in the destination, or pass --force (on --to when the transfer auto-accepts, or on --accept).

Example:

Terminal window
$ sfs project transfer --to acme_eng
Transfer initiated. Awaiting target acceptance: xfer_a1b2c3

List project transfers involving the caller.

sfs project transfers [--direction incoming|outgoing] [--state pending|accepted|rejected|cancelled|expired]
Option Type Default Description
--direction string both Filter by incoming or outgoing transfers
--state string all Filter by transfer state

A transfer proposed by an org admin (v0.23.0) appears in the project owner’s incoming list labelled Proposed by <admin> for <org>: <reason> with its expiry, and in the proposer’s outgoing list the same way. Accept or decline it with sfs project transfer --accept / --reject.

Set the scheduled knowledge-base compile for the current project (v0.23.0). sfs project show displays the current schedule.

sfs project compile-schedule nightly
sfs project compile-schedule weekly --after-claims 20
sfs project compile-schedule off
sfs project compile-schedule weekly --no-after-claims
Argument / option Type Description
schedule off | nightly | weekly How often the scheduled compile rebuilds the context document
--after-claims int Also compile once this many claims are waiting, whatever the schedule (1+)
--no-after-claims flag Clear the waiting-claims threshold so the project compiles only on schedule

nightly makes the project eligible every 24 hours, weekly every 7 days. off turns off the time-based schedule, but an --after-claims threshold still applies. Scheduled compiles use the deterministic compiler, never an LLM. On self-hosted servers the schedule takes effect only when something calls the compile sweep (see Self-Hosted).

Group an org’s projects and grant people access to the whole group (v0.26.0). Every command addresses a group by its slug and takes --org (default: your default org); most take --json. sfs project list --group SLUG lists only that group’s projects. See Project Groups.

Command Description
sfs project group list The org’s groups
sfs project group create NAME [--slug S] [--description D] Create a group (org admin or owner)
sfs project group show GROUP A group’s members and projects
sfs project group set GROUP [--name N] [--slug S] [--description D] [--compile|--no-compile] Rename or describe a group, or turn its overview compile on or off (group admin)
sfs project group delete GROUP Delete a group (org admin or owner)
sfs project group add GROUP PROJECT_ID... Add projects (group admin who can edit each project)
sfs project group remove GROUP PROJECT_ID Remove a project (group admin)
sfs project group members GROUP Members and their roles
sfs project group grant GROUP USER --role reader|editor|admin Grant or change a member’s role; USER is an org member’s email or user id (group admin)
sfs project group grant GROUP --file FILE [--role R] Grant up to 100 members at once; one email or user id per line, optionally email,role (--role is the default). All or nothing
sfs project group revoke GROUP USER Revoke a member’s grant (group admin)
sfs project group access Every group you have access to, across your orgs
sfs project group search GROUP [QUERY] [--entry-type T] [--limit N] Search knowledge claims across the group’s projects you can read (QUERY 3–200 characters; omit it to list top claims)
sfs project group context GROUP The group’s compiled overview
sfs project group compile GROUP Compile the overview (group editor or admin; the group must have compile turned on)

sfs project confluence publish (Enterprise)

Section titled “sfs project confluence publish (Enterprise)”

Publish a wiki page, or with --context the project context document, to the Confluence space mapped to this project (v0.26.0). See Confluence Cloud.

sfs project confluence publish architecture --preview
sfs project confluence publish --context --yes
Argument / option Description
slug Wiki page slug to publish
--context Publish the project context document instead of a wiki page
--preview Show the draft, with its citations and anything dropped, without publishing
--yes, -y Skip the confirmation prompt

Manage canonical project rules and compile them into the tool-specific files each AI agent reads (CLAUDE.md, codex.md, .cursorrules, .github/copilot-instructions.md, GEMINI.md). See Rules Portability for the full reference.

Seed canonical rules for the current project. Detects the git remote, preselects enabled tools from existing rule files + recent tool usage, and optionally imports a single unmanaged rule file as the canonical seed.

sfs rules init [--local-only]
Option Type Default Description
--local-only flag false Gitignore the compiled rule files instead of committing them

Only the five v0.9.9-supported tools are preselected: claude-code, codex, cursor, copilot, gemini. The picker shows the reason for each preselection (file present, recent usage, or manual pick).

Example:

Terminal window
$ sfs rules init
Detected rule files:
CLAUDE.md (reason: file present)
.cursorrules (reason: file present)
Recent tool usage (last 90 days):
codex (reason: recent usage)
Enable these tools? [Y/n]
Seeded canonical rules for myorg/my-project.
Run 'sfs rules edit' to edit preferences, then 'sfs rules compile'.

Open the canonical static_rules document in $EDITOR.

sfs rules edit

Show current canonical version, enabled tools, knowledge/context injection config, and whether compiled outputs are in sync.

sfs rules show

Example:

Terminal window
$ sfs rules show
Project: myorg/my-project
Canonical version: 4
Enabled tools: claude-code, codex, cursor, gemini
Knowledge injection: on
Types: convention, decision
Budget: 2000 tokens
Context injection: on
Sections: overview, architecture
Budget: 2000 tokens
Compiled outputs: in sync (last compile: 2026-04-12)

Compile canonical rules into tool-specific files. Deterministic — no new version is created unless a compiled output changes by hash.

sfs rules compile [--tool TOOL] [--dry-run] [--force]
Option Type Default Description
--tool string — Compile for a single tool only
--dry-run flag false Show what would be written without touching disk
--force flag false Overwrite files not managed by SessionFS

Example:

Terminal window
$ sfs rules compile
Compiling canonical rules v4...
CLAUDE.md written (sha256:9a1c…)
codex.md written (sha256:4e2f…)
.cursorrules written (sha256:b7d1…)
.github/copilot-instructions.md written (sha256:c3a8…)
GEMINI.md written (sha256:5f90…)
New rules version: 5

SessionFS refuses to overwrite a rule file that is not managed (no SessionFS marker and not created by sfs rules init). Use sfs rules init to import it, or pass --force.

Push the canonical record and latest compiled version to the SessionFS API. Uses optimistic concurrency — a stale write returns 409 Conflict.

sfs rules push

Pull canonical rules from the SessionFS API. Run sfs rules compile afterwards to regenerate tool files.

sfs rules pull

Print the latest compiled rules for a tool to stdout. Reads from the local rule cache populated by sfs rules compile and sfs rules pull — never hits the network.

sfs rules emit --tool TOOL [--format hook|file]
Option Type Default Description
--tool string required Target tool (claude-code, codex, cursor, copilot, gemini)
--format string hook hook for Claude Code’s hook JSON spec, file for the plain compiled body

--format hook is the format the SessionStart hook installed by sfs hooks install consumes. --format file is useful for piping the compiled body into another tool or inspecting it from the shell. If the local cache is empty, the command prints an empty payload and exits 0 — it never breaks Claude Code startup.

Example:

Terminal window
$ sfs rules emit --tool claude-code --format hook
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "..."
}
}

Manage SessionFS hooks for tools with native hook support. v0.10.1 supports Claude Code only. See Hook-based injection for the full reference.

Wire the SessionFS SessionStart hook into the target tool’s settings. The hook calls sfs rules emit on every session start and pipes the compiled rules into the system prompt. Idempotent — running twice does not duplicate the entry.

sfs hooks install --for TOOL [--user|--project] [--force]
Option Type Default Description
--for string required Target tool (claude-code only in v0.10.1)
--user flag default Install at user scope (~/.claude/settings.json)
--project flag false Install at project scope (.claude/settings.json in repo root)
--force flag false Skip the conflict warning when a managed CLAUDE.md already exists

Example:

Terminal window
$ sfs hooks install --for claude-code
Hook installed: ~/.claude/settings.json (SessionStart)
SessionFS will inject project rules at every Claude Code startup.

Remove the SessionFS-managed hook entry from the target tool’s settings. Idempotent — no-op if not installed.

sfs hooks uninstall --for TOOL [--user|--project] [--force]
Option Type Default Description
--for string required Target tool (claude-code only in v0.10.1)
--user flag default Uninstall from user scope
--project flag false Uninstall from project scope
--force flag false Skip the confirmation prompt

Show which SessionFS hooks are installed across supported tools and scopes. Tools without native hook support appear as N/A.

sfs hooks status

Example:

Terminal window
$ sfs hooks status
SessionFS Hooks
───────────────
claude-code (user): INSTALLED at ~/.claude/settings.json (SessionStart)
claude-code (project): not installed
codex: N/A (no native hook system)
gemini: N/A
cursor: N/A

Manage local session storage.

Show local disk usage, session counts, and retention policy.

sfs storage

Prune old sessions to free disk space.

sfs storage prune [OPTIONS]
Option Type Default Description
--dry-run flag false Show what would be pruned without deleting
--force flag false Skip confirmation prompt

Restart the daemon (stop + start).

sfs daemon restart

Manage tool watchers.

List all tool watchers and their status.

sfs watcher list

Enable a tool watcher.

sfs watcher enable TOOL

Disable a tool watcher.

sfs watcher disable TOOL

Manage cloud authentication.

Authenticate with the cloud server.

sfs auth login [OPTIONS]
Option Type Default Description
--url string https://api.sessionfs.dev Server URL
--key string — API key

Create a new account.

sfs auth signup [OPTIONS]
Option Type Default Description
--url string https://api.sessionfs.dev Server URL

Show current authentication status.

sfs auth status

Start the MCP server on stdio transport.

sfs mcp serve

Tools exposed: 130, covering sessions (including ask_session_helper), knowledge, rules, personas, tickets (including watch_ticket and get_ticket_updates), agent runs (including replay_agent_run, report_agent_run_usage and get_spend_summary), review-loop rollups (get_loop_report), merge readiness (check_merge_readiness), review loops (start_review_loop, get_loop_status and update_review_loop), workflow templates (list_workflow_templates, get_workflow_template, start_workflow and get_workflow_plan), the review checklist (get_loop_checklist and propose_checklist_item), agent feedback, handoffs, work queues, the skills marketplace, project groups, meetings and chat threads (upload_chat_thread), reminders, approvals (read only) and For You (get_my_attention). See MCP Server for the full catalogue.


Auto-configure SessionFS as an MCP server for an AI tool. Also injects knowledge-contribution instructions into the tool’s project config file.

sfs mcp install --for TOOL [OPTIONS]
Option Type Description
--for string Target tool: claude-code, codex, gemini, cursor, copilot, amp, cline, roo-code, kilo-code, antigravity
--skip-instructions flag Skip injecting knowledge-contribution instructions into project config

Example:

Terminal window
$ sfs mcp install --for claude-code
Added SessionFS MCP server in Claude Code.
Config: /Users/me/.claude.json
Restart Claude Code to activate.
Appended knowledge instructions to CLAUDE.md
Your AI agent can now search past sessions:
"Has anyone on the team seen this error before?"
"What was the fix for the auth middleware bug?"

Remove SessionFS MCP server registration and knowledge instructions from an AI tool.

sfs mcp uninstall --for TOOL
Option Type Description
--for string Target tool: claude-code, codex, gemini, cursor, copilot, amp, cline, roo-code, kilo-code, antigravity

Example:

Terminal window
$ sfs mcp uninstall --for cursor
Removed SessionFS MCP server from Cursor.
Restart Cursor to apply.
Removed knowledge instructions from .cursorrules

Rebuild the full-text search index from all local sessions.

sfs mcp index

Example:

Terminal window
$ sfs mcp index
Search index rebuilt: 47 sessions indexed.

Interactive setup wizard for SessionFS. Detects installed AI coding tools, writes configuration, optionally sets up cloud sync, and starts the daemon.

sfs init

Detects: Claude Code, Cursor, Codex, Gemini CLI, Copilot, Amp, Cline, Roo Code, Kilo Code, Antigravity.

Example:

Terminal window
$ sfs init
SessionFS Setup
Scanning for AI coding tools...
✓ Claude Code detected (~/.claude)
✓ Cursor detected (~/Library/Application Support/Cursor)
✓ Gemini CLI detected (~/.gemini)
✗ Codex not found
Found 3 tools. Track all? [Y/n]: y
Cloud sync lets you access sessions from any machine and share with teammates.
Set up cloud sync now? [y/N]: n
Start the SessionFS daemon now? [Y/n]: y
✓ Daemon started! Watching 3 tools.
Sessions stored in: /Users/me/.sessionfs/sessions
Next steps:
sfs list — View captured sessions
sfs show <id> — Inspect a session
sfs resume <id> — Resume in any tool
sfs search "query" — Search past sessions

Run 9 health checks with auto-repair. Checks store directory, session count, index integrity, index freshness, daemon status, API reachability, authentication, config permissions, and capture health (detects when an AI tool’s format change has silently broken capture — an idle tool is never flagged). Automatically repairs corrupted indexes.

sfs doctor

Example:

Terminal window
$ sfs doctor
SessionFS Health Check
┌─────────────────────┬────────┬──────────────────────────┐
│ Check │ Status │ Detail │
├─────────────────────┼────────┼──────────────────────────┤
│ Store directory │ ✓ │ /Users/me/.sessionfs │
│ Sessions directory │ ✓ │ 47 session(s) on disk │
│ Session index │ ✓ │ 47 indexed │
│ Index freshness │ ✓ │ in sync │
│ Daemon │ ✓ │ running (PID 12345) │
│ API server │ ✓ │ reachable (https://...) │
│ Authentication │ ✓ │ me@example.com (team) │
│ Config permissions │ ✓ │ permissions OK (0o600) │
│ Capture health │ ✓ │ all watched tools healthy │
└─────────────────────┴────────┴──────────────────────────┘

Scan local sessions for secrets and PHI. SessionFS ships with 20 secret patterns (API keys, access tokens, private keys, database URLs) and 14 PHI patterns (SSN, phone, credit card, medical IDs).

sfs dlp scan [SESSION_ID ...] [--mode MODE] [--format FORMAT]
Option Description
--mode warn|redact|block Action on findings (default: warn)
--format json|text Output format (default: text)
--verbose Show matched substrings
Terminal window
$ sfs dlp scan ses_abc123
2 findings in ses_abc123:
[HIGH] AWS access key in messages.jsonl:142
[MEDIUM] Email address in messages.jsonl:89

View or update the organization DLP policy. Applies server-side to all org members on sync.

sfs dlp policy [--get|--set-mode MODE|--enable|--disable]
Option Description
--get Show current policy
--set-mode warn|redact|block Update the policy mode
--enable Enable DLP scanning
--disable Disable DLP scanning

When set to block, uploads containing detected secrets/PHI are rejected. When set to redact, findings are automatically redacted before storage.


Run local security checks: config file permissions, API key exposure in shell configs, dependency vulnerabilities (via pip-audit), and stale sessions.

sfs security scan

Example:

Terminal window
$ sfs security scan
Security Scan Results
────────────────────────────────────────
✓ Config permissions: OK (0o600)
✓ API key exposure: No keys found in shell configs
✓ Dependencies: No vulnerabilities found
✓ Stale sessions: No stale sessions
All checks passed.

Auto-fix security issues where safe to do so. Fixes config permissions, upgrades vulnerable packages (with confirmation), and warns about issues requiring manual action.

sfs security fix [OPTIONS]
Option Type Default Description
--yes, -y flag false Skip confirmation prompts

Example:

Terminal window
$ sfs security fix
Security Fix
────────────────────────────────────────
✓ Fixed config permissions: 0o644 -> 0o600
Vulnerable packages with available fixes:
- cryptography>=44.0.0
Upgrade these packages? [y/N]: y
✓ Upgraded 1 packages
Fixed 2 issue(s).

Re-extract metadata for all cloud sessions (admin only).

sfs admin reindex

Poll organization Git marketplace registries now (platform admin, or a skills_registry:poll service key in SESSIONFS_API_KEY). The API polls up to --limit due registries and publishes each new matching tag through the normal org publish checks; each registry is leased while it is polled, so concurrent runs never poll one twice. Use it from a self-hosted cron, or enable the Helm CronJob instead. Exits 2 when a registry failed. See Polling Git Registries.

sfs admin registries poll [--limit N] [--registry ID ...] [--until-idle] [--max-runs N]
Option Default Description
--limit 5 Registries polled per request (1-20)
--registry — Poll this registry id now regardless of its schedule (repeatable)
--until-idle off Keep requesting batches while a full batch was polled
--max-runs 20 Stop after this many requests

Show the platform admin audit log, newest first (platform admin only): action, target, admin, reason, and before/after state when captured. Entries with source operator_record were recorded by an operator and not verified by the server. See Auditing Operator Overrides.

sfs admin audit-log [--target-type TYPE] [--target-id ID] [--action NAME] [--source api|operator_record] [--admin-id USER_ID] [--limit N] [--page N] [--json]
Option Default Description
--target-type / --target-id — Only entries for this target
--admin-id — Only entries performed or recorded by this admin
--action — Only entries with this action
--source — api or operator_record
--limit 50 Entries per page (1-200)
--json off Print the raw JSON, including the full before/after state

Org-scoped service keys for CI runners, agents and scheduled jobs (org owner or admin, Team or above). See API keys.

sfs admin service-keys list --org ORG_ID
sfs admin service-keys create --org ORG_ID --name NAME --scope SCOPE [--scope SCOPE]... [--expires-days N] [--project PID]... [--output-key]
sfs admin service-keys rotate KEY_ID --org ORG_ID [--output-key]
sfs admin service-keys revoke KEY_ID --org ORG_ID --reason "..."
sfs admin service-keys scopes

The raw key is printed once on create and rotate; --output-key prints only the key, for capturing in scripts. Platform scopes such as platform_sweeps:run (used by scheduled sweeps) can only be minted by a platform admin, and the key works only while the admin who minted or last rotated it and the user it runs as are both still platform admins. Since v0.28.0, create and rotate print a warning about this to stderr, scopes marks those scopes as tier-coupled, and list has a Coupling column that reads ok, or inactive: … with the reason once the key has stopped working. A request with such a key gets a 403 that names the cause and the fix.

Audited operator overrides (platform admin only).

sfs admin override project-transfer PROJECT_ID --to-org ORG_ID --reason "..." [--new-owner USER_ID] [--expect-from ORG_ID|personal] [--force] [--yes]
sfs admin override project-transfer --propose --project PROJECT_ID --org ORG_ID --reason "..."
sfs admin override record --action NAME --target-type TYPE --target-id ID --reason "..." [--before-file F] [--after-file F]
sfs admin override user-merge SOURCE_USER_ID TARGET_USER_ID --reason "..." [--apply] [--yes] [--json]
sfs admin override project-merge SOURCE_PROJECT_ID TARGET_PROJECT_ID --reason "..." [--persona-policy rename|skip|merge_content] [--apply] [--yes] [--json]

project-transfer moves a project into an organization without the owner’s consent. It keeps the normal transfer checks (merged projects and stranded org personas are refused unless --force), cancels any pending transfer, and commits the move together with an audit entry holding the reason and before/after state. The owner must be a member of the destination organization; otherwise pass --new-owner with an active member, who becomes the owner. --expect-from refuses the move unless the project is still in the given org (or personal), so a retried command cannot move it twice. With --propose (v0.23.0) nothing is forced: the command asks the owner of a personal project to move it into an org, and the project moves only when the owner accepts (POST /api/v1/orgs/{org_id}/projects/{project_id}/propose-transfer). The caller must be an owner or admin of the destination org, and the project owner must be an active member of it. One pending transfer per project (409 transfer_pending); the same project and org can’t be proposed again for 7 days after a decline or 24 hours after a cancel (409 proposal_cooldown); an org can hold at most 10 pending proposals (409 proposal_limit); proposals expire after 7 days. Use --project and --org in this mode. record logs an action performed outside the API, such as raw SQL; it is stored with source operator_record. Reasons are 1-500 characters; state files must hold a JSON object of at most 64 KiB.

Fold a duplicate account (for example a signup with a typo in the email) into the account to keep. Calls POST /api/v1/admin/users/{source_id}/merge-into/{target_id}. Dry run by default: it writes nothing and prints, per table, how many rows would be reassigned, deduplicated, revoked or cancelled (--json includes the row ids). --apply performs the merge in one transaction, deactivates the source user, revokes its API keys and writes exactly one user_merge audit entry with the reason and the state before and after. Prompts for confirmation when applying unless --yes.

  • Reassigned to the target: sessions, projects, share links, bookmarks, handoffs, knowledge entries, context compilations, tickets (creator, resolver, comments, edits), wiki revisions, personas (creator and represented member), work queues, rules, GitHub installation and the source’s plan records. Source storage usage is added to the target’s. A session alias the target already uses is cleared, and the sync watchlist keeps one row per session.
  • Deduplicated: org memberships (the higher role wins, the target on ties), and team memberships, devices, GitLab settings and judge settings (the target’s row wins).
  • Revoked, never moved: API keys (including service keys), trusted-reviewer bindings, SSO break-glass grants and SSO identities, and pending ownership or project transfers involving the source.
  • Left alone: audit and history tables, so past actions keep the original actor.

The merge refuses, changing nothing, when source and target are the same (400); either user does not exist (404); the target is inactive (409 target_inactive); the source is a platform admin (409 source_is_platform_admin); the source has billing attached (409 source_has_billing); both users hold an active plan (409 entitlement_conflict — it never guesses which plan to keep); the source owns skill marketplace packages, publishers, listings or registries (409 marketplace_assets_owned); both have a GitHub installation (409 github_installation_conflict); or the source owns org projects in an org neither user belongs to (409 project_owner_not_member).

Option Default Description
--reason, -r required Why the merge is needed (1-500 characters), stored in the audit log
--apply off Perform the merge. Without it the command is a dry run
--yes, -y off Skip the confirmation prompt when applying
--json off Print the raw JSON response, including the row ids

Merge a duplicate project into the one to keep, whoever owns them. Use it when the owners can’t run sfs project merge themselves, for example when the two projects belong to different users. Calls POST /api/v1/admin/projects/{target_id}/merge-from/{source_id}. It runs the same merge as sfs project merge: sessions, knowledge entries, wiki pages, tickets, personas, agent runs, handoffs and repos move to the target, and the source becomes a redirect to it. Dry run by default: prints the counts that would move. --apply merges in one transaction and writes one project_merge audit entry with the reason and the state before and after. Prompts for confirmation when applying unless --yes.

Both projects must be in the same org, or both personal (400 cross_scope otherwise: move one with sfs admin override project-transfer first). Owners don’t have to match: merging one user’s personal project into another user’s gives the target’s owner everything in the source, so check the dry run. It also refuses a project that is already merged or has a pending transfer.

Option Default Description
--reason, -r required Why the merge is needed (1-500 characters), stored in the audit log
--persona-policy rename What to do when both projects have a persona with the same name: rename, skip or merge_content
--apply off Perform the merge. Without it the command is a dry run
--yes, -y off Skip the confirmation prompt when applying
--json off Print the raw JSON response

Register, list, or revoke an organization’s trusted reviewers (org-admin only). A trusted reviewer is authorized to post review verdicts that the autonomous work queue’s stop oracle will trust — typically a dedicated automated reviewer key. Tightly gated and fully audited. Available starting v0.12.1.

sfs admin trusted-reviewers (list | add | revoke) [OPTIONS]

Run, complete, replay and measure agent runs against tickets. The run lifecycle (run, complete, status, list, replay, compare) and CI workflow are covered in CI integration; structured outcome records live under sfs agent feedback. This section documents usage reporting and the spend rollup.

sfs agent run also takes --model, --provider, --role (implementer, ui-implementer, reviewer, design-reviewer, security-reviewer or release) and --branch, so runs can be sliced by model and role. sfs agent complete takes the run’s usage and outcome:

Option Type Description
--input-tokens / --output-tokens integer Token usage (added to anything already reported)
--cache-read-tokens / --cache-write-tokens integer Cache token usage (additive)
--cost-usd number Cost in USD (additive)
--cost-basis string reported (the cost the tool or provider reported), estimated (your own estimate), plan (covered by a subscription, no per-token cost) or unknown
--head-sha string Head commit the run finished on (7–64 hex chars)
--exit-reason string finished, out_of_turns or crashed

Add token and cost usage to a queued or running run, for long runs and continuations that report more than once. Values are added to the run’s totals. Once the run is complete, the totals are fixed and further reports are refused.

sfs agent usage RUN_ID [--input-tokens N] [--output-tokens N] [--cache-read-tokens N] [--cache-write-tokens N] [--cost-usd X]

At least one value is required.

Summarize agent-run spend for a ticket or the current project. Dollar amounts only appear when the caller has admin standing on the project (org owners/admins, or the owner of a personal project); token totals are always shown. Service keys never see dollar figures.

sfs agent spend --ticket ID
sfs agent spend --project [--group-by GROUP] [--from ISO] [--to ISO] [--format text|json]
Option Type Description
--ticket string Ticket id to summarize (totals, per-persona, per-model, review rounds)
--project flag Summarize the current project (defaults to the last 30 days)
--group-by string persona | model | ticket | role | day (project view only)
--from string Start of the created_at window (ISO datetime)
--to string End of the created_at window (ISO datetime)
--format string text (default) or json

Only runs with a reported or estimated cost basis add dollars; plan and unknown runs (including runs that reported tokens but no cost) add tokens only, shown separately as tokens on plans.


Start, watch and budget a worker review loop, run its workers and record its review rounds, read its reports, keep its checklist, check merge readiness and share a ticket’s story. Tier: Team+ (the checklist and sfs loop ready are on every plan). From v0.29.2.

Command Description
sfs loop start <ticket-id-or-title> --reviewer-persona NAME [--ticket 'title::description' ...] [--criteria TEXT ...] [--token-budget N] [--cost-budget-usd N] [--max-review-rounds N] Start a loop on an existing issue, or create one from a title. Files one child task per --ticket and creates the reviewer’s queue. --cost-budget-usd needs org owner or admin standing; there is no default round cap
sfs loop status [LOOP_ID] One loop’s children (status, branch, head, rounds, spend), or every loop when the id is omitted
sfs loop update LOOP_ID [--token-budget N] [--cost-budget-usd N] [--max-review-rounds N] Raise a limit
sfs loop close-item LOOP_ID TICKET_ID Close an item the loop handed back as needing a person. Users only; service keys are refused
sfs loop run start TICKET_ID [--model M] [--provider P] [--branch B] [--step STEP_ID] [--output-id] Take the ticket’s lease and open a worker run; prints the run id and what is left of the budget (v0.29.3)
sfs loop run finish RUN_ID --head-sha SHA [--exit-reason finished|out_of_turns|crashed] [--branch B] [--input-tokens N] [--output-tokens N] [--cache-read-tokens N] [--cache-write-tokens N] [--cost-usd N] [--cost-basis BASIS] [--summary TEXT] [--step STEP_ID] Record the commit, how the worker exited and its tokens. Repeating it never counts usage twice (v0.29.3)
sfs loop review LOOP_ID --ticket TICKET_ID --round N --commit SHA --verdict VERIFIED-CLEAN|CHANGES-REQUESTED [--findings-file FILE] [--stage code|design] [--model M] [--provider P] [--input-tokens N] [--output-tokens N] [--cost-usd N] [--step STEP_ID] Record a review round for an exact commit. The findings file is a JSON list of {severity, class, harm, title, file?, line?, status?}. Pass the loop id as --ticket for a design round (v0.29.3)
sfs loop report TICKET_ID Per-round findings by harm, known versus new classes and round cost
sfs loop insights [--from DATE] [--to DATE] Findings caught, cost per accepted change and checklist learning
sfs loop checklist list [--status proposed|active|retired] Show the project checklist
sfs loop checklist seed Offer the generic starter items as proposals
sfs loop checklist add TITLE [--check TEXT] [--slug SLUG] Propose an item
sfs loop checklist accept SLUG / retire SLUG Activate or retire an item
sfs loop ready TICKET_ID --sha HEAD_COMMIT Merge readiness (below)
sfs loop share story TICKET_ID [--expires-days N] Mint a public, revocable link to a ticket’s story. The raw token is printed once and is never stored. Team+ to create; list and revoke keep working after a downgrade
sfs loop share ship-report VERSION [--expires-days N] Mint a public, revocable link to a ship report
sfs loop share list List the project’s share links (tokens are never shown)
sfs loop share revoke LINK_ID Revoke a share link

In a workflow loop, --step names the template step the report is for. The server checks that the step exists, its dependencies are done and its role matches, and refuses a mismatch with 422.

Dollar figures are shown only to org owners and admins, or the owner of a personal project.

Check whether a ticket’s work is safe to merge at a given head commit. Pure read: a person still does the merge.

sfs loop ready TICKET_ID --sha HEAD_COMMIT
Option Type Description
--sha string Full head commit id (40 or 64 lowercase hex characters)

Prints READY only when a trusted strict VERIFIED-CLEAN verdict is bound to exactly that commit, the reviewer’s identity differs from every implementer identity recorded for the ticket, and no open finding is harmful. Otherwise it prints NOT READY with the reasons and exits 1, so it can gate a script. MCP: check_merge_readiness.


Record-only workflow templates: store a multi-agent plan, start a loop from it, and read which steps are ready with their agents and briefs. SessionFS never starts an agent; your orchestrator does, and reports each step with --step. Tier: Team+ to start a workflow. Commands use the project of the current repository; --org works on the org’s templates.

Command Description
sfs workflow list [--org ORG] [--json] Active templates: the project’s own plus its org’s
sfs workflow show TEMPLATE_ID [--org ORG] [--json] One template version with its steps and brief templates
sfs workflow create FILE [--name NAME] [--org ORG] Create a template from a YAML or JSON file, validated locally before anything is sent
sfs workflow update TEMPLATE_ID FILE [--name NAME] [--org ORG] Save a new version; the old one is deactivated and running loops keep their pinned version
sfs workflow disable TEMPLATE_ID [--org ORG] Deactivate a version
sfs workflow start TEMPLATE_ID --ticket TK | --title TEXT [--description TEXT] [--reviewer-persona NAME] [--token-budget N] [--cost-budget-usd N] [--max-review-rounds N] [--output-id] Start a workflow loop. --output-id prints only the loop id
sfs workflow plan LOOP_ID [--json] Each step’s state, gate and reason, then the ready tickets with their agents and briefs

Project editors write project templates and org admins write org templates. See Workflow templates for the file format.


Record releases, their gates and their deployments, and read the Ship Report. Release events also arrive on their own from the GitHub App and the delivery webhooks. Tier: Team+. From v0.29.3.

Command Description
sfs release record VERSION --tag-sha SHA [--previous SHA] [--pr N ...] [--gate kind=status ...] [--source SOURCE] Record a release at a commit, link the pull requests it shipped and record its gates (for example --gate ci=passed). Source is github_release, gitlab_release, helm_sync or manual (default)
sfs release deploy VERSION --env ENV [--source argocd|helm|manual] Record a deployment of a release to an environment
sfs release list Releases with their gates and deployments
sfs release ship-report [VERSION] [--month YYYY-MM] [--markdown] The Ship Report for a release or a month: loops, review rounds, findings, harmful findings and whether all were fixed before merge, cost per accepted change, checklist classes learned, gates, deploys and pull requests. --markdown prints a snippet for release notes. Dollar figures follow the same visibility rule as the rest of the loop

Manage portable AI personas per project. Each persona has an ASCII name (^[A-Za-z0-9_-]{1,50}$) and a markdown body. Tier: every plan (from v0.29.10; Pro+ before). Available starting v0.10.1.

Command Description
sfs persona list [--no-org | --org ORG_ID] List personas usable in the current project (project + org, with a Scope column), or one org’s personas
sfs persona show <name> [--raw] [--org ORG_ID] Show a persona’s full content (--raw skips markdown render)
sfs persona create <name> [--content TEXT | --file PATH] [--org ORG_ID] [--represents EMAIL] Create a persona inline, from a file, or via $EDITOR; --org creates an org-level persona, and --represents names the org member who may edit it
sfs persona represent <name> --org ORG_ID (--user EMAIL | --clear) Set or clear the org member an org persona represents (org admins). That member can edit its role, content and specializations
sfs persona edit <name> [--org ORG_ID] Open the persona content in $EDITOR
sfs persona delete <name> [--force] [--org ORG_ID] Delete a persona; refuses 409 if non-terminal tickets reference it (use --force to override)
sfs persona pull [<name> | --all] [--no-org] Write personas to .agents/*.md; --all includes the org’s personas unless --no-org
sfs persona assume <name> Tag subsequent captured sessions with this persona (persona-only bundle)
sfs persona forget Clear the active persona bundle (refuses while a ticket bundle is in effect)

Org-level personas (--org): define a persona once for an organization and use it from every project in that org. Writes need the org admin or owner role; members can read. Inside a project, names resolve to the project’s own persona first, then the org’s — a project persona with the same name overrides the org one. Ticket assignment, sfs ticket start, agent runs, and the MCP tools all follow this rule.


Manage tickets with a server-enforced FSM (suggested → open → in_progress → blocked → review → done | cancelled), dependency graph, comments, and an active-ticket provenance bundle that tags every captured session with persona_name + ticket_id. Tier: every plan (from v0.29.10; Team+ before). Available starting v0.10.1.

Command Description
sfs ticket list [--status STATE] List tickets, optionally filtered by FSM state
sfs ticket show <id> Show ticket detail + dependencies + recent comments, with the creator, due date and estimate
sfs ticket history <id> [--limit N] The ticket’s change history, newest first: each status change, assignment and field edit with its before and after values and who made it (default 50, up to 200; v0.28.0)
sfs ticket create --title T --description D [--accept "..." --depends-on tkt_…] [--assigned-to PERSONA | --user EMAIL] [--due YYYY-MM-DD] [--estimate DURATION] Open a ticket (agent source requires ≥1 acceptance criterion + ≥20-char description). --user/-u assigns it directly to a teammate (email or user id), who gets a “Your turn” notification; it can’t be combined with --assigned-to (v0.27.0). --due sets a due date and --estimate an estimate in Jira duration syntax such as 2d 4h (v0.28.0). --assign-contact ec_… assigns it to an external contact of the project’s org instead (no notification: a contact can’t log in)
sfs ticket update <id> [--title T] [--description D] [--priority P] [--user EMAIL] [--due YYYY-MM-DD|none] [--estimate DURATION|none] Change a ticket’s editable fields; --user/-u reassigns it directly to a teammate (v0.27.0). --due and --estimate set the due date and estimate; none clears them (v0.28.0). --assign-contact ec_…|none assigns or unassigns an external contact
sfs ticket start <id> [--tool T] [--force] [--no-print-context] Atomic claim; writes the active-ticket bundle and prints compiled persona + ticket context with tool-aware token budget
sfs ticket complete <id> Move from in_progress to review; clears owned bundle
sfs ticket comment <id> "body" [--as PERSONA] Slack-like comment (non-idempotent)
sfs ticket status Render the active-ticket bundle (Rich panel)
sfs ticket follow <id> [--mute] / sfs ticket unfollow <id> Follow a ticket to be notified when it changes state, changes hands or gets a comment; --mute follows silently (v0.24.0)
sfs ticket inbox [--all] [--mark-read] Your ticket notifications, unread by default (v0.24.0)
sfs ticket updates [--persona NAME] [--no-ack] Agent-side poll of what changed on followed tickets; each persona keeps its own cursor, --no-ack peeks without advancing it (v0.24.0)
sfs ticket block <id> --reason "..." / sfs ticket unblock <id> Toggle blocked state
sfs ticket reopen <id> Move a terminal ticket back to open
sfs ticket approve <id> / sfs ticket dismiss <id> Decide on suggested tickets
sfs ticket assign <id> --persona NAME Attach a persona to a ticket
sfs ticket resolve <id> Move from review to done (atomic with rowcount guard)
sfs ticket escalate <id> --reason "..." Raise priority + append audit comment
sfs ticket review-state <id> Open and closed review findings, the last verdict, severity counts, and Strict VERIFIED-CLEAN: yes/no for the last verdict
sfs ticket jira preview <id> [--out FILE] Draft a Jira story from the ticket without sending anything (Enterprise, v0.23.0)
sfs ticket jira publish <id> --from FILE [--yes] [--overwrite-existing] Create the Jira issue from a saved preview, or update its summary and description. A ticket linked to an existing issue it never published needs --overwrite-existing to replace that issue’s summary and description (v0.27.0)
sfs ticket jira pull <id> [--yes] Replace the ticket’s title and description with the linked Jira issue’s; empty Jira fields leave the ticket unchanged (v0.27.0)
sfs ticket jira status <id> Linked issue key, URL and current Jira status
sfs ticket jira unlink <id> --confirm Remove the link (project admin); the Jira issue is left alone

The active-ticket bundle is stored locally and read by all 10 daemon watchers (claude_code, codex, copilot, cursor, gemini, amp, cline, roo_code, kilo_code, antigravity). Captured sessions carry the bundle in their manifest.json and the server populates sessions.persona_name + sessions.ticket_id on upload.

Following is also automatic: creating a ticket, being assigned, commenting or posting a review verdict follows it for you. Notifications are written by the server and never copy comment bodies. Choose an email digest (off, your_turn by default, or all) under Settings → Preferences in the dashboard.


An org’s external contacts: people the org works with who are not SessionFS users. Every command takes --org (default: your default org).

Command Description
sfs contact list [--q TEXT] [--status active|archived|all] [--tag TAG] Contacts, newest first
sfs contact show <id> [--refs] One contact, and with --refs where it appears (sources you can read)
sfs contact create NAME [--email E] [--role R] [--tag T] [--alias A] Create a contact (any member)
sfs contact edit <id> [...] / alias add|rm <id> ALIAS / archive <id> [--undo] Edit a contact
sfs contact merge <target> <source> [--yes] / delete <id> / export <id> / export-all Owners and admins
sfs contact suggestions [--apply NAME --contact ID] [--dismiss NAME] Names in your meetings and chats that nobody confirmed yet

Import, inspect, and install portable Agent Skills and Agent Plugins locally. SessionFS preserves standards payloads, pins Git sources, computes deterministic target plans, discloses omissions, and records package provenance on captured sessions. sfs plugin is an alias of sfs skill.

Command Description
sfs skill inspect SOURCE [--pin REF] [--subdir PATH] [--for TOOL] [--json] Validate and inspect a local path, Git source, hosted package, or named local marketplace package without installing, and print its install disclosure (see Skills Marketplace)
sfs skill add SOURCE [--for TOOL] [--scope project|user] Plan and transactionally install across one or more tools
sfs skill list / sfs skill show ID Inspect installed state, provenance, hashes, targets, and omissions
sfs skill plan ID / sfs skill compile ID [--for TOOL] [--drop TOOL] [--yes] [--allow-hidden-unicode] Compute a side-effect-free plan or re-apply the pinned package. --for is additive (installed targets are always kept); only --drop TOOL removes a tool, after listing the managed files to be unlinked and confirming (--yes in non-interactive mode)
sfs skill sync --locked [--approve-widening] [--allow-hidden-unicode] Reproduce exact project lockfile state without upgrading. Every installed version the lockfile replaces is classified like an update before anything changes; one refused transition refuses the whole sync
sfs skill remove ID / sfs skill update ID [--approve-widening] [--allow-hidden-unicode] Remove or update a package while preserving unmanaged (dirty) files; update previews old → new hash, commit, plan, the update diff and its class, then applies the re-consent rules below
sfs skill diff ID [--to VERSION] [--json] Show what an update would change without applying it: files added/removed/changed with bounded text diffs, capability changes, new scanner and hidden-character findings, and the update class (text, code, widening)
sfs skill rollback ID --to HASH [--approve-widening] [--allow-hidden-unicode] Re-apply a cached immutable version; --to is required and must be an exact sha256:<64 hex> (or bare 64-hex) digest. The transition is classified and consented like an update
sfs skill doctor Detect drift, missing files, unsafe paths, and state mismatches; also shows the size of the removal trash
sfs skill marketplace add URL --name NAME --pin SHA Register one pinned local marketplace source
sfs skill marketplace list|refresh|remove Manage multiple user/project registry aliases explicitly
sfs skill search QUERY [--tool TOOL] [--limit N] [--local-only] [--json] Search registered local marketplaces and the hosted SessionFS Marketplace. Each row is labelled local:<scope> or hosted and shows the reference to install it with. Signed out or offline, the hosted part is skipped with a note. --tool filters hosted results by tool compatibility; --marketplace ALIAS and --local-only search local registries only. Hosted filters: --category, --publisher, --verified, --attested, --license, --max-severity, --capability, --works-in, --updated-within, --hide-deprecated, --sort relevance|recent (see Skills Marketplace)
sfs skill categories [--json] List the hosted marketplace’s categories
sfs skill works-in ID [--json] The per-tool “works in” matrix for a hosted package (spk_...) or version (skv_...): verified (with tool version and date), format-valid, regressed or expected (see Skills Marketplace)
sfs skill usage --org ORG_ID [--days N] [--json] Your organization’s members’ hosted-marketplace usage by package and tool (org owners/admins, Team plan)
sfs skill add sessionfs:NAMESPACE/NAME[@VERSION] Install a package from the hosted SessionFS Marketplace (requires sfs auth login). sessionfs:spk_<id> also works and is required when a namespace/name pair is ambiguous. Without @VERSION the package’s current version is used; --pin VERSION is equivalent to @VERSION
sfs skill pull [--for TOOL] [--device-id ID] [--yes] [--allow-* ...] [--approve-widening] [--allow-hidden-unicode] [--json] Apply your org’s skill assignments and your approved install requests to this device (see Skills Marketplace)
sfs skill validate SOURCE [--visibility personal|org|public] [--json] Validate a package directory or .tar.gz exactly as the server would. Prints each problem with its file and line (when known), why it fails, and how to fix it, then exits 1. On success it prints the content hash, risk flags, sizes, and the checks that only the server can make
sfs skill publish SOURCE [--org ORG_ID] [--visibility personal|org|public] [--namespace NS] [--collection NAME] [--yes] [--json] Validate locally, show a summary (name, version, license, risk flags, size, target), confirm, then upload. Prints the listing, package, and version IDs and the package URL
sfs skill publish SOURCE --trusted-publishing --namespace NS [--package NAME] [--visibility public] [--audience AUD] [--ci-provider github|gitlab] [--id-token-env VAR] Publish from a GitHub Actions or GitLab CI job without an API key: reads the server’s OIDC audience, gets the job’s OIDC token (GitLab: from $SFS_ID_TOKEN, declared with id_tokens:), exchanges it for a single-use publish token, and uploads. See Trusted publishing and GitLab CI
sfs skill publisher claim NAMESPACE [--org ORG_ID] [--display-name NAME] [--json] Claim a namespace: 3-39 lowercase letters, digits or single hyphens. Personal publishers need Starter or above; org publishers need an org owner/admin and the team skill library. Names that imitate a reserved brand or a verified publisher are refused with 409 namespace_confusable: lookalike letters from any script (the full Unicode UTS #39 confusables table, so Cyrillic, Greek or Cherokee spellings), leetspeak digits (0 1 2 3 4 5 6 7 8 9), rn/m, one or two typos, and added -official, -team, -ai and similar. A namespace another owner already publishes packages in is refused with 409 namespace_in_use (ask SessionFS to review the claim). An owner can hold 5 publishers and claim 10 namespaces in total (retired ones count). Namespaces are never released, even after deletion
sfs skill publisher list [--json] Publishers you manage, personal and org
sfs skill publisher show PUBLISHER_ID [--json] Publisher details; managers also see verifications and trusted publishers
sfs skill publisher verify PUBLISHER_ID --dns DOMAIN Start DNS verification. Prints a sessionfs-verification=... TXT record to add at the domain. If your organization already verified the domain for SSO, it is reused (and re-checked) immediately
sfs skill publisher verify PUBLISHER_ID --github-org INSTALLATION_ID / --github-user INSTALLATION_ID Verify a GitHub organization or account through one of your own SessionFS GitHub App installations. The installation must be linked to your account through the verified GitHub sign-in flow; an installation linked only by its id is refused with 409 installation_claim_unverified. The badge is bound to GitHub’s numeric account id, so a renamed or re-registered login does not inherit it
sfs skill publisher check PUBLISHER_ID VERIFICATION_ID Re-check a verification now
sfs skill publisher trust PUBLISHER_ID --repo OWNER/REPO --workflow FILE [--environment ENV] [--ref-pattern REF] [--package NAME] [--reusable-workflow OWNER/REPO/.github/workflows/FILE] [--allow-workflow-run] Allow a GitHub Actions workflow to publish for this publisher (see Skills Marketplace)
`sfs skill publisher trust PUBLISHER_ID –gitlab-project ID [–gitlab-host ORIGIN] [–gitlab-project-path GROUP/PROJECT] [–gitlab-namespace ID –no-namespace-pin] [–environment ENV [–require-protected-environment]] [–ref-pattern REF] [–package NAME]`
sfs skill publisher untrust PUBLISHER_ID TRUSTED_ID Remove a trusted publisher. Publish tokens already issued under it stop working
sfs skill publisher stats PUBLISHER_ID [--days 7|30|90] [--json] Publisher analytics: installs by tool, version and day, active installs, uninstall rate, translation failures, works-in regressions, scan findings and open reports. Counts under 10 show as <10
sfs skill publisher package PUBLISHER_ID PACKAGE_ID [--category SLUG ...] [--deprecate|--undeprecate] [--message TEXT] [--successor PACKAGE_ID] [--readme-path PATH] Set a package’s categories (up to 3), deprecation with a same-publisher successor, and README path

Risky capabilities require explicit flags bound to the exact package hash: --allow-scripts for any non-inert skill asset (the policy is an inert allowlist, so .rb, .bat, .exe, Makefile, and suffix-less files all count), --allow-hooks for SKILL.md frontmatter hooks: / allowed-tools: grants, and --allow-executable-extensions for a hooks.json or hooks/ directory shipped inside a skill. --yes alone is refused for these and the error names the hook or tool grant. Local MCP activation remains reserved: SessionFS does not silently enable it.

Every update, rollback and sync --locked transition is classified as text (consent carries forward after one confirmation), code (the changed capability’s flag again) or widening (always stops until --approve-widening or an org admin approves that exact version). sfs skill pull and the daemon apply text updates and list the rest as held: <name> needs approval. Blocked packages are moved into ~/.sessionfs/skills/quarantine/; yanked ones are flagged by sfs skill list and sfs skill doctor. See Skills Marketplace for install disclosure, verified publishers and trusted publishing.

Native plugin catalogs: read-only git repositories of approved packages that each tool’s own plugin command can add. See Skills Marketplace.

Command Description
sfs catalog list [--json] The catalogs you can add (public, personal, organization), with plugin counts and clone URLs
sfs catalog add --for TOOL [--org ORG | --personal] [--run] [--no-credential-helper] Print the tool’s own command to add a catalog (claude-code, copilot, codex, cursor, gemini, antigravity); --run runs it where supported. Configures git to authenticate to the SessionFS host only through sfs catalog credential, so your key never appears in a URL
sfs catalog doctor Check that git sends your SessionFS key only through the SessionFS credential helper (run it inside a repository to check that repository’s config too)
sfs catalog export --to REMOTE [--org ORG | --personal] [--branch main] [--dry-run] [--ssh-key-file PATH] [--known-hosts PATH] Copy a catalog to a git repository you own (for example, for a Cursor team marketplace). The destination branch is overwritten with the generated catalog commit, and nothing is pushed when it is already current. With --ssh-key-file only that deploy key is used, over SSH with strict host-key checking, so it can run unattended

Store meeting transcripts for a project or a project group, extract action items and decisions, and promote action items to tickets. Transcripts are DLP-redacted by the server before storage, and every access rule is enforced server-side. See Meetings. Without --project or --group a command uses the project of the current repository.

Command Description
sfs meeting upload <file> | --stdin --title T [--project proj_… | --group pg_…] [--date ISO] [--duration MIN] [--extract] Upload a .txt, .md, .vtt or .srt transcript (cue timing in VTT/SRT is stripped server-side). --extract also runs extraction right away
sfs meeting list [--project | --group] [-q TEXT] [-n N] [--before ID] Meetings, newest first; a printed cursor pages onwards
sfs meeting search <q> [--project | --group] Search titles and transcript text
sfs meeting show <id> [--no-transcript] The numbered transcript, participants and their resolution, and the action items and decisions with line ranges
sfs meeting delete <id> [--yes] Delete a meeting
sfs meeting extract <id> Extract participants, action items and decisions with your own LLM key (your key, else your org’s; never a SessionFS key)
sfs meeting participants <id> Participants and how each was resolved
sfs meeting resolve-participant <id> <participant_id> --user USER_ID | --persona NAME | --contact ID Resolve a participant manually
sfs meeting resolve-participant <id> --file FILE Resolve up to 100 participants at once; each line is participant_id,user:<id>, participant_id,persona:<name> or participant_id,contact:<id>. All or nothing: if any line is refused, nothing changes and the failed lines are listed
sfs meeting action-items <id> Action items and decisions
sfs meeting promote <id> <item_id> [--title T] [--description D] [--assignee PERSONA | --user USER_ID] [--due DATE] [--priority P] [--target-project ID] [--jira] [--yes] Show the ticket draft and ask before creating it; --yes skips the prompt. A group meeting needs --target-project
sfs meeting link <id> <item_id> [TICKET_ID] [--yes] / unlink <id> <item_id> Tie a pending item to an existing ticket (the item’s suggestion when no ticket is given); shows the ticket and the comment it will add, then asks. unlink puts a linked item back to pending (v0.29.11)
sfs meeting dismiss <id> <item_id> / restore <id> <item_id> Dismiss a pending item, or bring a dismissed one back

Store chat threads (a Slack export, a DiscordChatExporter export, or a plain paste from any tool, including Teams) for a project or a project group. A thread is stored one message per line, so extracted items cite message ranges such as M12-15. The server refuses direct-message exports, redacts the text with your DLP policy before storage and enforces every access rule. The commands after upload are the sfs meeting commands run against chat threads.

Command Description
sfs chat upload <file> --channel "#infra" [--project proj_… | --group pg_…] [--provider slack|discord|paste|teams_paste] [--users users.json] [--attest] [--title T] [--extract] Upload a thread (2 MiB max, refused before anything is sent). Without --provider the format is detected: Slack JSON, DiscordChatExporter JSON, otherwise a paste. A paste needs --attest to confirm it is from a channel, not a direct message. --users (Slack only) sends the export’s users.json so ids show as names
sfs chat list [--project | --group] [-q TEXT] [-n N] [--before ID] Chat threads, newest first
sfs chat search <q> [--project | --group] Search titles and message text
sfs chat show <id> [--no-messages] Numbered messages (M1, M2, …), participants, action items and decisions
sfs chat delete <id> [--yes] Delete a chat thread
sfs chat extract <id> Extract participants, action items and decisions with your own LLM key
sfs chat participants <id> / resolve-participant <id> <participant_id> --user USER_ID | --persona NAME Participants, and resolving one manually (--file FILE resolves many, as for meetings)
sfs chat action-items <id> Action items and decisions
sfs chat promote <id> <item_id> [same options as sfs meeting promote] Show the ticket draft and ask before creating it
sfs chat link <id> <item_id> [TICKET_ID] [--yes] / unlink <id> <item_id> Tie an item to an existing ticket (the item’s suggestion when no ticket is given; asks first), or put a linked item back to pending (v0.29.11)
sfs chat dismiss <id> <item_id> / restore <id> <item_id> Dismiss or restore a pending item

What needs you right now: your For You list across reminders, approvals, the tickets assigned to you or to a persona you represent, Review Loop items, meeting and chat action items you own, knowledge changes in projects you work in and the weekly proof card. The server applies each source’s own access rules on every call. Every plan; each section appears only when its source is in your plan.

Command Description
sfs attention [--band now|your_turn|upcoming|lately] [--limit N] [--json] Print the feed grouped by band (Now, Your turn, Coming up, Lately), each item with why it is there and its dashboard link. Counts are the full totals; --limit (1–100, default 100) caps the items. A source that couldn’t load is named at the end. --json prints the raw response

Personal reminders, optionally tied to a meeting, a chat thread or a ticket. A reminder is private to the person reminded and the person who set it. When it falls due it shows in the notification bell and Inbox, and in the email digest if your notification settings allow it. Titles and notes are DLP-redacted by the server before storage. Reminders are on every plan.

Command Description
sfs remind add "title" --at "2026-11-06 09:00" [--tz Europe/London] [--meeting MEETING_ID[:LINES] | --chat CHAT_ID[:M<a>-<b>] | --ticket TK] [--for EMAIL] Create a reminder. --chat ties it to a chat thread and, optionally, a message range (chat_…:M3-5). --at takes YYYY-MM-DD HH:MM (or a bare date, meaning 09:00), read in --tz or this machine’s timezone; a value with an offset (…Z, …+01:00) is used as given. It must fall between 1 hour ago and 2 years ahead. --for reminds a teammate who can read the meeting or ticket
sfs remind list [--all | --done] [--due-before TIME] [--limit N] Your reminders, earliest due first (open by default); due ones are marked
sfs remind show <id> A reminder with its source and notes
sfs remind note <id> "text" Add a note (notes are append-only)
sfs remind snooze <id> 1h|tomorrow|next-week / --until TIME [--tz ZONE] Push it later. tomorrow and next-week mean 09:00 in the reminder’s timezone (next week = Monday)
sfs remind done <id> / dismiss <id> Close it as done, or dismiss it

Approval policies hold merges and knowledge-base promotion until the right people approve. Only people decide; implementers and authors (including through a service key they minted) can’t approve their own work. Creating and editing policies needs the Enterprise plan; reading, disabling and deciding keep working after a downgrade.

Command Description
sfs approval policy list [--org ORG] [--all] The org’s active policies (--all: every version, admins)
sfs approval policy create --name N --target merge|kb_promote --require role:admin:1 [--require users:ID[,ID]:COUNT ...] [--filter JSON | --filter-file PATH] [--advisory] [--description D] [--org ORG] Create a policy (owners and admins)
sfs approval policy update <policy_id> [--name] [--description] [--require ...] [--filter ...] [--blocking | --advisory] [--org ORG] Edit a policy. This creates a new version; open requests stay on the old one
sfs approval policy disable <policy_id> [--org ORG] Deactivate a policy
sfs approval list Pending requests you could decide now
sfs approval show <request_id> A request with its policy, target, state and decisions
sfs approval approve <request_id> --reason "…" / reject <request_id> --reason "…" Decide. One reject rejects the whole request

Ask the session helper a question over the sessions and project knowledge you can read (v0.23.0). Answers cite the sessions and messages they used. The model call uses your own key (Settings → Data protection → Security review model) or your org’s helper key. See Session Helper.

Command Description
sfs helper ask "QUESTION" [--project ID | --group ID_OR_SLUG | --session ID ...] [--conversation ID] [--no-stream] [--json] Ask a question. Streams the answer to the terminal and lists citations at the end. --project, --group (a project group id pg_… or its slug; v0.28.0) or --session scope the question, one at a time; --conversation continues a thread; --no-stream fetches the whole answer in one request; --json prints the raw JSON
sfs helper conversations list Your helper threads, newest first
sfs helper conversations show <id> One thread with its messages and citations
sfs helper conversations rename <id> "TITLE" Rename a thread (up to 200 characters, DLP-redacted like your questions)
sfs helper conversations delete <id> [--yes] Permanently delete a thread
sfs helper status Whether the helper is available to you, and which key, provider and model it would use

Organization membership. See Organizations.

Command Description
sfs org list Every organization you belong to; * marks your default org
sfs org info / sfs org members Your default organization, its seats and members
sfs org invite EMAIL [--role member|admin] Invite someone (admin only). When the server sends no email (no email provider configured), the command prints the link to share
sfs org invite --file FILE [--org ORG_ID] Invite up to 100 people at once; one email per line, optionally email,role. All or nothing: if any line is refused, nobody is invited and the failed lines are listed
sfs org invites Pending invites addressed to your email
sfs org accept INVITE_ID Accept one of them. You can accept while you belong to other orgs; accepting never changes your default org
sfs org set-role USER admin|member / sfs org remove USER Change a member’s role, or remove a member (admin only)

Manage the org’s inbound GitHub and GitLab webhooks for pull requests, releases and deployments (org owners and admins, v0.29.3). Every org has them; they are not feature-gated. See Delivery webhooks.

Command Description
sfs org delivery-webhook rotate --provider github|gitlab Generate or rotate the provider’s secret. The secret and the inbound URL are printed once; the secret is stored encrypted and only its last four characters are shown again
sfs org delivery-webhook status --provider github|gitlab Whether a secret exists, its last four characters and the inbound URL

Connect the org’s Jira Cloud site (org admins, v0.23.0). The API token is encrypted at rest and never printed back. See Jira Cloud.

Command Description
sfs org jira connect --site-url https://NAME.atlassian.net --email EMAIL --template agile|compliance|sre|bug [--api-token TOKEN] Check the credentials against Jira and save the connection; the token is prompted for (hidden) when omitted
sfs org jira mappings Project to Jira project mappings (key, issue type, template override, done status)
sfs org jira health Unmapped projects, failed updates, and links not checked in 7+ days
sfs org jira templates list Built-in and org-custom story templates (v0.26.0)
sfs org jira templates show SLUG [--versions] One template and its sections; --versions lists a custom template’s version history (v0.26.0)

Connect the org’s Confluence Cloud site and map projects to spaces (org admins, v0.26.0). See Confluence Cloud.

Command Description
sfs org confluence status The connection, project mappings and publishing health
sfs org confluence connect --site-url https://NAME.atlassian.net --email EMAIL --template reference|architecture|runbook|onboarding|concept [--api-token TOKEN] [--batch-window MIN] Save the connection; the token is prompted for (hidden) when omitted
sfs org confluence map PROJECT_ID --space-key KEY --parent-page-id ID [--template T] [--publish-context] [--auto-publish-pages] Map a project to a space and parent page; --auto-publish-pages opts it into the scheduled publish sweep
sfs org confluence unmap PROJECT_ID Remove a project’s mapping

The org skills policy and what it becomes in each tool’s managed settings. See Skills Marketplace for how the policy is enforced and delivered.

Command Description
sfs policy show [--org ORG] [--tool T] [--json] The policies that apply to you, with what each tool enforces, what only SessionFS checks, and what nothing checks
sfs policy compile --tool T [--org ORG] [--json] Print a tool’s compiled managed settings for IT to deploy (Claude Code, GitHub Copilot, VS Code, Gemini CLI, Codex; a checklist for Cursor)
sfs policy status [--json] Per tool on this device: system when the deployed managed settings match the current revision, otherwise advisory
sfs policy set --org ORG --file policy.json [--acknowledge-warnings] Owners and admins: preview the per-tool changes and side effects, then publish a new revision
sfs policy disable --org ORG [--yes] Owners and admins, any tier: publish a revision that restricts nothing (after leaving Enterprise the last policy stays enforced and can only be relaxed or disabled)