Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6cd9998
feat(env): isolate auth token from the agent process env (security)
2witstudios Jun 22, 2026
32559bc
test: add live E2E proof of token isolation through the bash-tool env…
2witstudios Jun 22, 2026
90b4389
feat(creds): add global credential store + pagespace login command
2witstudios Jun 22, 2026
526900a
feat(onboarding): first-run flow instead of missing-config exit
2witstudios Jun 22, 2026
cc2fe54
feat(onboarding): drive the full first-run flow — drives, models, mat…
2witstudios Jun 22, 2026
7bc68eb
feat(doctor): upgrade pagespace status into reusable doctor + remedia…
2witstudios Jun 22, 2026
b5b6315
feat(doctor): wire onboarding to the shared doctor (cross-surface reuse)
2witstudios Jun 22, 2026
7e65635
fix(bin): launcher imports shared src/doctor.ts (no mirroring)
2witstudios Jun 22, 2026
bf85d81
fix(bin): call main() after declarations (TDZ on PAGESPACE_AGENT_DIR)
2witstudios Jun 22, 2026
c24b65e
docs(readme): rewrite install + first-run docs for Cursor-grade onboa…
2witstudios Jun 22, 2026
15d4459
docs(readme): explicitly demote .mcp.json to optional override
2witstudios Jun 22, 2026
c2f6bf0
feat(config): multi-drive config — PAGESPACE_DRIVES drive set + singl…
2witstudios Jun 22, 2026
3df38e5
fix(bin): wire launcher to shared pure modules — eliminate all mirroring
2witstudios Jun 22, 2026
06b0827
fix(onboarding): address review findings — coherent machine driving
2witstudios Jun 22, 2026
71e913e
fix(onboarding): delete the dead validate-recovery branch (Finding 1)
2witstudios Jun 22, 2026
112489b
fix(security): resolve auth token from credential store — isolation w…
2witstudios Jun 22, 2026
bfb4724
fix(security): block .env secret injection into pi env + drop false h…
2witstudios Jun 22, 2026
1d3fcc5
fix(bin): resolve effective token in statusDoctor + fix main() indent…
2witstudios Jun 22, 2026
015512e
fix(review): valid inline-comment findings — whitespace, type guards,…
2witstudios Jun 22, 2026
be94446
fix(doctor): token check must not false-green when credential file ex…
2witstudios Jun 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 52 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,41 +38,48 @@
```bash
git clone https://github.com/2witstudios/pagespace-cli.git
cd pagespace-cli
npm install
npm install # resolves vendored pi workspaces in packages/
npm run build # required: builds workspace pi packages to dist/ (~3s)
```

`npm install` resolves the vendored pi workspaces in this monorepo (`packages/pi-agent-core`, `packages/pi-ai`, `packages/pi-coding-agent`, `packages/pi-tui`). You do **not** need a global `@earendil-works/pi-coding-agent` install.

Create local config (recommended):

```bash
cp .env.example .env.local
# then edit .env.local and set at least PAGESPACE_AUTH_TOKEN
```
This repo vendors pi via npm workspaces (`packages/`), so you do **not** need a global pi install.

Launch either way:

```bash
npm link
npm link # optional: puts `pagespace` on your PATH
pagespace

# or without linking
node bin/pagespace.mjs
```

Run the doctor:
### First run (Cursor-grade onboarding)

```bash
pagespace status
```
If no token is configured, `pagespace` now runs an interactive onboarding flow instead of exiting:

- prompts you to paste a token
- validates auth (`GET /api/drives`)
- discovers accessible drives (preferred drive first)
- discovers available AI_CHAT agent models across drives
- defaults drive/model to the first discovered option
- writes credentials + selection, then launches

Materialized config on successful onboarding:

- `~/.pagespace/credentials` (token, mode `0600`)
- chosen default drive/model

Happy path is now: **install → run → onboard → code**.

## Commands

```bash
pagespace # start the harness
pagespace status # env + connectivity doctor
pagespace sessions # list conversations for PAGESPACE_MODEL_PAGE
pagespace resume <id> # resume by exact id or unique prefix
pagespace # start (runs onboarding on first run if no token)
pagespace status # config + auth doctor (credential store + structured ✓/✗)
pagespace login # capture/refresh token into ~/.pagespace/credentials (0600)
pagespace sessions # list synced conversations
pagespace resume <id> # resume a conversation
```

In-session model switching:
Expand All @@ -82,56 +89,52 @@ In-session model switching:

## Configuration

### Environment variables
Token/config can come from several sources. Default UX is the credential store; override paths still work for those who need them.

