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
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ jobs:
- name: Syntax-check scripts
run: |
node --check scripts/init.mjs
node --check scripts/detect.mjs
node --check scripts/smoke-test.mjs
- name: Validate package.json parses
run: node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))"
Expand All @@ -31,10 +32,11 @@ jobs:
npm install "$GITHUB_WORKSPACE"/cursor-os-*.tgz
./node_modules/.bin/cursor-os init --target ./proj
./node_modules/.bin/cursor-os doctor --target ./proj
./node_modules/.bin/cursor-os detect --target ./proj --format json | grep -q '"schemaVersion": 1'
# bare invocation must print help and write nothing
./node_modules/.bin/cursor-os | grep -q "Usage:"
# programmatic import must resolve
node -e "import('cursor-os').then(m => { if (typeof m.install !== 'function') process.exit(1); }).catch(() => process.exit(1))"
node -e "import('cursor-os').then(m => { if (typeof m.install !== 'function' || typeof m.doctor !== 'function' || typeof m.detect !== 'function') process.exit(1); }).catch(() => process.exit(1))"

smoke-test:
strategy:
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This repository ships Cursor OS — an installable operating layer that makes Cu
## Repository layout

- `template/` — the kit that gets copied into other projects. Never assume a specific stack here.
- `scripts/` — the installer (`init.mjs`) and its smoke test. Node built-ins only; no dependencies.
- `scripts/` — the CLI and install/doctor APIs (`init.mjs`), read-only project detection (`detect.mjs`), and smoke test. Node built-ins only; no dependencies.
- `examples/` — concrete examples showing what localization looks like.
- `docs/` — this repo's own decision log (not installed into user projects).
- `README.md`, `CHANGELOG.md`, `CONTRIBUTING.md` — public-facing docs.
Expand Down
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,26 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

<!-- Add new changes here. -->
### Added

- Read-only `detect` command with deterministic text and versioned JSON output.
- Evidence-backed detection for languages, JavaScript frameworks, package managers,
monorepo indicators, package scripts, common tooling, and Next.js/Supabase/Vercel
localization presets.
- Programmatic `detect({ target })` export alongside `install` and `doctor`.
- Post-install project-signal summary that grounds the localization next step without
modifying user files.
- Detection warnings for malformed `package.json` and competing package-manager
lockfiles; neither condition prevents a partial report.
- Smoke coverage for programmatic and CLI detection, JSON parsing, read-only behavior,
invalid formats, stack presets, malformed manifests, and post-install signals (155
checks total).

### Changed

- `prompts/localize-cursor-os.md` now consumes `cursor-os detect --format json` as an
optional evidence source, while requiring every signal to be verified against the
repository before localization edits.

