floorplan
Floorplan draws an interactive, plain-English map of a codebase or a planned system (a 'blueprint' from a PRD), saved as floorplan/index.html. The map adds a health check, screens, guided flows, recent-work highlights and an Ask bar that answers questions through the user's own Claude Code or Codex CLI.
Why it's held
Changes the agent's instructions or settings.
What it can touch
| files | write, including Hard-coded keys found in scanned code/.env, CLAUDE.local.md, ~/.floorplan/settings.json |
|---|---|
| network | abcd.supabase.co, api.openai.com, claude.ai, developers.openai.com, docs.claude.com, evil.example, floorplan-waitlist-690500262396.us-central1.run.app, github.com, myapp.com, static.cloudflareinsights.com, tidy.app |
| shell | runs commands |
| secrets | API_KEY, DB_PASSWORD, FAKE_GITHUB_TOKEN, FAKE_OPENAI_KEY, FAKE_PASSWORD, NEXT_PUBLIC_STRIPE_SECRET_KEY, PUBLIC_OPENAI_KEY, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET |
What it actually does
The skill tells the agent to run its bundled Node scripts (scan, describe, build, recent, refresh, plan, open, status). The agent then writes architecture.json and descriptions/*.json into a floorplan/ folder at the codebase root. That folder ignores itself through its own .gitignore. The scripts walk the repos and call git (ls-files, rev-parse, config remote.origin.url with credentials stripped). They write graph.json, index.html, a query CLI and serve.mjs. open.mjs starts serve.mjs, a background HTTP server on 127.0.0.1 that checks the Host header and a per-run token. The server spawns `claude -p` (tools limited to Read/Grep/Glob and Bash limited to `node floorplan/query.mjs`) or `codex exec --sandbox read-only` to answer questions. It saves custom flows and health dismissals, and for blueprints it rewrites plan.json and architecture.json and re-runs the skill's scripts. The server also has an opt-in 'Floorplan Cloud' waitlist. A prompt appears after the map has been open for 2 minutes. If the user clicks 'Notify me', it POSTs an email address to a Cloud Run endpoint owned by the author. If the user clicks 'Use my Claude email', it first runs `claude auth status --json` to fill in the signed-in account email. The answer is stored in ~/.floorplan/settings.json. If the user agrees, the build writes a marked block into CLAUDE.local.md that future Claude Code sessions load, and adds that file to .git/info/exclude. It also strips old Floorplan blocks out of CLAUDE.md. The skill's frontmatter runs status.mjs automatically when the skill loads. Many scripts (build, scan, open, status, health, etc.) were left out of the bundle and could not be inspected.
What the check found
highChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
skills/floorplan/SKILL.md:97 **A note for future sessions, only if the user wants one.** In Claude Code, the build can keep a short marked block in the project's `CLAUDE.local.md`, Claude C
highChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
skills/floorplan/scripts/lib/claudemd.mjs:58 /** Refreshes the block, or adds it when `add` (the user asked for it); moves it out of a committed CLAUDE.md written by older versions. */
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
docs/project-files.md:50 In Codex this file isn't touched. Codex has no personal, uncommitted notes file (`AGENTS.md` is shared with your team), so Floorplan doesn't add a note there.
mediumRuns code that is built while it runs
eval, exec and new Function run text as code, which makes it hard to know what will actually run.
skills/floorplan/assets/serve.mjs:189 const c = new Function(`${coreSrc.replace(/^import .*$/gm, '')}; return { FLOORPLAN_ANSWER_SCHEMA, FLOORPLAN_FLOW_SCHEMA, FLOORPLAN_CHANGE_SCHEMA, floorplanAskI
mediumContains invisible characters
Zero-width and other invisible characters can hide words or split them so filters and reviewers miss them.
skills/floorplan/scripts/lib/common.mjs:252 .replace(/^⟦U+FEFF⟧/, '')
mediumOpt-in waitlist sends email to author's Cloud Run service and can read the Claude account email
The local server can POST an email address and 'solo/team' choice to a hard-coded Cloud Run endpoint run by the author. When the user presses 'Use my Claude email', it runs `claude auth status --json` to get the signed-in account email. Both steps need explicit clicks, and the UI states what is sent. It is still a third-party data flow that has nothing to do with mapping code, and a two-minute timed prompt triggers it.
skills/floorplan/assets/serve.mjs:235 const WAITLIST_URL = process.env.FLOORPLAN_WAITLIST_URL || 'https://floorplan-waitlist-690500262396.us-central1.run.app/';
skills/floorplan/assets/serve.mjs:263 const r = await fetch(WAITLIST_URL, { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: JSON.stringify({ email, use }), redirect: 'follow', signa
skills/floorplan/assets/serve.mjs:250 const out = execFileSync(cli.cmd, [...cli.args, 'auth', 'status', '--json'], { encoding: 'utf8', timeout: 15000, stdio: ['ignore', 'pipe', 'ignore'], windowsHid
mediumWrites a persistent instruction block into CLAUDE.local.md (opt-in)
With the user's consent, the build adds a block to CLAUDE.local.md that every future Claude Code session loads. The block tells the agent to consult the map first. It also edits .git/info/exclude and removes old blocks from CLAUDE.md. The skill tells the agent to ask first and to add the block only on a yes, and the content shown is benign. Once added, every build keeps it current.
skills/floorplan/SKILL.md:97 **A note for future sessions, only if the user wants one.** In Claude Code, the build can keep a short marked block in the project's `CLAUDE.local.md`, Claude C
skills/floorplan/scripts/lib/claudemd.mjs:89 if (next !== old) { fs.writeFileSync(file, next); notes.unshift(`${old == null ? 'created' : 'updated'} ${NAME}`); }
skills/floorplan/scripts/lib/claudemd.mjs:53 fs.writeFileSync(file, cur.replace(/\s*$/, cur.trim() ? '\n' : '') + `# personal Claude Code notes (added by Floorplan)\n${line}\n`);
mediumTells Codex to request escalated permissions to run outside its sandbox
Under Codex, the skill tells the agent to ask for escalated permissions and run open.mjs outside the sandbox. The stated reason is so the background server can keep running and reach the network. open.mjs was not included in the bundle and could not be checked.
skills/floorplan/SKILL.md:123 - **In Codex**, run open.mjs outside the sandbox (ask for escalated permissions): the server has to keep running after the command ends, and Ask needs the netwo
mediumRuns a bundled script automatically when the skill loads; most scripts not reviewable
The SKILL.md frontmatter uses dynamic context injection, so status.mjs runs as soon as the skill is invoked. status.mjs, scan.mjs, build.mjs, open.mjs, health.mjs and other core scripts were left out of the bundle. Their behaviour, including how secrets found by the health scan are handled, could not be verified.
skills/floorplan/SKILL.md:25 Existing map: !`node ${CLAUDE_SKILL_DIR}/scripts/status.mjs || true`
Keep an eye on it
This check is of one commit. Watch floorplan and we'll email you if a later commit changes what it can touch.
About this check
Checked November 2, 2026 at commit 226cda6b6cd1, 144 files. Rules for known red flags, then two Claude reviews, one of them told to assume the author is malicious. A later commit hasn't been checked. How checks work.