Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ and note your edits; no separate permission is needed.

## Run the Editor Locally

Node.js 22.13 or newer can create a persistent local Pascal installation without
Node.js 22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+ can create a persistent local Pascal installation without
cloning this repository:

```bash
Expand Down
2 changes: 1 addition & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ only for shared projects; the files a shared scene references are served to it a

## CLI-managed editor

Node.js 22.13 or newer can install a persistent local runtime, start it in the
Node.js 22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+ can install a persistent local runtime, start it in the
background, and open it in the browser without a repository checkout:

```bash
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ separately from the runtime, so updating the CLI does not replace your work.

## Requirements

- Node.js 22.13 or newer
- Node.js 22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+
- npm, including when the CLI itself is launched with pnpm or Bun
- A browser, unless you pass `--no-open`
- Network access the first time you start the editor, or a local copy of the web runtime
Expand Down
26 changes: 25 additions & 1 deletion packages/cli/src/diagnostics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,34 @@ import { expect, test } from 'bun:test'
import { mkdir, mkdtemp, rm, stat, writeFile } from 'node:fs/promises'
import os from 'node:os'
import path from 'node:path'
import { collectInfo, runDoctor } from './diagnostics.js'
import { collectInfo, isSupportedNodeVersion, runDoctor } from './diagnostics.js'
import { resolvePascalPaths } from './paths.js'
import { installBundledRuntime } from './runtime.js'

test('node check follows the engines range', () => {
for (const version of ['22.23.4', '22.24.0', '24.22.1', '24.23.0', '26.12.1', '27.0.0']) {
expect(isSupportedNodeVersion(version)).toBe(true)
Comment on lines +9 to +11

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exercise the Node check through the package export

This test directly pins the new internal isSupportedNodeVersion helper, which is not exported from src/index.ts; consequently, an equivalent refactor that preserves runDoctor behavior but inlines or replaces the parser breaks the test. T-001 requires tests to use package exports and tolerate equivalent implementations, so exercise the version check through an exported behavior or intentionally make the check part of the package contract.

AGENTS.md reference: AGENTS.md:L5-L5

Useful? React with 👍 / 👎.

}
for (const version of ['22.13.0', '22.23.3', '23.11.0', '24.22.0', '25.9.0', '26.12.0']) {
expect(isSupportedNodeVersion(version)).toBe(false)
}
})

test('doctor accepts Bun regardless of its reported Node version', async () => {
const root = await mkdtemp(path.join(os.tmpdir(), 'pascal-cli-doctor-'))
try {
const checks = await runDoctor(resolvePascalPaths({ PASCAL_HOME: path.join(root, 'home') }))

expect(checks).toContainEqual({
id: 'node',
status: 'pass',
message: `Bun ${process.versions.bun}`,
})
} finally {
await rm(root, { recursive: true, force: true })
}
})

