Skip to content

Commit c450a08

Browse files
committed
Drop project-marker requirement on launch
cwdGuard required cwd to contain one of .git, package.json, composer.json, Cargo.toml, or pyproject.toml. The check was paternalistic, not load-bearing: nothing else in the codebase consumes PROJECT_MARKERS, and the real safety guards (refusing ~, /, /root, and inside ~/.mdredd/) were already separate. The sandbox builder mirrors via cheap symlinks and applies gitignore filtering at every level, so launching from a non-project directory is slow at worst (a flat dump with no .gitignore would walk every file) but never unsafe. Remove the marker check, the anyExists helper, and the PROJECT_MARKERS constant.
1 parent b264bb8 commit c450a08

3 files changed

Lines changed: 2 additions & 31 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ npm run test:slug # tsx test/slug.spec.ts
3636

3737
- `CLAUDE_BIN` — path to the `claude` binary. Defaults to `claude` (resolved via PATH). Point this at `test/fake-claude.mjs` to drive the runner deterministically without spending tokens.
3838
- `MDREDD_LOG_LEVEL``debug` | `info` (default) | `warn` | `error`. Server-only; logs go to stdout (info/debug) or stderr (warn/error).
39-
- `bin/mdredd.js` takes no flags. The cwd must contain a project marker (`.git`, `package.json`, etc. — see `PROJECT_MARKERS`); the browser opens automatically on first launch and is suppressed on tsx-watch hot restarts via `~/.mdredd/.dev-open-marker`.
39+
- `bin/mdredd.js` takes no flags. mdredd runs from any cwd except `~`, `/`, `/root`, or inside `~/.mdredd/`. The browser opens automatically on first launch and is suppressed on tsx-watch hot restarts via `~/.mdredd/.dev-open-marker`.
4040

4141
Tests are plain tsx scripts, not a framework. Each file declares scenarios via a local `scenario(name, fn)` helper and exits non-zero on failure. To run a single scenario, edit the file's queue or comment out the others — there's no `--grep`. Most server tests use `test/fake-claude.mjs` (a stand-in for the real `claude` CLI) selected via `FAKE_CLAUDE_SCENARIO` env vars.
4242

src/server/preflight.ts

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@ import { createHash } from 'node:crypto';
44
import { homedir } from 'node:os';
55
import { join, resolve } from 'node:path';
66
import { pathExists, atomicWriteFile, ensureDir, readJsonIfExists } from './fsUtil.js';
7-
import {
8-
PROJECT_INFO_FILE,
9-
PROJECT_MARKERS,
10-
PROJECTS_DIR_NAME,
11-
STORAGE_DIR_NAME,
12-
} from '@shared/constants.js';
7+
import { PROJECT_INFO_FILE, PROJECTS_DIR_NAME, STORAGE_DIR_NAME } from '@shared/constants.js';
138
import { readdir, readFile, rm, stat, unlink, writeFile } from 'node:fs/promises';
149
import lockfile from 'proper-lockfile';
1510
import { log } from './log.js';
@@ -158,22 +153,6 @@ async function cwdGuard(cwd: string, storageRoot: string): Promise<void> {
158153
'cd into the project root and try again.',
159154
);
160155
}
161-
162-
const hasMarker = await anyExists(PROJECT_MARKERS.map((m) => join(cwd, m)));
163-
if (!hasMarker) {
164-
throw new PreflightError(
165-
'cwd-no-marker',
166-
`No project marker (${PROJECT_MARKERS.join(', ')}) found at ${cwd}.`,
167-
'Run mdredd from a project root.',
168-
);
169-
}
170-
}
171-
172-
async function anyExists(paths: string[]): Promise<boolean> {
173-
for (const p of paths) {
174-
if (await pathExists(p)) return true;
175-
}
176-
return false;
177156
}
178157

179158
async function ensureAutoGitignore(storageRoot: string): Promise<void> {

src/shared/constants.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,6 @@ export const HEARTBEAT_INTERVAL_MS = 15_000;
1717
export const READ_ONLY_TOOLS = ['Read', 'Glob', 'Grep', 'WebSearch', 'WebFetch'];
1818
export const WRITE_TOOLS = [...READ_ONLY_TOOLS, 'Write', 'Edit'];
1919

20-
export const PROJECT_MARKERS = [
21-
'.git',
22-
'package.json',
23-
'composer.json',
24-
'Cargo.toml',
25-
'pyproject.toml',
26-
];
27-
2820
// Pin to a concrete model ID, not the `haiku` CLI alias: aliases can be
2921
// repointed to a future generation or removed, which would silently shift
3022
// score baselines or break the judge entirely (issue #13). Bump manually

0 commit comments

Comments
 (0)