Documentation

Everything needed to install it, embed it, or teach it a new language.

Install

The IDE and engine

pip install nishachar-ide

Requires Python 3.10 or newer. This gives you the nishachar command, the HTTP API, and the Python library.

The embeddable component

npm install @nishachar/ide

Or skip the install entirely and use a CDN:

<script type="module" src="https://cdn.jsdelivr.net/npm/@nishachar/ide"></script>

Container

docker run --rm -p 8777:8777 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/ni-sh-a-char/nishachar-ide:2.0.0 --runner docker --host 0.0.0.0

Mounting the Docker socket lets the server start a sandboxed container per language. Without it you still get the API and IDE, limited to the toolchains inside the image.

Quick start

nishachar                       # the IDE, in your browser
nishachar run hello.she         # language inferred from the extension
nishachar run -l rust -c 'fn main(){println!("hi")}'
nishachar languages             # what exists, and what you have installed

CLI reference

nishachar

With no arguments, starts the server and opens the IDE in your browser — the Jupyter model. There is no Electron download.

nishachar run

nishachar run FILE                 # infer language from extension
nishachar run FILE -l python       # force a language
nishachar run -l py -c 'print(1)'   # run a snippet
echo 'print(1)' | nishachar run -l py -   # read stdin
FlagMeaning
-l, --languageLanguage id, alias or extension.
-c, --codeRun this snippet instead of a file.
--runnerauto (default), local or docker.
--timeoutSeconds before the process tree is killed. Default 10.
-v, --verboseReport the language, backend and timing to stderr.

The exit code is the program's own exit code, so it composes with shell scripts and CI.

nishachar languages

Lists every registered language. A * marks the ones your machine can run right now. --available shows only those.

nishachar serve

The API without opening a browser.

FlagDefaultMeaning
--host127.0.0.1Bind address.
--port8777Port.
--runnerautoExecution backend.
--corsclosedAllow embedding from this origin. Repeatable.
--allow-shelloffEnable the terminal endpoint.
--allowed-hostloopbackExtra acceptable Host value. Repeatable.
--allow-remote-execoffPermit the unsandboxed runner off loopback.

Component API

<nishachar-ide> is a native custom element. It needs no framework wrapper because custom elements are part of the platform.

Attributes

AttributeValuesMeaning
languageid · alias · extensionStarting language. Default python.
codesource textInitial buffer. Inline text content also works.
themedark · lightFollows the OS when unset.
endpointURLBackend to run against. Omit for in-browser.
runtimeauto · browser · remoteDefault auto.
readonlypresentEditor is not editable.
stdinpresentShow the standard-input tab.
layoutsplit · stackedDefaults to width-based.
timeoutmillisecondsPer-run limit.

Properties, methods and events

const ide = document.querySelector('nishachar-ide');

ide.value    = 'print("hello")';   // read/write the buffer
ide.language = 'python';
ide.stdin    = 'piped input';
await ide.run();                    // resolves with the result object
ide.focus();

ide.addEventListener('ready',  e => e.detail.languages);
ide.addEventListener('change', e => e.detail.code);
ide.addEventListener('run',    e => e.detail.language);
ide.addEventListener('result', e => e.detail.stdout);

Press Ctrl/Cmd + Enter in the editor to run.

Theming

nishachar-ide {
  --nsc-accent: #ff4f81;
  --nsc-bg: #000;
  --nsc-mono: 'JetBrains Mono', monospace;
  --nsc-radius: 4px;
  height: 600px;
}
nishachar-ide::part(toolbar) { border-bottom: 2px solid var(--nsc-accent); }

Exposed parts: toolbar, editor, output, run-button.

Which languages run without a backend? Python, SHE and JavaScript. The language dropdown groups the rest under “Needs a backend”, so users are never left guessing.

Python library

import nishachar

result = nishachar.run('say "hello"', "she")
result.stdout       # 'hello\n'
result.exit_code    # 0
result.duration_ms  # 158
result.ok           # True
result.timed_out    # False
result.truncated    # False

nishachar.run_file("script.rs", runner="docker", timeout=30)
nishachar.languages()        # every Language in the registry
nishachar.registry.require("go")

HTTP API

EndpointReturns
GET /api/healthVersion, active runner, language count, whether the shell is on.
GET /api/languagesEvery language, each flagged with localToolchain.
POST /api/runExecutes and returns the result.
WS /api/ptyInteractive terminal. Requires --allow-shell.
curl -X POST http://localhost:8777/api/run \
  -H 'content-type: application/json' \
  -d '{"language":"she","code":"say \"hi\"","stdin":"","timeout":10}'

{"stdout":"hi\n","stderr":"","exitCode":0,"durationMs":158,
 "timedOut":false,"truncated":false,"runner":"local","language":"she","ok":true}
StatusMeaning
400Malformed body, or a field of the wrong type.
404Unknown language.
413Source larger than 1 MiB.
421Host header not accepted — see Security.
422No backend could run that language.

Language registry

Every language is one JSON file. Adding one requires no source changes.

{
  "id": "ruby",
  "name": "Ruby",
  "extensions": [".rb"],
  "image": "ruby:3.3-slim",
  "run": ["ruby", "{file}"],
  "template": "puts \"Hello from Ruby!\"\n"
}
PlaceholderBecomes
{file}Full path to the source file.
{bin}Path the compiled binary should be written to.
{dir}The working directory.
{stem}Filename without its extension.

Placeholders substitute inside an argument, so "-o{bin}" works. Commands are argument vectors, never shell strings — nothing reaches a shell, so there is no quoting to get right and nothing to inject.

Full field reference and contribution guide →

Execution tiers

TierWhereLanguagesIsolation
browserthe visitor's tabPython, SHE, JSthe browser sandbox
localyour machinewhatever is installednone — runs as you
dockera containerall 62strong

auto resolves per language: your local toolchain if you have it, a container if you don't. That is what lets Rust run on a machine with only Python installed.

Security

The local tier has no isolation. It runs code as you, with your privileges. That is correct for code you wrote and wrong for anyone else's. Use --runner docker for input you do not trust.

Server defaults are deliberately restrictive:

Full threat model, including what it does not protect against →

Self-hosting

Serving this to people you do not trust:

nishachar serve \
  --host 0.0.0.0 \
  --runner docker \          # never 'local'
  --timeout 10 \
  --cors https://your-site.example

Leave the terminal off, put it behind a reverse proxy with rate limiting, and run the whole thing inside a VM. Containers share a kernel; they are a strong boundary, not an absolute one.

Troubleshooting

X is not installed or not on PATH”

The local toolchain is missing. Install it, or run with --runner docker to use a container instead.

The nishachar command isn't found after install

pip installed it somewhere off your PATH. python -m nishachar works identically, or add the reported scripts directory to PATH.

The first in-browser run is slow

Expected. Pyodide is a full CPython build and takes roughly three seconds to download and start. It is cached afterwards, and SHE adds about two more seconds the first time while micropip fetches it from PyPI.

The embedded component won't reach my server

CORS is closed by default. Start the server with --cors https://your-site.example.

The terminal shows no colours on Windows

ConPTY needs the optional dependency: pip install "nishachar-ide[pty]". Without it the terminal falls back to pipes, which run commands but have no TTY.