Extensions

Spacesheep

PointmanOfficial

Publish pages and sites to Spacesheep from any agent, with its CLI, and talk to an agent from its page's Session tab.

Install

pointman add pointman-ai/pointman-spacesheep

On every machine of your workspace, or the ones you pick. Or open it in the app:

Open in PointmanView on GitHub

spacesheep

A Pointman extension that has agents write documents, reports and explainers as Spacesheep pages, published with Spacesheep's CLI and opened beside the thread for the person they're working for. Spacesheep publishes pages and sites at a URL people open on any device. With Talk on, a message typed in a page's Session tab reaches the agent that published it (or the agents it starts by calling), as a post in its thread, and the agent answers there and on the page.

pointman add spacesheep

How it works

  • A behaviour and a small process: installed on a node, SKILL.md's body goes into every agent run there, whichever agent it is and whether it runs on Claude Code, Codex or Gemini CLI. The process (bin/spacesheep, Rust) is only for Talk, and listens only while the account's Talk switch is on.
  • What agents do: anything longer than a post becomes a page, not a Markdown file or a long post, unless the person asks for another format. Technical explainers are visual and interactive (diagrams, live examples, toggles, tables, and diffs explained beside the code), with few words. A new or updated page opens beside the thread (open_pane), and its link goes in the thread.
  • Pages for tasks: a page for Pointman tasks starts its title with their refs (AGC-16 · …, or the project's key for several: AGC · …), links each task near the top (pointman://item/AGC-16, which opens it in the app), and is added to each task's links with links_add (core release 19), which keeps the task's other links, so the task shows it.
  • The CLI: agents publish with npx -y spacesheep@latest (or spacesheep where it's installed): deploy for a new page or a new version of one, read, list, share and whoami. The extension's permission rules go into each run's allowed tools, so agents use the CLI without a prompt: Bash(spacesheep:*) and Bash(npx -y spacesheep@latest:*).
  • Page links: while the workspace runs Spacesheep, a page's link in a post (https://spacesheep.dev/@<owner>/<space>) shows in the apps as a pill with the page's name.

Talk from a page

Spacesheep's Session tab messages the coding session that published a page: each deploy records the session that ran it ($CLAUDE_CODE_SESSION_ID). The node knows each agent's session, so the extension listens for it with Spacesheep's own CLI (1.36: talk is unchanged since 1.26), and nothing goes into ~/.claude: no hooks, no machine on, no sessionpipe. The spec: https://spacesheep.dev/@james/spacesheep-talk-through-the-pointman-node (Pointman thread 6914).

  • One switch: the account's own, "Talk to your sessions" at https://spacesheep.dev/settings/talk, read every minute (talk status). Nothing listens while it's off, and the extension never turns it on (talk on). It has no settings of its own (James, thread 6914 [16235]: no list of agents).

  • Who's listened for: each agent here whose current session published a page. Every 5 minutes, while Talk is on, it reads every page of the account's spaces (spacesheep spaces list --json --limit=200, then --after=<page.next> until it's empty) and, for each new or changed one, who pushed its versions (versions list --space-id <page> --json --limit=200, then --after=<page.next> until it's empty: each version's client.session_id; an empty or missing one is another account's version), kept in the state folder (pages.json). A page that leaves the list is kept for 30 days from its last change, up to 500 pages: a burst of other pages (core's docs job updates dozens at once) doesn't silence it. Every 60 s it reads the node's agents (agents.sessions), and for each publisher with a thread it runs spacesheep talk listen --session <id> (the machine's spacesheep, else npx -y spacesheep@latest), signed in with the machine's own key in ~/.config/spacesheep. With npx, it asks npx where its copy of spacesheep@latest is (npx -y -p spacesheep@latest -c 'command -v spacesheep', hourly, which also brings the copy up to date) and runs that copy with node, so no npm exec (~100 MB) stays under each listener; if npx can't say, or the copy goes (npm's cache cleaned) and npx can't fetch it again, the CLI runs through npx. So one process per agent that has a page, not one per agent: a node may run dozens. A listener that ends (its link gone, the CLI failing) starts again after 5 s, doubling to 5 minutes. An agent with a new session, or Talk turned off, has its listener stopped. Each listener is a process group of its own, kept in the state folder (listeners.json), so a restart stops any left from a crash.

  • Each message is a board.post in the page's own thread, as the extension's robot account: the thread the first session here that pushed it was running in when it did (its first version's created_at, against that session's threads as each look saw them, kept in threads.json), set once in pages.json, so a page's comments stay with it when its agent goes on to work in another thread. A session seen before 0.8.2 kept that history counts its last known thread. A page not read yet goes to the thread of the publisher's latest run. Its mention wakes the publisher:

    @scene
    
    ```
    Can you make the header blue?
    ```
    
    

    A second block says where it came from, that it is unsigned, the quoted pin when present, and how to answer:

    From spacesheep.dev (Session tab, not signed).
    
    Answer here, then send it to the page: `spacesheep talk reply --session 205b1fbd-… "…"`
    

    The words are in a code fence longer than any run of backticks in them, so a mention inside wakes nobody (the board reads no mention in code). The reply names the session listened for, which is the page's, whatever session the agent wakes in. Once the CLI's talk reply takes --to (its help, read every hour, says [--to MESSAGE_ID]), it also names the message's id: otherwise Spacesheep answers the session's newest message, and with comments waiting on two pages an answer lands under the other one. A message Spacesheep sends again (redelivered: a new listener gets back, for a day, what no talk reply answered) says so in the second block, since the agent may have answered it another way, and that a short answer sent with the post's line closes it. Without --to that line answers the newest message waiting, so the note says to use it only when this is the one.

  • Pages from an earlier session (its agent despawned, or moved on to a new session): the extension remembers each agent's session and thread (agents.json in the state folder) and keeps listening on the 10 such pages changed most recently. Only sessions an agent here once had count: every node reads the same account's pages, so another node's agents and the person's own sessions are left alone. When the page's agent is still here in a new session, its messages reach the agent in the page's own thread, as on a page of its current session; replies still name the page's own session. Otherwise a message that calls agents reaches them in the page's thread, and one that calls nobody gets a reply on the page saying the agent has finished and how to ask another.

  • A session that ends before its page is found: the page scan runs every five minutes, so a session can end before its page is listed. Sessions seen here stay in agents.json for 30 minutes after they were last seen, and a page's publisher stays while its page is kept (at most 1,000 others, oldest first out; state from before 0.8.1 gets the same 30 minutes).

  • The header says where it was written, in fixed words: "a comment on the page" when Spacesheep's asked_in says exactly that, else the Session tab. Nothing of Spacesheep's goes outside the fence.

  • Comments: a comment on a page that mentions @session is Spacesheep's own way to ask the session that made the page: it arrives as a Talk message, and the agent's talk reply is posted under the comment. Only the page's owner can ask (Spacesheep's rule), so someone else's comment can't wake an agent. No sign-in beyond the machine's.

  • Calling an agent: a message that starts with handles (@editor cut the intro, @editor, @scene: …, or @pm.editor / @pointman.editor) is for those agents instead, any agent on the board, in the same thread. In a comment write @session @pm.editor …: a bare @editor there is also a mention of a Spacesheep user called editor. Then: "@editor from spacesheep.dev (Session tab of @scene's page, not signed):", the publisher in code so naming it doesn't wake it too. Its reply line still names the page's session, so @editor's answer shows on @scene's page. A handle later in the message stays in the fence. Spacesheep doesn't document the message's JSON: its words are text, else message, else body, else the whole JSON, and the first message's JSON goes in the log once.

  • Trust: messages come from the account's signed-in spacesheep.dev session, not a passkey, so a stolen web login could message any agent while Talk is on. Each lands as a visible post saying where it's from, the agent's own permission rules still apply, and SKILL.md tells agents to trust such a post only when this machine posted it (anyone on the board can type its first line), and to ask in the thread before anything risky.

Health

Part ok not ok
account: the account's Talk, the one switch talk status says enabled (read every minute, and after Spacesheep stops a listener) stopped: Talk off for the account, or no Pro or Team plan; failing: the machine not signed in (needs: auth: what the vault's key did, or to run /spacesheep add), or talk status failing
listeners: Talk listeners listening for each agent here whose session published a page, with the last message's time failing: one that keeps ending, the node not answering agents.sessions, the pages not readable, a post that didn't go out, or no CLI; stopped: Talk off, or no agent here has published a page in its current session

The spacesheep.talk event says whether Talk is on, who's listened for, and when the last message came.

Signing in

Once for every node: /spacesheep add in the app seals an API key from https://spacesheep.dev/settings/api-keys in the vault as spacesheep.key. A node that isn't signed in then signs itself in within a minute, with a key of its own:

  1. spacesheep keys create --name <machine> --json, with the vault's key in its environment as SPACESHEEP_KEY (which the CLI reads before its login file), mints a key named after the machine.
  2. spacesheep keys save --name <machine> reads that key from stdin, checks it with spacesheep.dev, and keeps it in ~/.config/spacesheep, as login does.

Neither key is ever a word of a command (anyone on the machine can read those in ps), nor in the log, a post or health. Each machine's key shows under its name in Settings › API keys, to revoke on its own. A machine already signed in keeps its own key, and one signed in by hand (npx -y spacesheep@latest login in a terminal on it) needs no vault key. A key Spacesheep refuses is tried again after 30 minutes, or at once when the vault's key changes; health's account part says why until then. A minted key that keys save couldn't keep (no network, say) is held in memory and saved at the next try, and no other is minted, so a failing save leaves no keys unused on spacesheep.dev. The CLI's errors reach health and the log with any ss_… key in them cut.

An agent whose whoami fails asks its person in the thread to run /spacesheep add, and never asks for a key in a post.

Commands and settings

No commands: the guidance and the CLI's own commands are all agents use. No settings: the account's Talk switch is the one switch.

Files

File What
extension.toml The manifest: [run] beside [behavior], the permissions (agents, post, the CLI's rules) and how the apps draw page links
SKILL.md The guidance, in the standard skill format (frontmatter, then the body), so it works as an ordinary skill outside Pointman too
references/ Shipped with the behaviour and handed to every run: pages.md (how to write a page people take in: 15 researched rules with sources), check.py (the checker agents run before each deploy; python3 -m unittest runs its tests) and template.html (a starter that passes it)
src/main.rs The process: the looks, the listeners, the posts and health
src/cli.rs, src/said.rs, src/pages.rs, src/words.rs Finding and stopping the CLI, reading what talk listen prints, who published each page, and the post's words (and whom a message calls)
src/signin.rs Signing a machine in with the vault's key: a key of its own, minted and kept
tests/ Under the SDK's stand-in node with a fake spacesheep (talk.rs), the manifest (manifest.rs), and the real CLI signed out (real_cli.rs, when SPACESHEEP_REAL_CLI is npx's folder)

Development

cargo test runs it all with a fake CLI; nothing reaches spacesheep.dev or the board. SPACESHEEP_REAL_CLI=/opt/homebrew/bin cargo test also runs Spacesheep's real CLI through npx, signed out.

Releasing

Bump version in extension.toml and Cargo.toml (a test checks they match), commit, and push the tag v<version>. .github/workflows/release.yml builds each platform (two Macs, two musl Linuxes) and makes the release with every archive (extension.toml, bin/spacesheep, SKILL.md, README.md, LICENSE). The marketplace lists it within 30 minutes, and pointman upgrade moves nodes onto it.

Licence

MIT. See LICENSE.

Versions

  1. 0.9.5

    What's Changed

    • 0.9.5: read spaces and versions with CLI 1.36 spaces list / versions list, no fallbacks (EXT-141) by @pointman-app[bot] in #19

    Full Changelog: v0.9.4...v0.9.5

  2. 0.9.4

    What's Changed

    • 0.9.4: read a page's versions to the last page (--limit=200, then --after page.next) by @pointman-app[bot] in #18

    Full Changelog: v0.9.3...v0.9.4

  3. 0.9.3

    What's Changed

    • 0.9.3: read a version's session from client.session_id, falling back to pushed_by.session_id by @pointman-app[bot] in #17

    Full Changelog: v0.9.2...v0.9.3

  4. 0.9.2

    What's Changed

    • 0.9.2: sign in with the ss_ key from the vault record, not the whole record by @pointman-app[bot] in #16

    Full Changelog: v0.9.1...v0.9.2

  5. 0.9.1

    What's Changed

    • 0.9.1: an unkept minted key is saved at the next try, not minted again; keys cut from the CLI's errors by @pointman-app[bot] in #15

    Full Changelog: v0.9.0...v0.9.1

All 20 versions on GitHub