Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
92c36e9
feat: show session and weekly usage limits in status bar (fork-issue-35)
Jul 24, 2026
773e71c
fix: parse and show per-model weekly usage buckets (fork-issue-35)
Jul 25, 2026
1bf5746
fix: read the per-model weekly window from the limits array (fork-iss…
Jul 25, 2026
f4e7cc9
feat: add pure path/binary/uri helpers for the turn diff view (fork-i…
Jul 25, 2026
d7249d6
feat: show code changes as a real VS Code diff against the turn check…
Jul 25, 2026
a6ade54
fix: refresh usage limits right after a turn ends instead of serving …
Jul 25, 2026
550ae12
fix: restore checkpoints after history load via backup-repo existence…
Jul 27, 2026
93aff13
Fix stale Fable references in usage-limits comment and status line
Jul 28, 2026
f3d91a2
Fix context-window sizes and scrub internal-fork references
Jul 28, 2026
da55e88
fix: wire currentContextTokens from extension host to webview status …
Jul 28, 2026
4dc7100
docs: scrub remaining internal-process wording from turn-diff comments
Jul 28, 2026
d686a45
fix: log only the basename in the turn-diff auto-skip perm-log line
Jul 28, 2026
e9e02a0
docs: fix stale fork-issue-24 comment, drop two stray blank lines
Jul 28, 2026
9c03a2e
fix: wire dead KNOWN_ENDPOINT_MARKERS constant, redact reason= path l…
Jul 29, 2026
9aa0377
feat: offer a shortcut to raise CLAUDE_CODE_MAX_OUTPUT_TOKENS (fork-i…
Jul 25, 2026
619ff07
feat: configurable chat font family and size (fork-issue-44)
Jul 25, 2026
9d6b008
feat: expose font and max-output-token settings in the chat settings …
Jul 25, 2026
6ba6e26
fix: keep saving the settings batch after one key fails (fork-issue-56)
Jul 27, 2026
c4863c2
test: scrub internal review note from settings-batch suite title
Jul 28, 2026
a20f5e1
fix: remove the dead onSettled param and its inaccurate rationale (fo…
Jul 28, 2026
d8f966f
chore: de-link bare internal issue references reintroduced by the set…
Jul 28, 2026
f27ea8d
docs: correct 6257620's overstated config-change-broadcast claim
Jul 28, 2026
90ccc94
docs: fix settings-batch comments' false _permLog claim and stale sib…
Jul 28, 2026
fcc7066
docs: replace fabricated ui.renderMath scenario with real setting keys
Jul 28, 2026
bb5ee6a
test: replace the nonexistent ui.compactMode fixture key with a real …
Jul 29, 2026
75237b7
fix: don't zero out max-output-tokens/font settings when the modal wa…
Jul 29, 2026
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 @@ -48,7 +48,7 @@ Ditch the command line and experience Claude Code like never before. This extens

### 📝 **Inline Diff Viewer**
- **Full Diff Display** - See complete file changes directly in Edit, MultiEdit, and Write messages
- **Open in VS Code Diff** - One-click button to open VS Code's native side-by-side diff editor
- **Open in VS Code Diff** - One-click button opens a real VS Code diff comparing the checkpoint from before the current turn against the live, editable file; it stays available after the edit completes and after reloading a saved conversation, and can auto-open after every successful edit (configurable in settings)
- **Smart Truncation** - Long diffs are truncated with an expand button for better readability
- **Syntax Highlighting** - Proper code highlighting in diff views
- **Visual Change Indicators** - Clear green/red highlighting for additions and deletions
Expand Down
28 changes: 27 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@
"default": "",
"description": "Custom path to the Claude Code executable. Leave empty to use the default 'claude' command."
},
"claudeCodeChat.advanced.maxOutputTokens": {
"type": "number",
"default": 0,
"minimum": 0,
"description": "Maximum number of tokens Claude may generate in a single response (sets the CLAUDE_CODE_MAX_OUTPUT_TOKENS environment variable for the CLI). Increase this if you hit a \"response exceeded the output token maximum\" error. 0 = use the CLI default."
},
"claudeCodeChat.environment.variables": {
"type": "object",
"default": {},
Expand All @@ -208,6 +214,23 @@
"type": "boolean",
"default": false,
"description": "Enable the local router to convert OpenAI format to Anthropic format. Required for providers that use OpenAI-compatible APIs."
},
"claudeCodeChat.diff.autoOpen": {
"type": "boolean",
"default": true,
"description": "Automatically open a VS Code diff view after Claude successfully edits or creates a file, comparing it against the checkpoint from before the current turn."
},
"claudeCodeChat.ui.fontFamily": {
"type": "string",
"default": "",
"description": "Custom font family for the chat message area and input field. Leave empty to use the editor's default font."
},
"claudeCodeChat.ui.fontSize": {
"type": "number",
"default": 0,
"minimum": 0,
"maximum": 72,
"description": "Custom font size (px, 6-72) for the chat message area and input field. Leave at 0 to use the editor's default font size."
}
}
}
Expand All @@ -221,7 +244,10 @@
"test": "vscode-test",
"test:downloader": "npm run compile && mocha --ui tdd \"out/test/downloader*.test.js\" --reporter spec --timeout 360000",
"test:downloader:unit": "npm run compile && mocha --ui tdd out/test/downloader.test.js --reporter spec",
"test:models": "npm run compile && mocha --ui tdd out/test/model-updater.test.js --reporter spec"
"test:models": "npm run compile && mocha --ui tdd out/test/model-updater.test.js --reporter spec",
"test:diff-utils": "npm run compile && mocha --ui tdd out/test/diff-utils.test.js --reporter spec",
"test:restore-commit-utils": "npm run compile && mocha --ui tdd out/test/restore-commit-utils.test.js --reporter spec",
"test:settings-batch": "npm run compile && mocha --ui tdd out/test/settings-batch.test.js --reporter spec"
},
"devDependencies": {
"@types/mocha": "^10.0.10",
Expand Down
116 changes: 116 additions & 0 deletions src/diff-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Pure helpers for the fork-issue-38 turn-diff feature (real vscode.diff view comparing the
// pre-turn checkpoint against the live file). No vscode import, so these run under
// plain mocha like model-updater -- extension.ts owns all the side effects (git exec,
// workspace lookup, vscode.Uri/vscode.diff) and just feeds paths/buffers through
// these functions.

// Maps a WSL-reported path (e.g. /mnt/c/Users/example/foo.ts, as seen in tool_use
// rawInput.file_path when claudeCodeChat.wsl.enabled is on) back to the real Windows
// path VS Code and git need. Only rewrites an actual /mnt/<drive>/... path; anything
// else (already a Windows path, or a Linux path outside /mnt) is returned unchanged.
export function mapWslPathToWindows(filePath: string): string {
const match = filePath.match(/^\/mnt\/([a-zA-Z])\/(.*)$/);
if (!match) {
return filePath;
}
const drive = match[1].toUpperCase();
const rest = match[2].replace(/\//g, '\\');
return `${drive}:\\${rest}`;
}

// Resolves an absolute file path to a path relative to the workspace root, using '/'
// separators so the result can be passed straight to `git show <sha>:<relPath>`
// (git's tree-ish path syntax always uses '/', regardless of OS). Comparison is
// case-insensitive on Windows, where the filesystem is case-insensitive but tool
// input paths and the workspace folder path aren't guaranteed to agree on casing.
// Returns undefined when filePath isn't inside workspaceRoot ("not mappable"), which
// also covers filePath being the workspace root itself (a
// directory has no checkpointed blob to diff against, so treat it the same as
// "outside the workspace" instead of handing callers a '' relPath).
export function toWorkspaceRelativePath(filePath: string, workspaceRoot: string): string | undefined {
const normalize = (p: string) => p.replace(/\\/g, '/').replace(/\/+$/, '');
const normFile = normalize(filePath);
const normRoot = normalize(workspaceRoot);
if (!normFile || !normRoot) {
return undefined;
}

const caseInsensitive = process.platform === 'win32';
const fileKey = caseInsensitive ? normFile.toLowerCase() : normFile;
const rootKey = caseInsensitive ? normRoot.toLowerCase() : normRoot;

if (fileKey === rootKey) {
return undefined;
}
if (fileKey.startsWith(rootKey + '/')) {
return normFile.slice(normRoot.length + 1);
}
return undefined;
}

// Binary heuristic used to keep obviously-binary content out of the diff virtual
// document: a NUL byte within the first 8 KB, the same window common tools (git,
// grep) use. Not exact binary detection -- just a "should we even try to diff this"
// guard before handing content to a text-based diff view.
const BINARY_CHECK_WINDOW_BYTES = 8192;

export function isBinaryContent(content: Buffer): boolean {
const len = Math.min(content.length, BINARY_CHECK_WINDOW_BYTES);
for (let i = 0; i < len; i++) {
if (content[i] === 0) {
return true;
}
}
return false;
}

// Scheme of the existing read-only diff content provider (registered once in
// extension.ts, reused here instead of adding a second provider).
export const TURN_DIFF_URI_SCHEME = 'claude-diff';

export interface TurnDiffUriParts {
scheme: string;
path: string;
query: string;
}

// Builds the (scheme, path, query) a stable baseline URI is made of: deterministic
// per (sha, relPath), so vscode.Uri.from(parts) always produces the identical URI
// for the same turn+file and VS Code dedupes the tab instead of stacking a new one
// per click. relPath keeps its real extension in `path` (git's basename) so the
// virtual document still gets the right syntax highlighting; `sha` goes in the query
// so two turns diffing the same file don't collide on the same URI/cache entry.
export function buildTurnDiffUriParts(sha: string, relPath: string): TurnDiffUriParts {
return {
scheme: TURN_DIFF_URI_SCHEME,
path: '/' + relPath.replace(/^\/+/, ''),
query: `sha=${sha}`
};
}

// Inverse of buildTurnDiffUriParts: recovers (sha, relPath) from
// a claude-diff URI's own (path, query), so DiffContentProvider can resolve a cache
// miss -- a tab restored via "Reopen Closed Editor" or a VS Code restart, after the
// in-memory diffContentStore is gone -- without needing any other state. vscode.Uri
// hands back path/query already decoded, matching what buildTurnDiffUriParts wrote,
// so this is a plain string split, not URI-decoding. Returns undefined when query
// doesn't look like a URI this feature built (defensive; shouldn't happen for a URI
// on the claude-diff scheme).
export function parseTurnDiffUriParts(parts: { path: string; query: string }): { sha: string; relPath: string } | undefined {
const match = parts.query.match(/^sha=(.*)$/);
if (!match) {
return undefined;
}
return {
sha: match[1],
relPath: parts.path.replace(/^\/+/, '')
};
}

// Cache key for the content-provider's Map, derived identically on the writer (host,
// right before vscode.diff) and reader (provideTextDocumentContent) side so a
// (sha, relPath) pair never collides with a different turn's baseline for the same
// file (see buildTurnDiffUriParts).
export function turnDiffCacheKey(parts: { path: string; query: string }): string {
return `${parts.path}?${parts.query}`;
}
Loading