JSCR — JavaScript AI-Powered Code Runner
Live inline JavaScript & TypeScript execution inside VS Code.
Type code, see results — no button presses, no terminal switching, no context loss.
Enjoying JSCR? Buy me a coffee — it keeps the updates coming.
Why JSCR
📚 Complete Feature Reference → docs/FEATURES.md — every feature, with its access path, target, how-to, per-language reach, pros and limits.
- Live inline evaluation — every top-level expression is reported next to its line, in real time.
- File Mode — runs the active
.js / .ts file against your workspace's node_modules. No config.
- Scratch Mode — persistent scratchpad snippets that survive restarts, kept in
~/.jscr/snippets/.
- Dormant when off — zero background processes when the panel is closed.
- AI-assisted fixes — send a runtime error + code to OpenRouter and preview a two-column diff before accepting.
- Theme-native output — panel colors are pulled from your active VS Code color theme, not hardcoded.
- Polyglot — first-class Python, Java, Go, Rust, C#, C++, Ruby and Groovy alongside JS/TS, each running live.
- Multi-file snippets — give a snippet companion files it can import, in all twelve languages. See Multi-file snippets.
- Rich output —
jscr.table() / .chart() / .image() / .html() render instead of print. See Rich output.
- Run in Terminal — an interactive escape hatch with live stdin, for menus and prompt loops. See Run in Terminal.
Polyglot: Python, Java, Go, Rust, C#, C++, Ruby & Groovy
JSCR also runs Python, Java, Go, Rust, C#, C++, Ruby and Groovy snippets live, streaming their output into the same panel. Each language's toolchain is auto-detected on startup (results are cached, so subsequent launches are instant); a language only appears in the New Snippet menu when a supported toolchain is found.
| Language |
Minimum version |
Package install |
Run mode |
Live debounce |
Notes |
| JavaScript |
Node 17+ |
✅ npm |
live |
300 ms |
In-process V8 vm, line-anchored value inspector |
| TypeScript |
TypeScript 3.8+ (Node 17+) |
✅ npm |
live |
300 ms |
Transpiled, then run in the in-process V8 vm; line-anchored value inspector |
| Python |
3.7 |
✅ pip |
live |
1 s |
Runs the file in place: python <file> |
| Ruby |
2.5.1 |
✅ gem |
live |
1 s |
Runs the file in place: ruby <file> |
| Groovy |
2.5 |
✅ Grape (@Grab) |
live |
1.5 s |
Slightly higher debounce to absorb JVM startup |
| Go |
1.11 |
✅ go modules |
live (compiled) |
2.5 s |
Modules build; the go.mod target tracks your detected Go version, so modern features (generics, etc.) compile |
| Java |
11 |
✅ Coursier (Maven) |
live (compiled) |
2.5 s |
Single-file source launcher (JEP 330) — no javac step, no .class files; deps resolved into ~/.jscr/java/lib |
| Rust |
1.39 |
✅ cargo (crates) |
live (compiled) |
3.5 s |
Generous debounce because rustc + LLVM is the slowest compile |
| C# |
.NET SDK 6 |
✅ NuGet |
live (compiled) |
2.5 s |
Scaffolds a throwaway .csproj + Program.cs, then dotnet run |
| C++ |
14 |
✅ header-only catalog |
live (compiled) |
1.5 s |
Compiles with g++ / clang++ to a temp binary, then runs it; libraries resolve from ~/.jscr/cpp/include |
- Package install? ✅ means JSCR can fetch a missing third-party dependency for that language on demand (into an isolated
~/.jscr store) — see Missing packages, installed on demand. All twelve languages are covered; C++ is limited to header-only libraries, since anything needing compiled binaries + linker flags has no place in a single-file model.
- Below the minimum? If a detected toolchain is older than the minimum, that language is treated as unavailable — running such a snippet shows a clear "version too old" message (just like an unsupported Node version) while every other language keeps working.
- Compiled languages run live too — Go, Java, Rust, C# and C++ re-compile+run on an idle debounce (never mid-keystroke). Turn this off per language with
jscr.<lang>.liveMode (e.g. jscr.rust.liveMode) to run them only on demand.
- Timeouts — native runs get a longer default (
jscr.process.timeoutMs, 45 s) than the in-vm JS engine, and the whole process tree is force-killed (SIGTERM → SIGKILL) on timeout so worker threads never linger.
Missing packages, installed on demand
When a run fails on a missing third-party dependency, JSCR surfaces an inline "install?" banner in the panel. Accept it and JSCR fetches just that package into an isolated store under ~/.jscr (never your system packages), then re-runs — so if more are missing, the next one surfaces, one at a time. Supported per language:
| Ecosystem |
Languages |
How |
| npm |
JavaScript / TypeScript |
into ~/.jscr/node_modules |
| pip |
Python |
--target ~/.jscr/py/site-packages |
| gem |
Ruby |
--install-dir ~/.jscr/ruby/gems |
| modules |
Go |
go mod tidy |
| crates |
Rust |
cargo add (converts the snippet to a Cargo project) |
| NuGet |
C# |
dotnet add package into the snippet's scaffolded project |
| Grape |
Groovy |
resolves a Maven group:artifact:version (with transitive deps) into ~/.jscr/groovy/lib |
| Coursier |
Java |
resolves a Maven group:artifact:version (with transitive deps) into ~/.jscr/java/lib |
| header catalog |
C++ |
fetches a header-only library from its own release into ~/.jscr/cpp/include |
An import has no deterministic Maven coordinate, so Java and Groovy resolve it automatically — one Install click maps the failing import to a coordinate (a curated map of common libraries, then a Maven Central class search), no prompt. Java fetches via Coursier (run with the JDK you already have, or a cs/coursier on PATH — jscr.java.coursierPath to override); Groovy via Grape. C# maps a CS0246 error's using namespace straight to the NuGet id.
C++ has no package manager bundled with g++/clang++, so JSCR fetches the library itself — a curated catalog of header-only libraries (nlohmann/json, {fmt}, spdlog, Eigen, GLM, EnTT, Asio, doctest, Catch2, cpp-httplib, cereal, magic_enum, nameof, cxxopts, CLI11, argparse, toml++, range-v3, date, GSL, tl::expected, nanoflann, unordered_dense, ConcurrentQueue, tabulate and utfcpp) downloaded from each project's own release into ~/.jscr/cpp/include, which is already on every compile's -I. A fatal error: nlohmann/json.hpp: No such file is matched to its library and one Install click resolves it; any flags that library needs (-DFMT_HEADER_ONLY, the winsock/pthread libs for cpp-httplib) are recorded at install time and applied to later compiles, so the snippet declares nothing. Libraries that need compiled binaries and per-library linker flags (OpenCV, Qt, Boost) are explained rather than half-installed — that is the honest edge of a single-file model — and you can still drop any header-only library into that folder yourself.
Version selector. Every install banner has an editable Version box, defaulting to latest — click Install to take the newest, or type a version to pin it (e.g. okhttp's 5.x main jar is a thin aggregator that won't compile, so pin 4.12.0). It threads through each ecosystem (name==ver for pip, name@ver for npm/cargo, -v ver for gem/NuGet, the coordinate version for Maven/Coursier). Dismiss re-runs the snippet so the panel refreshes after you resolve a dependency by hand.
Install Troubleshooter. When an install fails, every banner shows a Troubleshoot button (left of Dismiss/Install). It runs a safe, diagnostic-first sequence — is the package manager present? is the ~/.jscr store writable? is the registry reachable? — then a clean reinstall, classifies the failure into a likely cause (deprecated / moved / removed / renamed, version conflict, corrupt download, native-build needs a compiler, permissions), and shows the exact manual command. For Java/Groovy it adds a last-resort direct jar download from Maven Central straight into the classpath overlay (the "curl -O into lib"). The report stays on screen until you Dismiss or Retry (with a version box), so you can read every check — every remedy stays inside JSCR's own store, and a Copy diagnostics button copies the full report.
While a package is fetched — or a compiled language is building, or Groovy is resolving @Grab — the panel shows a status line (Groovy lists the exact @Grab coordinates it's downloading) so a slow first run never sits blank with no explanation.
Declaring packages inline (C# & Groovy). Instead of the banner you can pin dependencies in the snippet itself, and JSCR runs it as-is:
- C# —
#r "nuget: Newtonsoft.Json, 13.0.3" (or .NET 10's #:package Newtonsoft.Json@13.0.3). JSCR lifts these into the project's <PackageReference>s. Script-style layout (top-level statements after class/record declarations) is auto-normalized so it compiles as a program, with your statement line numbers preserved.
- Groovy — the native
@Grab('group:artifact:version') annotation, resolved into ~/.jscr/groovy/grape.
For interactive-looking programs — Java Scanner, Python input(), Go fmt.Scan — the panel has a Program Input box (toggle it from the header's terminal-prompt icon). Type the input your program reads ahead of time, one value per line, with one-click Paste and Clear:
Alice
30
On each run JSCR feeds that into the program's stdin and then closes it. So a read past what you supplied instantly hits end-of-input (Java NoSuchElementException, Python EOFError, Go io.EOF) with a red squiggle on that line — the re-run never hangs waiting for a human. Fill the box → every line runs each cycle. Leave it short → it fails fast at the first unsatisfied read. Input is remembered per snippet.
Run in Terminal (interactive)
Pre-supplied stdin is the right default for a live re-run, but it can't serve a genuinely interactive program — a menu loop, a REPL-ish prompt, a readline conversation. For those, right-click → JSCR: Run in Terminal (Interactive).
It runs the same snippet in a real VS Code terminal — a PTY — so stdin is live and you just type. It reuses each language's normal prepare(), so compilation, classpaths, package stores, env vars and multi-file companions behave exactly as in a panel run. JS/TS are transpiled plainly and handed to real node (the in-process vm engine has no PTY). Output is un-instrumented: no line-tagging sentinels reach the terminal, and jscr.* calls degrade to readable text instead of rendering.
Multi-file snippets (companion files)
A snippet can own companion files it imports — in all twelve languages. You write ordinary code; JSCR uses each language's own resolution:
|
|
| Python / Ruby / Lua |
import helpers · require_relative "helper" · require("helper") |
| Go / Rust / C# |
same-package files · mod helpers; · project globbing |
| C++ / Groovy / Elixir |
#include "helpers.h" + extra translation units · classpath · -r |
| Java |
switches to a real javac compile (the JEP-330 single-file launcher can't see siblings) |
| JS / TS |
an in-vm CommonJS loader — TypeScript companions transpile automatically |
Manage them from the JSCR Snippets tree: right-click a snippet → Add Companion File…, or drag a snippet onto another to make it a companion (and drag it back out to make it standalone). Companions appear as children with a +N badge, and editing one live re-runs its entry.
Full details: docs/MULTI_FILE.md.
Rich output (render instead of print)
Call the ambient jscr API — no import, just like console — and the panel renders a block instead of printing text:
jscr.table([{ lang: 'JS', runs: 2 }, { lang: 'Go', runs: 5 }]); // columns inferred
jscr.chart({ type: 'bar', series: [{ name: 'runs', values: [12, 3] }], labels: ['Py', 'Rust'] });
jscr.image('data:image/png;base64,…');
jscr.html('<b>hi</b>');
jscr.table(df) # a pandas DataFrame — duck-typed; pandas is never imported
jscr.chart({"type": "bar", "series": [{"values": [12, 3]}], "labels": ["a", "b"]})
- Tables scroll, right-align numbers, and cap at 500 rows (the caption shows the true total).
- Charts are bar, line, scatter, area, pie and donut, drawn as inline SVG using your VS Code theme's chart colours — no charting library is bundled. Pass a
{label: value} dict straight in as a series and the keys become labels.
- HTML renders in a sandboxed iframe, never the panel's own DOM.
- Blocks sit in the same line-anchored grid as ordinary output. A bad emit never breaks a run — it falls back to plain text.
Available in JavaScript, TypeScript and Python today. Full contract: docs/RICH_OUTPUT.md.
Live Web — render a webpage, not a console
Rich output renders blocks. Live Web renders the whole page. Open a React
component, a Svelte file, a Vue SFC, some jQuery, or an HTML file, and the panel
renders it live as you type — the same tab, showing a page instead of a
console:
import { useState } from 'react';
import { createRoot } from 'react-dom/client';
function Counter() {
const [n, setN] = useState(0);
return <button onClick={() => setN(n + 1)}>clicked {n}</button>;
}
createRoot(document.getElementById('root')).render(<Counter />);
| Renders today |
Needs installed |
| HTML · plain DOM JS/TS |
— |
React (.jsx/.tsx) · Preact · Solid |
react+react-dom / preact / solid-js |
Svelte (.svelte) |
svelte |
Vue (.vue SFC, or the JS API) |
vue, @vue/compiler-sfc |
| Lit · jQuery |
lit / jquery |
| Angular (standalone, via JIT) |
@angular/core+common+platform-browser+compiler, rxjs, zone.js |
- Nothing is bundled into JSCR. Frameworks and their compilers resolve from
your own store (
~/.jscr/node_modules) — so JSCR: Install Package is all it
takes, and a framework JSCR has never heard of works if esbuild can bundle it.
Adding one to the registry is a table row, not a code change.
- Auto-detect (
jscr.liveWeb.autoDetect) shows web source as a page without
being asked. It's conservative: framework-free JS only counts if it touches the
DOM, so a console snippet is never hijacked.
- One tab, two modes — toggling swaps the panel's document, it never opens a
second pane. The mode belongs to the snippet, so switching files switches
the panel with you.
- Toggle from the panel header — a globe button in the Live Output header
renders the current file as a webpage; the Live Web view has its own header
with a button back. Your choice sticks per snippet, outranking auto-detect.
- A component just works — a file that only does
export default Counter
gets mounted for you, rather than building fine and rendering a blank page.
- Errors are never silent: build errors, missing packages, and runtime
errors (a page that dies on load) all surface in the pane itself.
Ember is explained rather than rendered — it builds through ember-cli over an app
directory, so there's no single-file entry. Full contract:
docs/LIVE_WEB.md.
Requirements
- VS Code 1.85+
- Node.js v17+ (recommended v22 LTS for full ES2023 support)
- Optional, only for their languages: Python 3.7+, Java (JDK) 11+, Go 1.11+ on your
PATH (or point JSCR at them with jscr.python.path / jscr.java.path / jscr.go.path).
Install
Marketplace (recommended):
Extensions view → search JSCR → Install.
From a local .vsix:
code --install-extension jscr-<version>.vsix
Build a local .vsix yourself with npm run package — see docs/LOCAL_BUILD_AND_USE.md.
Quick start
- Press Ctrl+Shift+J (macOS: Cmd+Shift+J) to open the JSCR panel.
- Open any
.js or .ts file — or press Ctrl+Shift+N to create a Scratch snippet.
- Type. Each 300 ms of idle triggers a run.
- Per-line results appear inline in the panel:
L 3 const total = 42 → 42
L 4 users.map(u => u.name) → ['ada', 'grace', 'linus']
L 5 console.log('hi', 3) → hi 3
Commands
| Command |
Default keybind |
| JSCR: Toggle Panel |
Ctrl+Shift+J / Cmd+Shift+J |
| JSCR: New Scratch Snippet (JavaScript) |
Ctrl+Shift+N / Cmd+Shift+N |
| JSCR: New Scratch Snippet (TypeScript) |
— |
| JSCR: New Scratch Snippet (Python / Java / Go) |
— (shown when the toolchain is detected) |
| JSCR: Run Snippet |
Ctrl+Shift+Enter / Cmd+Shift+Enter |
| JSCR: Run in Terminal (Interactive) |
— |
| JSCR: Refresh Language Environments |
— |
| JSCR: Run Current File |
— |
| JSCR: Add Companion File… |
— (right-click a snippet) |
| JSCR: Move to Snippet as Companion… |
— (right-click a snippet) |
| JSCR: Convert Companion to Snippet |
— (right-click a companion) |
| JSCR: Show Live Output |
— |
| JSCR: Render as Webpage (Live Web) |
— (toggle on a web snippet in JSCR Snippets) |
| JSCR: Show Console Output (Live Output) |
— (toggle back from a rendered page) |
| JSCR: Install Package |
— |
| JSCR: Switch Package Source |
— |
| JSCR: Benchmark (run N times) |
— (no AI key needed) |
| JSCR: Compare… |
— (no AI key needed) |
| JSCR: Snapshot History… |
— (no AI key needed) |
| JSCR: Save Snapshot… |
— (right-click a snippet) |
| JSCR: Snippet Environment… |
— (env vars + OS-keychain secrets) |
| JSCR: New Snippet from Template… |
— (4 tasks × 12 languages) |
| JSCR: Add Shared Workspace… |
— (a folder your team syncs) |
| JSCR: Share to Workspace… / Copy to My Snippets |
— (right-click a snippet) |
| JSCR: Learn |
— (hub: courses, challenges, streak) |
| JSCR: Start a Course… |
— (guided practice tracks) |
| JSCR: Daily Challenge / Challenge Calendar… |
— (no AI key needed) |
| JSCR: Check Challenge Solution |
— (grades against real test cases) |
| JSCR: Search Snippets |
— (🔍 in the JSCR Snippets title bar) |
| JSCR: Filter Snippets… |
— (funnel in the JSCR Snippets title bar) |
| JSCR: New Folder |
— (right-click a scope or folder) |
| JSCR: Move to Folder… / Edit Tags… / Toggle Favorite |
— (right-click a snippet) |
| JSCR: Fix with AI |
Ctrl+Shift+A / Cmd+Shift+A |
| JSCR: Switch AI Model (OpenRouter) |
Ctrl+Shift+Alt+A / Cmd+Shift+Alt+A |
| JSCR: Save Snippet to Project |
— |
| JSCR: Move Snippet to Global |
— |
| JSCR: Delete Snippet |
— |
| JSCR: Clear All Snippets (Global) |
— |
| JSCR: Clear All Snippets (This Project) |
— (shown when a workspace is open) |
| JSCR: Toggle Snippet Language (JS ↔ TS) |
— |
All commands are available from the Command Palette — press Ctrl+Shift+P (macOS: Cmd+Shift+P) and type JSCR.
In the editor's right-click menu, JSCR takes up one row: a JSCR submenu holding Run in Terminal, the free tools (Benchmark / Compare / Snapshots), Practice with AI, and an AI Assist sub-branch with the 16 AI commands. One row, so your own menu items stay where you expect them. The AI branch disappears when JSCR Assist is off.
Configuration
Search jscr in Settings, or edit .vscode/settings.json:
| Setting |
Default |
What it controls |
jscr.debounceMs |
300 |
Wait this long after a keystroke before running (JS/TS). |
jscr.executionTimeoutMs |
20000 |
Hard timeout for JS/TS — user code is killed after this many ms. |
jscr.process.timeoutMs |
45000 |
Hard timeout for spawned-process languages (Python/Java/Go/Rust/C#/C++/Ruby). The process tree is force-killed on timeout. |
jscr.python.path |
"" |
Override the Python interpreter path. Empty = auto-detect (py / python3 / python). |
jscr.java.path |
"" |
Override the Java (JDK 11+) launcher path. Empty = auto-detect. |
jscr.go.path |
"" |
Override the Go toolchain path. Empty = auto-detect. |
jscr.rust.path |
"" |
Override the Rust (rustc 1.39+) path. Empty = auto-detect. |
jscr.csharp.path |
"" |
Override the .NET SDK (dotnet) path. Empty = auto-detect. |
jscr.cpp.path |
"" |
Override the C++ compiler (g++ / clang++) path. Empty = auto-detect. |
jscr.ruby.path |
"" |
Override the Ruby (ruby 2.5.1+) path. Empty = auto-detect. |
jscr.<lang>.debounceMs |
per-language |
Live re-run/re-compile debounce. Defaults: Python/Ruby 1000, C++ 1500, Go/Java/C# 2500, Rust 3500. |
jscr.<lang>.liveMode |
true |
Re-run compiled langs (Go/Java/Rust/C#/C++) live as you type. Off = run on demand only. |
jscr.liveWeb.autoDetect |
true |
Render web source (HTML, JSX/TSX, Vue, Svelte, or JS that touches the DOM) in JSCR — Live Web instead of the console. The panel-header toggle always wins over this, per snippet. |
jscr.benchmark.runs |
10 |
How many timed runs JSCR: Benchmark takes. No AI key needed. |
jscr.benchmark.warmup |
1 |
Runs executed but excluded from the stats (skips JIT / cold-cache warmup). 0 measures cold starts. |
jscr.benchmark.measureMemory |
true |
Sample peak memory on one dedicated extra run, so timings are never perturbed. |
jscr.versions.keep |
30 |
Automatic snapshots kept per snippet. Snapshots you name yourself are never auto-evicted. |
jscr.openRouterApiKey |
"" |
Required for Fix with AI. Get one at openrouter.ai. |
jscr.openRouterModel |
cohere/north-mini-code:free |
Any OpenRouter model ID. Change it with JSCR: Switch AI Model. |
jscr.aiRequestTimeoutMs |
30000 |
AI request timeout. |
jscr.output.tokenColors |
{} |
Optional per-token color overrides (string, number, keyword, property). Empty = inherit from theme. |
Five features that need no OpenRouter key, spend nothing, and keep working
with JSCR Assist switched off. They're the plain answers to questions you
shouldn't need a language model for. Full details in docs/TOOLS.md.
Benchmark — JSCR: Benchmark (run N times)
Runs your snippet N times and reports the real distribution — min / median /
p95 / max / std dev / peak memory — plus a sparkline, one bar per run, so an
outlier is visible at a glance.
Three things make it honest: warmup runs are discarded (a JVM's first run
pays JIT costs you only pay once), compiled languages compile once and re-spawn
per sample (so you measure run time, not ten compiles), and p95 is
nearest-rank — an actually-observed slow run, never an interpolation of one
that never happened. If run-to-run variance is high enough that small differences
are just noise, it says so.
Peak memory is measured on a dedicated extra run, so sampling never perturbs the
timings. It's exact for JS/TS and on Linux; on Windows a tasklist probe costs
~300 ms, so snippets faster than that report "too fast" with the reason
rather than a misleading dash.
This is the free counterpart to Performance A/B Lab. Benchmark measures
what you already wrote; A/B asks a model for a faster version. Use Benchmark
constantly, A/B when you want a suggestion.
Find in output — Ctrl+F in the panel
The moment a run prints more than a screenful you need to search it. The find
bar highlights matches with a live "3 of 17" counter, and adds three more
controls: Filter (hide everything that doesn't match), Hide lines
matching… (drop the noise), and Collapse repeats (fold identical
consecutive lines into one row with a ×N badge). Case and regex toggles
included.
Copy and Save run as… always export the complete output — what you filtered
on screen never silently changes what you share.
Compare — JSCR: Compare…
A plain side-by-side diff, four ways: the last two runs, this run vs. any
earlier one, two snippets' source, or run both snippets and diff what
they actually printed — which works across languages. "Is my Rust port of
this Python function equivalent?" gets answered by execution, not by asking a
model to judge.
Run-vs-run mode also tells you whether the code changed between the two runs. If
it didn't, any output difference is nondeterminism.
A flat tree stops being navigable around a hundred snippets. So:
- Search (🔍 in the JSCR Snippets title bar) matches name, language, folder,
tags and file content — because "where did I write that binary search?" is
the question people actually have.
- Filter narrows the tree itself and stays until cleared.
- Folders nest up to 8 deep. Create them, rename them, drag snippets onto
them. Removing a folder never deletes snippets — everything inside moves up
a level.
- Tags and a ★ Favorites group, both shown in the tree and both
searchable.
Folders are virtual — your snippet files never move on disk. JSCR's on-disk
layout is load-bearing for twelve language toolchains, so organization lives in
a sidecar index instead. If that index is ever lost, every snippet simply shows
at its scope root: still runnable, nothing deleted.
Snapshots & restore — JSCR: Snapshot History…
JSCR snapshots a snippet's code after every run, deduplicated by content hash
so unchanged re-runs cost nothing. Browse past versions, diff one against the
current file, and restore it.
Restore is itself undoable — the current content is snapshotted first, so a
mistaken restore is recoverable from the same list you just came from. You can
also save a named snapshot deliberately ("before rewriting the parser"); those
are never auto-evicted by retention.
Snapshots are plain files with your snippet's own extension under
~/.jscr/.versions/, readable with ordinary tooling.
Per-snippet env vars & secrets — JSCR: Snippet Environment…
A snippet that calls a real API needs a key, and the only place to put one used
to be inside the snippet — exactly where it must not be, since that file gets
exported, snapshotted, shared and pasted into issues.
Ordinary values live in a per-snippet .env file you can open and edit. Secret
values go to your OS keychain, and the file keeps only a placeholder:
API_BASE=https://api.example.com
OPENAI_KEY=<jscr:secret>
So nothing that copies a snippet can carry the credential — because the
credential isn't in the file. That's a property of the layout, not a rule to
remember. Deleting the snippet purges its keychain entries too.
Every snippet has its own .env — a "This Project" and an "All Global"
snippet get separate, independent files, never a shared one — and the file opens
with commented examples you can uncomment and edit.
The environment reaches every way you run: the live panel (both engines), Run in
Terminal, and Benchmark/Compare — read it with process.env, os.environ,
System.getenv, ENV, os.Getenv, whatever your language uses. All twelve
languages, verified end-to-end.
Starter templates — JSCR: New Snippet from Template…
New snippets opened blank, which is unhelpful in a language you don't write
daily — and JSCR runs twelve. Four tasks, each in all twelve languages:
the basics, read Program Input, parse CSV & summarize, and run work
concurrently.
Standard library only, so a fresh template runs the instant you create it — and
every one of the 48 combinations is executed against its real toolchain before
shipping. Picking the task first (then the language) is deliberate: the
interesting thing is that the same program exists in twelve languages.
Shared team workspaces — JSCR: Add Shared Workspace…
Point JSCR at a folder your team already syncs — a cloud drive, a network share,
or a git repo you manage with your own git workflow — and it becomes another root
in the JSCR Snippets tree. Snippets there run directly, no copy step. Share into
it from JSCR ▸ Share to Workspace… (editor menu), a tree right-click, or the
Command Palette — This Project and All Global snippets both.
JSCR deliberately doesn't run git for you: that would mean owning tokens, a
merge-conflict UI and offline states, all duplicating tools your team already
trusts. Delegating sync to whatever already syncs the folder works on day one.
JSCR never touches your project files. It's a companion, not part of your
repo — snippets live under ~/.jscr, never your project folder, so sharing (or
anything else JSCR does) can't modify a file you didn't create. A shared
workspace is a folder you pick; JSCR only adds snippet-* files to it.
Secrets are never shared. Environment files and snapshot history live
outside the snippet store, so copying a snippet into a shared workspace
structurally cannot carry them. Your teammate gets your code, never your keys.
Runtime-aware AI
Static editor-AI (Copilot, Cursor, …) reads your code. JSCR's AI reads your code and its actual run — real per-line values, real errors, real stdout, real timing across all ten languages — so every feature below is grounded in what your program did, not what a model guessed. Bring your own OpenRouter key (jscr.openRouterApiKey); the default free model works out of the box.
JSCR Assist — the master switch
JSCR: Assist (default ON) is the circuit breaker for every AI feature. Toggle it off and all AI is disabled and hidden from the menus, any on-screen AI card is dismissed, and native autocomplete/inline-suggestions for JSCR languages are suppressed too — one switch, nothing lingers. Toggle it from the JSCR Snippets view's sparkle icon or JSCR: Toggle Assist. There is exactly one code path to the model, so "Assist off ⇒ AI off" is a structural guarantee.
All are on every language unless noted, and each is invocable from the editor right-click menu (JSCR ▸ AI Assist) or the Command Palette.
① Understand a run
- Error Tutor —
JSCR: Explain Error (AI) — a plain-language explanation of why your code broke (teaching the misconception, never just a patch); becomes a quick code review when there's no error. When: a crash you don't understand.
- Explain This Value —
JSCR: Explain This Value (AI) — why one line produced the value it did, traced through the actual runtime values from this run. Click an inline result, or run it on the cursor line. When: an unexpected value and you want the real data-flow story.
- Semantic Output Diff —
JSCR: Explain Output Change (AI) — explains, in meaning not bytes, why the output changed between your last two runs — tying it to your edit, or flagging nondeterminism when the code is unchanged. When: "why is it printing something different now?"
- AI Program Input —
JSCR: Generate Program Input (AI) — reads what your program reads from stdin and generates a typical input plus an edge-case one, dropped straight into the Program Input box. When: a program that reads input and you don't want to hand-craft it.
② Change code — with proof
- Fix with AI —
JSCR: Fix with AI — sends your code + the captured error and previews a two-column accept/reject diff before a single character changes. When: a runtime error you want fixed reviewably.
- Performance A/B Lab —
JSCR: Performance A/B Lab (AI) — the AI proposes a faster version; JSCR runs both and shows measured timings, a behavioral-equivalence verdict (outputs actually compared), and an apply-able diff. When: "is this genuinely faster, and does it still behave the same?"
- Freeze Behavior as Tests —
JSCR: Freeze Behavior as Tests (AI) — turns the snippet's current observed output into an idiomatic test file (Jest / pytest / JUnit / go test / …). When: lock in today's behavior before a refactor.
- Self-Repairing Snippet —
JSCR: Self-Repairing Snippet (AI) — describe a goal in plain language; the AI writes it, JSCR runs it, and feeds the real error back to fix-and-retry until it runs cleanly. When: you want code that did run, not code that merely looks right.
- Verified Translation —
JSCR: Verified Translation (AI) — translate a snippet to another language, run both and diff their outputs, retrying until they match — then it's saved as a runnable snippet, so it runs immediately. When: porting logic and needing proof it's equivalent.
③ Always-on guards (also fire automatically after each run; see jscr.ai.continuousChecks)
- Intent Comments —
JSCR: Check Intent Comments (AI) — annotate a line with //? (or #? in Python/Ruby) stating what it should do — e.g. total = a + b //? should equal 42 — and JSCR compares that against the real output, flagging contradictions inline. When: encode an assumption and be told the moment reality disagrees.
- Surprise Detector —
JSCR: Detect Surprises (AI) — flags outputs you most likely didn't intend (NaN, blank-where-data-expected, a swallowed error, an off-by-one count). When: catch quiet wrongness you'd otherwise scroll right past.
- Explain Flakiness —
JSCR: Explain Flakiness (AI) — runs the snippet N times on the same input and, if results diverge, names the concrete source of nondeterminism (unseeded RNG, time, map/hash ordering, races, …). When: "sometimes it passes, sometimes it doesn't."
- Hunt Counterexample —
JSCR: Hunt Counterexample (AI) — fuzzes your stdin to find one input that breaks it (crash / exception / timeout) and loads it into Program Input so it reproduces live. When: find the edge case before your users do.
- Minimize Repro —
JSCR: Minimize Repro (AI) — shrinks a failing input to the smallest slice that still reproduces the same failure (delta debugging, real runs as the oracle), and explains why. When: a big failing input you want reduced to its essence.
④ Investigate & verify
- Hallucination-Proof API Probes —
JSCR: Probe API (AI) — writes a tiny probe that exercises a real, installed library and runs it, answering strictly from what actually happened — so it can't hallucinate an API that doesn't exist. All ten languages, including Rust, Java and C++. When: "does this method exist / what does it actually return for an empty input?"
- Execution Time-Travel + AI Blame —
JSCR: Time-Travel & AI Blame (AI) — JSCR keeps a rolling history of a snippet's past runs; step back through them, and AI Blame attributes the current result to the exact run that introduced it. When: "which change made the output flip — and when?"
⑤ Learn interactively
- Practice with AI —
JSCR: Practice with AI — turns any snippet into a per-snippet coding tutor. Right-click → Practice with AI and the Live Output panel becomes an interactive classroom: you learn where you already work, with no course site and no second tab. See the dedicated section below.
Practice with AI — the coding tutor, in depth
Right-click any file → JSCR: Practice with AI. Type any topic you want — it's not a fixed curriculum. Ask for recursion, async/await, the borrow checker, pandas joins, regex, SQL windows, or a library you installed five minutes ago.
Graded on what your code actually did. In Written Answer the AI writes a complete, runnable starter into the snippet — the problem as comments plus the language's boilerplate so it compiles as-is (Java keeps its class Main) — and drops your cursor exactly where you finish it. You write and run as usual; a floating, draggable Submit Answer button sends your code plus its real execution output to the AI. It grades what your program did, not what a model guessed it would print.
Three modes for three learning styles:
| Mode |
For |
Graded |
| Written Answer |
hands-on building |
by the AI, against your real run output |
| Multiple Choice |
fast recognition |
instantly on-device against the answer key |
| Fill in the Blanks |
recall |
instantly on-device against the answer key |
MCQ and Fill render in a swapped-in "JSCR Live Practice with AI" pane and never touch your file — only Written mode edits the editor.
Ladder up. Four difficulty levels — Easier → Medium → Hard → Complex — so one topic grows with you. Level, mode and session length persist per snippet.
Feedback you actually read. Every verdict is a 👍/👎 flash and a result banner explaining why. Advancing is manual via Next question →, so a wrong answer stays put to retry (or Skip) instead of being overwritten. A pinnable Info Pane offers a hint and the expected output when you're stuck, and a loader tells you when a question is generating or an answer is being graded.
Sessions and a scorecard. Run 2–50 questions or an endless Stream ∞. JSCR tracks passed / failed / skipped and finishes on a dashboard with your tally and passing rate, then Restart or close.
Good for: learning a new language · interview and algorithm prep · getting fluent in a library against the dependencies you really installed · teaching and self-assessment.
Questions render as formatted, syntax-highlighted code blocks in a modern bottom-drawer UI. Works across all twelve languages plus unknown file types (drill any technology as plain text), every session is isolated per snippet, and it's gated by JSCR Assist like every other AI feature. Full spec: docs/AI_FEATURES.md.
Fix with AI — step by step
Uses OpenRouter — bring your own API key.
- Get a key at openrouter.ai and paste it into
jscr.openRouterApiKey.
- Open a
.js / .ts file with a runtime error.
- Run it once so JSCR captures the error (a red squiggle marks the failing line).
- Command palette → JSCR: Fix with AI, or right-click the file → JSCR: Fix with AI.
- Review the side-by-side diff → Accept Fix or Reject.
Choosing a model
Run JSCR: Switch AI Model (OpenRouter) from the Command Palette (Ctrl+Shift+P) to:
- see the model you're currently using,
- change it by browsing OpenRouter's live catalog (free models are tagged) or entering a custom ID, and
- validate the choice — JSCR sends a tiny request with your key and confirms it works before saving.
The default cohere/north-mini-code:free works out of the box; any free-tier model is a good starting point.
Learn — build a daily coding habit
Three features that turn JSCR from a scratchpad into somewhere you come back to. All reachable from JSCR: Learn, the 🔥/🎓 status-bar item, or the Learn button in the JSCR Snippets view. Full details in docs/LEARN.md.
Streaks — 🔥 N in the status bar
A visible counter that grows each day you practice or solve a challenge, and quietly resets if you skip a day. Answering a practice question or solving a challenge counts — the point is that you showed up.
Courses — JSCR: Start a Course…
Guided practice tracks — one per language, all twelve (JavaScript Fundamentals, Python for Interviews, Learn Rust Basics, Java Essentials, C++ Foundations, C# Basics, Ruby Basics, …) — each a handful of short lessons you do a few minutes at a time. A course is a thin, curriculum front-end over Practice with AI: each lesson opens a fresh scratch snippet and runs a preset guided session, then advances to the next lesson when you finish. Like Practice, courses need your OpenRouter key and are gated by JSCR Assist.
Daily Challenges — JSCR: Daily Challenge
Today's coding problem, solved in any of the twelve languages and graded by real execution — no key, no Assist gate. A challenge is a problem plus hidden stdin/stdout test cases; write a solution that reads stdin and prints the answer, then Check Challenge Solution runs it against every case.
- "Today's" is picked deterministically by date, so everyone gets the same problem — and in December it's framed as an Advent-of-Code-style 🎄 Day N.
- Challenge Calendar browses the whole catalog with ✓ on the ones you've solved.
- On a solve, your streak advances and JSCR offers a copyable shareable card (AoC-style) to paste anywhere.
Every challenge's expected outputs are verified against real runtimes before shipping (48 test cases, all green) — a challenge can never fail you unfairly.
Share a run
The panel header has a Save run as… button (next to Copy). It exports the current snippet and its output as either:
- Markdown — a code fence + output fence, ready to paste into a GitHub issue or PR comment.
- Standalone HTML — a self-contained, theme-coloured page you can drop into a doc or chat.
One click turns "let me screenshot this" into "here's the code, here's what it prints."
Scratch snippets
Snippets are file-backed and auto-saved with a 400 ms debounce — you'll never see a "save?" prompt. They live under:
~/.jscr/snippets/global/ — shared across all workspaces.
~/.jscr/snippets/projects/<workspace>/ — scoped to a workspace.
An JSCR Snippets view appears in the Explorer once you create one:
- 📁 Save to project (global rows only) — moves the snippet into the current workspace.
- 🗑️ Delete — with confirm.
- 🔀 Toggle language — renames
.js ↔ .ts in place, ID preserved.
- Clear all — wipes global snippets (with confirm).
How it compares
|
JSCR |
RunJS |
Quokka |
| Runs inside VS Code |
✅ |
❌ (separate app) |
✅ |
| Live inline evaluation |
✅ |
✅ |
✅ (paid tier) |
| Persistent scratch snippets |
✅ |
✅ |
❌ |
Uses workspace node_modules |
✅ |
partial |
✅ |
| AI-assisted fixes (bring your own key) |
✅ |
❌ |
❌ |
| Free to use (incl. commercial) |
✅ |
❌ |
partial |
Troubleshooting
See docs/LOCAL_BUILD_AND_USE.md § 11.
Contributing
Issues and PRs at github.com/wirekind/jscr.
Support
Questions, enquiries, or need a hand? Reach Wirekind Communications LLP:
License
JSCR Freeware End-User License Agreement (EULA) — © 2026 Wirekind Communications LLP.
JSCR is free to download and use by both individuals and companies, including in commercial settings, at no cost.
You may not modify, reverse-engineer, copy/redistribute, sublicense, rent, or sell the Software.
All rights are reserved by Wirekind Communications LLP — see LICENSE for the full terms, or contact support@wirekind.com for permissions beyond this license.
Publisher
Wirekind Communications LLP — jscr.app