1. **Credential store (recommended):** `~/.pagespace/credentials` (mode `0600`). Written by first-run onboarding or `pagespace login`. Global across projects.
2. **Project env files (optional override):** `.env.local` then `.env`, auto-loaded by the launcher.
3. **`.mcp.json` (optional override, MCP workflows):** holds the token for MCP-server workflows (see `.mcp.json.example`). Not required for the harness itself — `pagespace` reads from the credential store / env, not `.mcp.json`.
4. **Shell env (highest precedence):** exported env vars always win at runtime.

By default, launcher/extension load `.env.local` then `.env` (shell env still wins). Configure with:
Effective precedence is: **shell env > `.env.local`/`.env` > credential store**. (`.mcp.json` is consumed by MCP clients, not the launcher's token resolution.)

### Environment variables

| Variable | Required | Purpose |
|---|---|---|
| `PAGESPACE_AUTH_TOKEN` | **Yes** | Scoped PageSpace token for API access. |
| `PAGESPACE_AUTH_TOKEN` | No | Scoped token. **Now optional** (recommended to set via `pagespace login` / onboarding). |
| `PAGESPACE_API_URL` | No | PageSpace base URL. Default: `https://pagespace.ai`. |
| `PAGESPACE_DRIVE` | No | Default drive slug used for mount + memory grounding order. |
| `PAGESPACE_DRIVE` | No | Default drive slug for bare mount paths. |
| `PAGESPACE_MOUNT` | No | Mount prefix in your cwd. Default: `pagespace`. |
| `PAGESPACE_MODEL_PAGE` | No | Optional primary brain agent page id (pin first model). |
| `PAGESPACE_MODEL_PAGES` | No | Optional comma-separated additional agent page ids. |
| `PAGESPACE_MODEL_PAGE` | No | Optional primary model page pin. |
| `PAGESPACE_MODEL_PAGES` | No | Optional comma-separated model page pins. |
| `PAGESPACE_READONLY` | No | Optional comma-separated mounted prefixes to protect from write/edit (e.g. `Specs,Epics`). |

### Auto-discovery first, pinning optional
### Models: auto-discovery by default

If `PAGESPACE_MODEL_PAGES` is not set, the extension auto-discovers model agents across all accessible drives and registers them under provider `pagespace`.
If model pins are not set, `pagespace` auto-discovers AI_CHAT agent models across all drives accessible to your token (preferred drive first).

Use `PAGESPACE_MODEL_PAGE` / `PAGESPACE_MODEL_PAGES` only when you want to pin or extend the model list explicitly.
Use `PAGESPACE_MODEL_PAGE` / `PAGESPACE_MODEL_PAGES` only when you want explicit pinning.

### `.env.local` vs `.mcp.json`
### Security note

These are separate configuration paths:

- **`.env.local` / `.env`**: consumed directly by `pagespace` launcher + extension runtime.
- **`.mcp.json`** (gitignored): MCP server config format (see `.mcp.json.example`) that can also hold the same token for MCP workflows.

`pagespace status` will suggest `.mcp.json.example` when required env is missing, but runtime behavior is still based on process env.
The launcher strips auth token env before spawning pi. That means the agent's `bash` tool cannot read your token via `env`, `printenv`, or `/proc/self/environ`. Provider auth reads from config/credential storage, not child process env.

## How it works

### 1) Dual-mount files

`extensions/pagespace.ts` replaces file tools with path-aware routers:

- under mounted PageSpace path: operate on PageSpace pages via API
- outside mount: use local filesystem tools
- `grep` on mounted paths uses server-side regex search
- `bash` remains local-only
### 1) Dual-mount filesystem

### 2) PageSpace as model brain
- Paths under `pagespace/<drive>/...` route to PageSpace pages.
- Everything outside that mount stays on your local filesystem.
- `bash` always runs locally.

`src/provider.ts` registers provider `pagespace` and calls:
### 2) PageSpace brain

- `POST /api/v1/chat/completions`
- `model: ps-agent://<pageId>`
- includes pi-native `tools`
- `disable_server_tools: true`
- Uses native function-calling via `POST /api/v1/chat/completions`.
- Targets `model: ps-agent://<pageId>`.
- Sends pi tools with `disable_server_tools: true`, keeping the tool loop in pi.

The model streams native `tool_calls`; pi executes those tools locally and returns tool results in the next turn. No text tool shim.
This keeps the two axes explicit: **PageSpace-backed mounted memory/files + local code execution**.

## Architecture (condensed)

Expand Down
Loading
Loading