test('doctor reports corrupt managed state instead of crashing', async () => {
const root = await mkdtemp(path.join(os.tmpdir(), 'pascal-cli-doctor-'))
try {
Expand Down
27 changes: 21 additions & 6 deletions packages/cli/src/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,35 @@ export interface DiagnosticCheck {
message: string
}

// Mirrors `engines.node` in packages/cli/package.json: ^22.23.4 || ^24.22.1 || >=26.12.1
export function isSupportedNodeVersion(version: string): boolean {
const [major = 0, minor = 0, patch = 0] = version
.split('.')
.slice(0, 3)
.map((part) => Number.parseInt(part, 10) || 0)
const atLeast = (m: number, p: number) => minor > m || (minor === m && patch >= p)
if (major === 22) return atLeast(23, 4)
if (major === 24) return atLeast(22, 1)
if (major === 26) return atLeast(12, 1)
return major > 26
}

export async function runDoctor(
paths: PascalPaths,
options: { runtimeSourceFile?: string } = {},
): Promise<DiagnosticCheck[]> {
const checks: DiagnosticCheck[] = []
const [major = 0, minor = 0] = process.versions.node
.split('.')
.slice(0, 2)
.map((part) => Number.parseInt(part, 10))
const nodeSupported = major > 22 || (major === 22 && minor >= 13)
// Bun reports a Node compatibility version that does not track Node security releases.
const bun = process.versions.bun
const nodeSupported = bun !== undefined || isSupportedNodeVersion(process.versions.node)
checks.push({
id: 'node',
status: nodeSupported ? 'pass' : 'fail',
message: nodeSupported ? `Node ${process.versions.node}` : 'Node 22.13 or newer is required.',
message: nodeSupported
? bun
? `Bun ${bun}`
: `Node ${process.versions.node}`
: 'Node 22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+ is required.',
Comment thread
cursor[bot] marked this conversation as resolved.
})
try {
await ensurePascalDirectories(paths)
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Cursor, and OpenClaw, read [Connect an AI agent](https://editor.pascal.app/docs/
The hosted endpoint edits projects in a Pascal account; this package is the
open-source, local server for custom hosts and local scene storage.

The server runs headlessly in Node.js 22.13 or newer or Bun, with no browser,
The server runs headlessly in Node.js (22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+) or Bun, with no browser,
WebGPU, React, or external database service. It exposes the same scene mutations used
by the editor UI (create walls, place items, cut openings, undo, etc.) as MCP tools,
resources, and prompts.
Expand Down
2 changes: 1 addition & 1 deletion skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Use one active agent client per local CLI service. Its standalone HTTP runtime s

## Install in Cursor

The Cursor marketplace installs this repository's `skills/` directory. Its `.cursor-plugin/plugin.json` explicitly selects the Cursor MCP configuration, so the Claude-only `${user_config.pascal_api_key}` header is never used by Cursor. The local server runs `npx --yes --package=@pascal-app/cli@1.0.6 pascal mcp connect`; Node.js 22.13 or newer and npm must be available to Cursor. No global `pascal` installation or web-editor runtime is required. The first connection downloads the pinned CLI from npm, and later connections reuse npm's cache. This starts only the local MCP service and keeps existing local project storage. If Cursor reports `spawn npx ENOENT`, install Node.js/npm and fully restart Cursor so it picks up the executable path. For an older installed bundle that still runs `pascal`, update the plugin; `npm install --global @pascal-app/cli@1.0.6` followed by **Customize → MCPs → pascal → Reload** repairs that legacy local command.
The Cursor marketplace installs this repository's `skills/` directory. Its `.cursor-plugin/plugin.json` explicitly selects the Cursor MCP configuration, so the Claude-only `${user_config.pascal_api_key}` header is never used by Cursor. The local server runs `npx --yes --package=@pascal-app/cli@1.0.6 pascal mcp connect`; Node.js 22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+ and npm must be available to Cursor. No global `pascal` installation or web-editor runtime is required. The first connection downloads the pinned CLI from npm, and later connections reuse npm's cache. This starts only the local MCP service and keeps existing local project storage. If Cursor reports `spawn npx ENOENT`, install Node.js/npm and fully restart Cursor so it picks up the executable path. For an older installed bundle that still runs `pascal`, update the plugin; `npm install --global @pascal-app/cli@1.0.6` followed by **Customize → MCPs → pascal → Reload** repairs that legacy local command.

The hosted `pascal-hosted` server uses browser sign-in. In **Customize → MCPs**, choose **Authenticate** (or **Connect**) beside `pascal-hosted`. Pascal opens in your browser: sign in or create an account with Google or email, choose the intended workspace, review access, then return to Cursor. No API key or plugin variable is required. Let the user approve the account and workspace shown in consent. Ordinary access covers reading and editing projects; it does not authorize publishing, credit spending, external AI processing, community posting, or account management. Disconnect at `https://editor.pascal.app/settings/connected-apps`.

Expand Down
2 changes: 1 addition & 1 deletion skills/furniture-fit/references/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ The current OpenClaw static-header path stores the expanded key in its private M

Cursor:

The Cursor marketplace installs this repository's `skills/` directory. Its `.cursor-plugin/plugin.json` explicitly selects the Cursor MCP configuration, so the Claude-only `${user_config.pascal_api_key}` header is never used by Cursor. The local server runs `npx --yes --package=@pascal-app/cli@1.0.6 pascal mcp connect`; Node.js 22.13 or newer and npm must be available to Cursor. No global `pascal` installation or web-editor runtime is required. The first connection downloads the pinned CLI from npm, and later connections reuse npm's cache. This starts only the local MCP service and keeps existing local project storage. If Cursor reports `spawn npx ENOENT`, install Node.js/npm and fully restart Cursor so it picks up the executable path. For an older installed bundle that still runs `pascal`, update the plugin; `npm install --global @pascal-app/cli@1.0.6` followed by **Customize → MCPs → pascal → Reload** repairs that legacy local command.
The Cursor marketplace installs this repository's `skills/` directory. Its `.cursor-plugin/plugin.json` explicitly selects the Cursor MCP configuration, so the Claude-only `${user_config.pascal_api_key}` header is never used by Cursor. The local server runs `npx --yes --package=@pascal-app/cli@1.0.6 pascal mcp connect`; Node.js 22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+ and npm must be available to Cursor. No global `pascal` installation or web-editor runtime is required. The first connection downloads the pinned CLI from npm, and later connections reuse npm's cache. This starts only the local MCP service and keeps existing local project storage. If Cursor reports `spawn npx ENOENT`, install Node.js/npm and fully restart Cursor so it picks up the executable path. For an older installed bundle that still runs `pascal`, update the plugin; `npm install --global @pascal-app/cli@1.0.6` followed by **Customize → MCPs → pascal → Reload** repairs that legacy local command.

The hosted `pascal-hosted` server uses browser sign-in. In **Customize → MCPs**, choose **Authenticate** (or **Connect**) beside `pascal-hosted`. Pascal opens in your browser: sign in or create an account with Google or email, choose the intended workspace, review access, then return to Cursor. No API key or plugin variable is required. Let the user approve the account and workspace shown in consent. Ordinary access covers reading and editing projects; it does not authorize publishing, credit spending, external AI processing, community posting, or account management. Disconnect at `https://editor.pascal.app/settings/connected-apps`.

Expand Down
2 changes: 1 addition & 1 deletion skills/pascal-3d/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: pascal-3d
description: Connect to Pascal and use its MCP tools to create, inspect, edit, validate, save, or hand off editable 3D building scenes. Use this skill whenever a user asks an agent to work in Pascal, make a room or building model, inspect a Pascal project, perform spatial edits, connect Pascal MCP, or return a verified Pascal editor link. It also governs safe local, existing-account, and explicitly authorized autonomous setup.
compatibility: Requires an MCP-capable host and either the local Pascal CLI or access to the hosted Pascal MCP endpoint. Local CLI requires Node.js 22.13 or newer.
compatibility: Requires an MCP-capable host and either the local Pascal CLI or access to the hosted Pascal MCP endpoint. Local CLI requires Node.js 22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+.
metadata:
version: "0.1.0"
source-reviewed: "2026-09-08"
Expand Down
4 changes: 2 additions & 2 deletions skills/pascal-3d/references/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Choose one path. Do not switch storage boundaries without the user's instruction

## Local Pascal CLI

Use local mode when the project should remain on the current machine. It requires Node.js 22.13 or newer and does not require a Pascal account or API key.
Use local mode when the project should remain on the current machine. It requires Node.js 22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+ and does not require a Pascal account or API key.

Install the published CLI:

Expand Down Expand Up @@ -107,7 +107,7 @@ The current OpenClaw static-header path stores the expanded key in its private M

Cursor:

The Cursor marketplace installs this repository's `skills/` directory. Its `.cursor-plugin/plugin.json` explicitly selects the Cursor MCP configuration, so the Claude-only `${user_config.pascal_api_key}` header is never used by Cursor. The local server runs `npx --yes --package=@pascal-app/cli@1.0.6 pascal mcp connect`; Node.js 22.13 or newer and npm must be available to Cursor. No global `pascal` installation or web-editor runtime is required. The first connection downloads the pinned CLI from npm, and later connections reuse npm's cache. This starts only the local MCP service and keeps existing local project storage. If Cursor reports `spawn npx ENOENT`, install Node.js/npm and fully restart Cursor so it picks up the executable path. For an older installed bundle that still runs `pascal`, update the plugin; `npm install --global @pascal-app/cli@1.0.6` followed by **Customize → MCPs → pascal → Reload** repairs that legacy local command.
The Cursor marketplace installs this repository's `skills/` directory. Its `.cursor-plugin/plugin.json` explicitly selects the Cursor MCP configuration, so the Claude-only `${user_config.pascal_api_key}` header is never used by Cursor. The local server runs `npx --yes --package=@pascal-app/cli@1.0.6 pascal mcp connect`; Node.js 22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+ and npm must be available to Cursor. No global `pascal` installation or web-editor runtime is required. The first connection downloads the pinned CLI from npm, and later connections reuse npm's cache. This starts only the local MCP service and keeps existing local project storage. If Cursor reports `spawn npx ENOENT`, install Node.js/npm and fully restart Cursor so it picks up the executable path. For an older installed bundle that still runs `pascal`, update the plugin; `npm install --global @pascal-app/cli@1.0.6` followed by **Customize → MCPs → pascal → Reload** repairs that legacy local command.

The hosted `pascal-hosted` server uses browser sign-in. In **Customize → MCPs**, choose **Authenticate** (or **Connect**) beside `pascal-hosted`. Pascal opens in your browser: sign in or create an account with Google or email, choose the intended workspace, review access, then return to Cursor. No API key or plugin variable is required. Let the user approve the account and workspace shown in consent. Ordinary access covers reading and editing projects; it does not authorize publishing, credit spending, external AI processing, community posting, or account management. Disconnect at `https://editor.pascal.app/settings/connected-apps`.

Expand Down
Loading