`setup defaults --agent claude` silently skips Claude Code: JSON comment stripper corrupts `//` inside permission strings
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 74/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- cli
Research direction
Start in src/utils/web-defaults.ts, especially removeJsonComments(), configureClaudeDefaults(), and configureWebDefaults(). Run the reported firecrawl setup defaults --agent claude reproduction with a Read(//c/Users/...) permission rule, then verify valid settings remain parseable, the Claude deny entry is handled, and skipped agents do not produce an unconditional success result.
Written by the indexing model from the issue text.
Description
Summary
firecrawl setup defaults --agent claude reports
! Skipped Claude Code settings because settings.json is not valid JSON
against a settings.json that is valid JSON. The cause is the regex comment-stripper in configureClaudeDefaults, which deletes from any // to end-of-line — including // that occurs inside a JSON string literal.
This is not a rare edge case on Windows. Claude Code writes local-path permission rules in the form Read(//c/Users/...), so the leading // appears in the file as soon as the user approves any path-scoped read or edit. One such rule is enough to make the whole file unparseable to the CLI, permanently.
Environment
firecrawl-cli1.23.3 (vianpx -y firecrawl-cli@1)- Windows 11, Node v24.13.0
Reproduction
Two settings.json files, both valid JSON, differing by one line.
Case A — ~/.claude/settings.json:
{
"permissions": {
"allow": [
"Read(//c/Users/someone/projects/**)"
]
},
"model": "opus"
}
Case B — identical, with that rule replaced by "Bash(git status)".
Run firecrawl setup defaults --agent claude against each:
| result | |
|---|---|
| A | ! Skipped Claude Code settings because settings.json is not valid JSON — no deny written |
| B | ✓ Disabled Claude Code native WebSearch/WebFetch — deny written correctly |
JSON.parse() accepts both files as-is.
Root cause
removeJsonComments() in src/utils/web-defaults.ts (observed in dist/utils/web-defaults.js:28):
function removeJsonComments(content) {
return content
.replace(/\/\*[\s\S]*?\*\//g, '')
.replace(/(^|[^:\\])\/\/.*$/gm, '$1');
}
The [^:\\] guard exempts :// (protecting URLs) and escaped slashes, but the // in "Read(//c/Users/...)" is preceded by (. The line is truncated to "Read(, leaving an unterminated string, and the subsequent JSON.parse in configureClaudeDefaults throws:
Bad control character in string literal in JSON at position 988
The catch then reports the file as invalid and skips the agent.
Because the stripper runs over the entire file before parsing, a single // anywhere poisons the parse for every key.
Two related problems in the same function
1. The comment support is self-defeating. The write path is:
await writeText(filePath, `${JSON.stringify(nextConfig, null, 2)}\n`);
The file is rebuilt from the parsed object, so any comments the stripper removed in order to parse are silently discarded on write — along with the user's key order and formatting. The stripper exists to tolerate comments, and the writer destroys them.
2. The success line prints unconditionally. configureWebDefaults can skip every agent and the command still ends with:
Firecrawl is now the default web provider for supported AI agents.
and exit code 0. That is what masked the failure initially — the warning scrolls past and the closing line reads as success. It also makes the failure invisible in CI.
Suggested fixes
Minimal — try strict JSON first
Valid JSON never reaches the regex. Verified working against Case A above:
if (existing && existing.trim()) {
try {
- config = JSON.parse(removeJsonComments(existing));
+ try {
+ config = JSON.parse(existing);
+ }
+ catch {
+ config = JSON.parse(removeJsonComments(existing));
+ }
}
catch {
return { /* skipped */ };
}
}
Proper — use a string-aware JSONC parser
Regex stripping cannot be made correct; [^:\\] was already a patch for https://, and (// is the next hole. Any // inside a string value will keep reproducing this. jsonc-parser (used by VS Code for this exact problem) handles both the read and the write:
import { parse, modify, applyEdits } from 'jsonc-parser';
const config = parse(existing) ?? {};
// ...compute nextDeny...
const edits = modify(existing, ['permissions', 'deny'], nextDeny, {
formattingOptions: { insertSpaces: true, tabSize: 2 },
});
await writeText(filePath, applyEdits(existing, edits));
modify + applyEdits also resolves problem 1 — surgical edits preserve comments, key order, and formatting instead of rewriting the document.
Reporting
Gate the closing message on results.some(r => !r.skipped), and return a non-zero exit code when an agent was skipped, so the failure is visible to users and to CI.
Workaround
Add the entries by hand to ~/.claude/settings.json:
"permissions": {
"deny": ["WebSearch", "WebFetch"]
}
Note that setup defaults --undo fails the same way, so undoing also has to be done by hand.
- Dominant language
- TypeScript
- Stars
- 635
- Forks
- 106
- Avg merge
- 1h 33m
- Merged PRs (30d)
- 43
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from firecrawl/cli
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
firecrawl-monitor skill: description exceeds Claude Code's 1024-char limit, skill fails to load Open
Difficulty 1/5 Under an hour Newbie friendliness 88/100
-
Difficulty 1/5 1-3 hours Newbie friendliness 68/100
Similar issues
-
comp/desktop P3 type/bug
Difficulty 1/5 Under an hour Newbie friendliness 92/100
NousResearch/hermes-agent#118866 ·
-
Browser Waiting for: Product Owner
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
getsentry/sentry-javascript#24577 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
agilepathway/label-checker#640 ·
-
Plugin stuck at "loading" on DSH 0.1.6-alpha.2 — turnTail list slot registration missing options.id Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
chrisparsons83/flexspotff#153 ·