fuzzyworld

fuzzyworld-tools / commit

VS Code in the browser: open a file with &file=<path>[:<line>]

db784ff55055c16fc149abc77c77ef62e36d3eb3 · Pavel Safronov · 2026-10-28 18:14:01 -0700 · parents 57d16c8b28dc

Claude Code usage: this commit 100.4K out / 25.1M cached · cost unknown (no per-model trailer) · session 4 tally 546 in / 257.3K out / 31.8M cached · usage by commit and session

VS Code in the browser: open a file with &file=<path>[:<line>]

The folder URI carries a query when the address has &file=, so fw-fs
leaves the README closed and the requested file stays in front.

FW-Tokens-In: 546
FW-Tokens-Out: 257265
FW-Tokens-Cached: 31801514
FW-Session: 2b561b3f-f2e7-4c3d-8a96-adefba656c9e
FW-Rtk-Saved: 2546793
FW-Rtk-Cmds: 6093

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
 README.md                     |  2 +-
 vscode-web/fw-fs/extension.js |  3 ++-
 vscode-web/index.html         | 19 +++++++++++++++----
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index fb41bb8..ca15ad8 100644
--- a/README.md
+++ b/README.md
@@ -252,7 +252,7 @@ Without runner screenshots, the images in a public repo's `screenshots/` folder
 ## VS Code in the browser
 
 `apps.fuzzyworld.net/vscode/?repo=<name>` (and `&branch=<branch>` for an unmerged branch) opens a public repo in
-VS Code, linked from each summary page. It is the open-source VS Code web build (the `vscode-web` npm package,
+VS Code (add `&file=<path>` to open a file, `&file=<path>:<line>` to jump to a line), linked from each summary page. It is the open-source VS Code web build (the `vscode-web` npm package,
 1.91.1, MIT) plus `vscode-web/fw-fs/`, an extension that reads `files.json` and `objects/<sha>` from
 code.fuzzyworld.net. Everything is static files; nothing can be changed (clone to edit). Quick open (Ctrl/Cmd+P)
 and search across files work; search reads text files up to 256 KB. Not yet: Markdown preview and other webviews
diff --git a/vscode-web/fw-fs/extension.js b/vscode-web/fw-fs/extension.js
index 9b853ac..0442d2f 100644
--- a/vscode-web/fw-fs/extension.js
+++ b/vscode-web/fw-fs/extension.js
@@ -173,7 +173,8 @@ exports.activate = function (context) {
 // domain per view, which this static site doesn't have yet; so it isn't opened by default.)
 async function openReadme() {
   const folder = vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders[0];
-  if (!folder || folder.uri.scheme !== "fuzzyworld" || vscode.window.visibleTextEditors.length) return;
+  // index.html adds a query to the folder when the address has &file=: that file is opened instead.
+  if (!folder || folder.uri.scheme !== "fuzzyworld" || folder.uri.query || vscode.window.visibleTextEditors.length) return;
   try {
     const m = await manifest(folder.uri);
     const readme = [...m.dirs.get("").keys()].find((n) => /^readme(\.md|\.markdown|\.txt)?$/i.test(n));
diff --git a/vscode-web/index.html b/vscode-web/index.html
index 53dbd31..808c7e4 100644
--- a/vscode-web/index.html
+++ b/vscode-web/index.html
@@ -1,5 +1,5 @@
 <!doctype html>
-<!-- VS Code in the browser for code.fuzzyworld.net: apps.fuzzyworld.net/vscode/?repo=<name>[&branch=<branch>].
+<!-- VS Code in the browser for code.fuzzyworld.net: apps.fuzzyworld.net/vscode/?repo=<name>[&branch=<branch>][&file=<path>[:<line>]].
      Installed by vscode-web/install.sh, beside dist/ (the vscode-web build) and fw-fs/ (our read-only file system). -->
 <html lang="en">
 <head>
@@ -16,13 +16,18 @@
 </head>
 <body aria-label="">
 <script>
-  // Which repository: ?repo=<name>, optionally &branch=<branch> (the default branch otherwise).
+  // Which repository: ?repo=<name>, optionally &branch=<branch> (the default branch otherwise),
+  // and &file=<path>[:<line>] to open a file (and jump to a line) at startup.
   (function () {
     var q = new URLSearchParams(location.search);
     var repo = q.get("repo") || "", branch = q.get("branch") || "";
     var okName = /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(repo);
+    var file = q.get("file") || "", line = 0;
+    var lm = /:(\d+)$/.exec(file);
+    if (lm) { line = +lm[1]; file = file.slice(0, lm.index); }
+    var okFile = !file || !(/^\/|\/$|\\|[\x00-\x1f]/.test(file) || file.split("/").some(function (s) { return s === "" || s === "." || s === ".."; }));
     var okBranch = !branch || (!/[\s~^:?*\[\\@]|\.\.|\/\/|^\/|\/$/.test(branch));
-    if (!okName || !okBranch) {
+    if (!okName || !okBranch || !okFile) {
       document.body.innerHTML = '<div class="fw-missing"><h1>Which repository?</h1><p>Open a repository from its page on ' +
         '<a href="https://code.fuzzyworld.net/">code.fuzzyworld.net</a> ("Open in VS Code in the browser"), or add ' +
         '<code>?repo=&lt;name&gt;</code> to this address.</p></div>';
@@ -42,7 +47,13 @@
         // Webviews (e.g. Markdown preview) load from this site, not from Microsoft's CDN.
         webviewContentExternalBaseUrlTemplate: new URL("dist/out/vs/workbench/contrib/webview/browser/pre/", app).href,
       },
-      folderUri: { scheme: "fuzzyworld", path: "/" + repo + (branch ? "@" + branch : "") },
+      // The query marks a visit with &file=: fw-fs then leaves the README closed. File systems read only the path.
+      folderUri: { scheme: "fuzzyworld", path: "/" + repo + (branch ? "@" + branch : ""), query: file ? "file" : "" },
+      // force: open the file on every visit, not only the first one to this workspace.
+      defaultLayout: file ? { force: true, editors: [{
+        uri: { scheme: "fuzzyworld", path: "/" + repo + (branch ? "@" + branch : "") + "/" + file, query: "file" },
+        options: line ? { selection: { startLineNumber: line, startColumn: 1 } } : undefined,
+      }] } : undefined,
       additionalBuiltinExtensions: [{ scheme: app.protocol.slice(0, -1), authority: app.host, path: app.pathname + "fw-fs" }],
     };
   })();