## [0.2.0] — 2026-06-10

Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ Prompts live in `template/prompts/` and use descriptive command-style names (e.g
## Development

```bash
npm test # run installer, doctor, and CLI smoke tests
npm test # run installer, doctor, detector, and CLI smoke tests
node scripts/init.mjs init --dry-run # preview an install into the current dir
node scripts/init.mjs doctor # check install state of current dir
node scripts/init.mjs detect --format json # read-only project signals
npm run pack:dry-run # preview npm package contents
```

Expand Down
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ prompts/

The installer copies these files. The localization prompt fills them in for your project.

Before localization, the read-only detector can extract evidence-backed stack signals
from root manifests and configuration files:

```bash
npx cursor-os detect --format json
```

It reports languages, frameworks, services, tooling, package scripts, workspace shape,
and applicable localization presets. It never edits the project, and its output is
guidance—not a replacement for inspecting the actual code.

## The two-step setup

**Step 1 — Install the base OS** (the installer does this):
Expand Down Expand Up @@ -117,6 +128,8 @@ Target: /path/to/your-project
(Abbreviated — `doctor` lists every installed file; the version shown matches your checkout. The `note:` lines flag the unfilled TODO placeholders in `AGENTS.md` and `docs/repo-memory.md` that localization resolves. Once localization fills them, `doctor` reports "installed and localized". If the install came from an older Cursor OS version, `doctor` also notes the drift so you can re-run `init` to pick up new files.)

`init` runs this same health check automatically after installing, so you always see the placeholder count and the next step without a separate command.
When root manifests expose recognizable tooling, it also prints a concise set of
detected project signals to ground the localization step.

## What Cursor loads automatically vs. what you paste

Expand All @@ -134,6 +147,9 @@ localize-cursor-os.md (once after install)
plan-feature.md → implement-change.md → verify-work.md → review-pr.md
```

For an evidence-first setup, run `npx cursor-os detect --format json` immediately
before `prompts/localize-cursor-os.md`.

See the [prompts guide](template/prompts/README.md) (installs as `prompts/README.md`) for when to use each prompt.

## When not to use the full workflow
Expand Down Expand Up @@ -166,15 +182,32 @@ npx cursor-os <command> [target] [options]
Commands:
init Install Cursor OS into the target directory
doctor Check whether Cursor OS is installed in the target directory
detect Report project stack signals without modifying files

Options:
-n, --dry-run Preview changes without writing anything (init only)
-t, --target DIR Use DIR as the target directory
--format TYPE Output text or json (detect only; default: text)
-v, --version Print version and exit
-h, --help Show this help
```

A command is required: bare invocation (`npx cursor-os` with no arguments) prints help and never writes files. For a target directory named `init` or `doctor`, or one whose name starts with `-`, use the explicit form `init --target <dir>`. Requires Node.js 20 or newer.
A command is required: bare invocation (`npx cursor-os` with no arguments) prints help and never writes files. For a target directory named `init`, `doctor`, or `detect`, or one whose name starts with `-`, use the intended command with `--target <dir>`. Requires Node.js 20 or newer.

`detect` reads only root manifests, lockfiles, dependency names, and well-known config
markers. JSON output uses a versioned schema and includes evidence for each signal plus
non-fatal warnings for malformed manifests or competing lockfiles.

## Programmatic API

```js
import { detect, doctor, install } from "cursor-os";

const profile = detect({ target: process.cwd() });
```

All three APIs are dependency-free. `detect` and `doctor` are read-only; `install`
preserves the no-overwrite contract.

## What gets installed

Expand Down Expand Up @@ -220,7 +253,8 @@ prompts/

- `v0.1` — installable operating layer: contract, rules, skills, verifier, docs, prompts, installer, doctor command. ✅
- `v0.2` — npm publishing (`npx cursor-os init`), safer CLI defaults, post-install health check, version-drift detection. ✅
- Next — interactive setup with project detection, stack presets (Next.js, Supabase, Vercel).
- `v0.3` — read-only project detection, deterministic JSON, and localization preset signals for Next.js, Supabase, and Vercel. 🚧 Unreleased
- Next — opt-in interactive localization using the detected profile, with explicit review before edits.

## Contributing

Expand Down
7 changes: 4 additions & 3 deletions RELEASE_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ Use this checklist before tagging a public release or publishing Cursor OS to np

## Installer and CLI

- [ ] `node scripts/init.mjs --help` shows `init`, `doctor`, `--target`, `--dry-run`, and `--version`.
- [ ] `node scripts/init.mjs --help` shows `init`, `doctor`, `detect`, `--target`, `--format`, `--dry-run`, and `--version`.
- [ ] `node scripts/init.mjs` with no arguments prints help and writes nothing.
- [ ] `node scripts/init.mjs --version` matches `package.json`.
- [ ] `node scripts/init.mjs init --dry-run --target <tmp>` writes nothing.
- [ ] `node scripts/init.mjs init --target <tmp>` installs the expected file set.
- [ ] `node scripts/init.mjs doctor --target <installed-tmp>` exits 0.
- [ ] `node scripts/init.mjs doctor --target <empty-tmp>` exits non-zero and lists missing files.
- [ ] `node scripts/init.mjs detect --target <project> --format json` emits parseable, evidence-backed JSON and writes nothing.
- [ ] Invalid commands and invalid `--target` usage exit non-zero without writing files.

## Template quality
Expand All @@ -48,8 +49,8 @@ Use this checklist before tagging a public release or publishing Cursor OS to np

## Packaging integrity

- [ ] `npm pack`, install the tarball into a scratch project, and run the bin: `init`, `doctor`, and bare invocation all behave. (CI runs this on every push.)
- [ ] `import('cursor-os')` resolves and exposes `install` and `doctor`.
- [ ] `npm pack`, install the tarball into a scratch project, and run the bin: `init`, `doctor`, `detect`, and bare invocation all behave. (CI runs this on every push.)
- [ ] `import('cursor-os')` resolves and exposes `install`, `doctor`, and `detect`.
- [ ] `head -1 scripts/init.mjs` is exactly `#!/usr/bin/env node` (no CRLF, no BOM).
- [ ] No stray `*.tgz` files tracked in git.

Expand Down
21 changes: 21 additions & 0 deletions docs/decision-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

Append-only record of notable decisions for the Cursor OS project itself. Newest first. (Not part of the installable template — `template/docs/decision-log.md` is what gets installed into user projects.)

## 2026-08-01 — Project detection is read-only, evidence-backed, and advisory

- **Decision:** Add a `detect` command and programmatic API that inspect root manifests,
lockfiles, dependency names, and well-known config markers. It emits deterministic
text or versioned JSON, including evidence and warnings, but never writes a generated
profile into the project. Next.js, Supabase, and Vercel are emitted as localization
preset signals rather than stack-specific template files.
- **Context:** The v0.2 workflow asks an agent to rediscover basic stack facts during
every localization. The roadmap called for project detection and presets, but the
base template must remain framework-neutral and the installer must not silently
rewrite user content.
- **Alternatives:** Automatically localize files during `init` — rejected because it
spends tokens and produces unreviewed edits. Persist `.cursor/project-profile.json`
— rejected for now because generated state can become stale and would create another
overwrite exception. Recursively scan all source files — rejected because it is
slower, noisier, and unnecessary for the first evidence pass.
- **Consequences:** Detection is safe to run at any time and straightforward to consume
in automation. Localization still verifies signals against source and remains an
explicit, reviewable step. Richer opt-in interactive localization can build on the
versioned report later.

## 2026-06-10 — v0.2.0 publishes manually; CI publishing with provenance deferred

- **Decision:** The first npm release is published manually by the maintainer (`npm publish` from a tagged, CI-green commit). Automated publishing from GitHub Actions with npm provenance/trusted publishing is deferred.
Expand Down
4 changes: 2 additions & 2 deletions docs/quality-rubric.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ Gate to check before claiming any change is done. All items must pass with evide

## Verification (project-specific)

- [ ] `npm test` passes — `node scripts/smoke-test.mjs`, 126 checks minimum.
- [ ] `node --check scripts/init.mjs && node --check scripts/smoke-test.mjs` clean.
- [ ] `npm test` passes — `node scripts/smoke-test.mjs`, 155 checks minimum.
- [ ] `node --check scripts/init.mjs && node --check scripts/detect.mjs && node --check scripts/smoke-test.mjs` clean.
- [ ] `npm run pack:dry-run` exits 0 and file list matches `package.json#files`.
- [ ] `node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))"` succeeds.
- [ ] If `template/` files changed: `EXPECTED` in `smoke-test.mjs`, `README.md`, and `CHANGELOG.md` updated together.
Expand Down
9 changes: 6 additions & 3 deletions docs/repo-memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ Cursor OS: an installable operating layer that makes Cursor project-aware. Devel

- **Language:** Node.js ESM (`.mjs`), zero runtime or dev dependencies by design
- **Minimum Node:** 20 (enforced in `package.json` `engines`)
- **Product:** `template/` (the installable kit) + `scripts/` (installer CLI)
- **Product:** `template/` (the installable kit) + `scripts/` (installer, doctor, and read-only detector CLI)
- **No build step:** scripts run directly with `node`

## How it's organised

```
template/ The kit installed into user projects (AGENTS.md, rules, skills, agents, docs, prompts)
scripts/ init.mjs (installer + library) and smoke-test.mjs (installer smoke test suite)
scripts/ init.mjs (CLI + install/doctor APIs), detect.mjs (read-only project profile), smoke-test.mjs
examples/ Before/after localization walkthrough
docs/ This repo's own decision log (not installed into user projects)
.cursor/ cursor-os installed on itself (dogfooded)
Expand All @@ -27,17 +27,19 @@ docs/ This repo's own decision log (not installed into user project

- Install: none (zero dependencies)
- Test: `npm test`
- Lint / syntax-check: `node --check scripts/init.mjs && node --check scripts/smoke-test.mjs`
- Lint / syntax-check: `node --check scripts/init.mjs && node --check scripts/detect.mjs && node --check scripts/smoke-test.mjs`
- Pack preview: `npm run pack:dry-run`
- Dry-run install: `node scripts/init.mjs init --dry-run`
- Health check: `node scripts/init.mjs doctor`
- Project detection: `node scripts/init.mjs detect --format json`
- Build: none (no compile step)

## Conventions and gotchas

- **Zero deps, always.** The installer must stay dependency-free (Node built-ins only). No devDependencies without a very strong reason.
- **Template files are framework-neutral.** No stack presets in `template/`; all project-specific content is generated during localization.
- **No-clobber invariant.** `install()` never overwrites existing files. Every test that touches this path must preserve it.
- **Detection is advisory and read-only.** `detect()` uses root evidence only, returns a versioned report, and never replaces source inspection during localization.
- **Idempotency.** Re-running `init` is always safe. Smoke tests verify second-run behaviour.
- **EXPECTED list in smoke-test.mjs must stay in sync with template/.** When you add or remove a template file, update `EXPECTED` in `scripts/smoke-test.mjs`, `README.md`, and `CHANGELOG.md` together.
- **Prompt files referenced by full path, never by number.** e.g. `prompts/plan-feature.md` not "prompt 1".
Expand All @@ -57,3 +59,4 @@ docs/ This repo's own decision log (not installed into user project
- 2026-06-10 — `doctor`'s success state required rewriting template instruction notes so placeholder markers only appear as real placeholders. Fixed in audit remediation; the smoke test pins this.
- 2026-06-10 — `listFiles` used `statSync` (follows symlinks); swapped to `lstatSync` to prevent cycle risk.
- 2026-06-10 — CLI previously defaulted to `init`; now bare invocation prints help (breaking pre-publish, safe decision).
- 2026-08-01 — `detect` adds evidence-backed stack and preset signals without persisting generated state or adding dependencies.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
"scripts": {
"init": "node scripts/init.mjs init",
"doctor": "node scripts/init.mjs doctor",
"detect": "node scripts/init.mjs detect",
"pack:dry-run": "npm pack --dry-run",
"test": "node scripts/smoke-test.mjs"
},
"files": [
"template",
"scripts/init.mjs",
"scripts/detect.mjs",
"examples",
"README.md",
"LICENSE",
Expand Down
Loading
Loading