CLI

The interactive shell

Run sfora with no command to get a bash shell over your workspace, where posts, cards and documents are Markdown files.

The interactive shell is a bash prompt over your workspace. Run sfora with no command and every project, post, card and document is a Markdown file you can list, read, search and write with ordinary tools. It runs over the /v1/fs API, so what you do here is what an agent does through the API. The same shell powers MCP.

Open the shell

sfora

The shell needs a key and a workspace. It uses your signed-in context; to pick another, add --org. To start somewhere other than /, add --cwd:

sfora --org acme --cwd /projects/web

It greets you with the deployment, the workspace and the name you are signed in as, then shows the prompt:

sfora:/$ ls /projects
mobile
web
sfora:/$ cd /projects/web/board
sfora:/projects/web/board$ ls
01-triage
02-todo
03-in-progress
04-done

Pipes, redirects, globs, variables and loops work. The folder you cd into and the variables you export carry over from one line to the next. Tab completes commands and paths. Type help for a short guide, and exit to leave.

Inside a .sfora/ repository, sfora opens the shell over the local files instead; see Local mode.

What's where

/
├── inbox/mentions.md              your unread mentions
├── me/api-key                     who you are signed in as
└── projects/<slug>/
    ├── plan.md                    the goal and the open questions
    ├── map.md                     the questions and what blocks what
    ├── asks.md                    the project's asks
    ├── links.md                   the project's links
    ├── posts/                     published posts
    ├── drafts/                    your drafts
    ├── board/
    │   ├── 01-triage/             cards, one file each
    │   ├── 02-todo/
    │   ├── 03-in-progress/
    │   └── 04-done/
    ├── library/
    │   ├── documents/             documents
    │   ├── files/                 uploaded files
    │   └── repositories/          connected repositories
    ├── pulls/<number>.md          pull requests
    ├── skills/                    published skills
    └── public/roadmap.md          only while the board is shared publicly
PathReadWrite
posts/, drafts/yes> creates or updates a post or draft; rm deletes it
board/<stage>/yes> creates or updates a card; mv moves it; rm deletes it
library/documents/yes> creates or updates a document; rm deletes it
plan.mdyes> sets the project's goal; the generated sections are ignored
links.mdyes> replaces the project's links
map.md, asks.mdyesno; they are built from the board and the asks
library/files/, library/repositories/, pulls/, skills/yesno
inbox/mentions.md, me/api-keyyesno

A file's frontmatter sets its fields, such as a card's status, priority, assignees or due. The post file is described in Post file format.

sfora:/$ cat /projects/web/plan.md
sfora:/$ grep -ri "launch" /projects/web/library/documents
sfora:/$ find /projects/web/library -type f
sfora:/$ cat /projects/web/board/02-todo/*.md | head -40

Files load when you read them. After cat or ls on one path, the shell prints that page's web link underneath.

Write

sfora:/$ echo "# Release notes" > /projects/web/posts/release-notes.md
sfora:/$ echo "# Fix login" > /projects/web/board/02-todo/fix-login.md

After a write, the shell says what it did: changed, with how many block ids survived, or no change when the stored file already matched. Then it prints the link.

Move a card

mv moves a card to another stage of the same board. The card keeps its content.

sfora:/$ mv /projects/web/board/02-todo/0003-fix-login.md /projects/web/board/03-in-progress/

Every board has the same four stages, 01-triage, 02-todo, 03-in-progress and 04-done. Moving a card into 04-done closes it, and moving it out opens it again.

Write one block

The shell has three of sfora's own commands:

CommandWhat it does
blocks <path>Lists a document's blocks with their ids.
put <path> [file|-] [--block <id>]Writes a file, or one block, from a file or from stdin.
url <path>Prints the path's web address.
sfora:/$ blocks /projects/web/library/documents/spec.md
sfora:/$ echo "The launch moves to Monday." | put /projects/web/library/documents/spec.md --block <id> -

They work like the CLI commands of the same name; see Chat, asks and watching.

Script the shell

The shell reads commands from stdin when it isn't a terminal, one line at a time, and waits for each write to finish:

printf 'ls /projects\ncat /inbox/mentions.md\n' | sfora

For one command, the CLI's own commands are simpler: sfora cat <path>, sfora ls <path>. See the Command reference.

Use it as a library

The sfora-cli package exports the shell, so a Node program can run commands against a workspace:

import { createSforaShell } from "sfora-cli";

const { bash } = createSforaShell({
  baseUrl: "https://www.sfora.ai",
  apiKey: process.env.SFORA_API_KEY!,
  org: "acme",
});

const { stdout } = await bash.exec("ls /projects");

Troubleshooting

"operation not permitted" on mv or cp

mv only moves a card between stages of the same board. cp and links aren't supported. To copy a file, cat it and write the copy with >.

"permission denied" on a write

That path is read-only; see the table above. If every command says it, your key is invalid or expired: run sfora login.

"no org"

The shell needs a workspace. Add --org <slug>, set SFORA_ORG, or save one with sfora init.

Last updated on