|
Kordex is a small JavaScript and TypeScript runtime built on top of Vix.cpp and Softadastra. It is designed for local-first, offline-ready, permission-controlled applications where JavaScript code can run close to the system while native capabilities stay explicit. |
Kordex is a JavaScript and TypeScript runtime focused on reliability, local execution, explicit permissions, and local-first application design.
It can run JavaScript and TypeScript files, resolve local imports, load JSON files, expose native standard modules, bundle scripts, and connect JavaScript code to native C++ capabilities.
Kordex is not trying to be another general-purpose Node.js clone.
Kordex is built for a different direction:
JavaScript that can keep working locally first.That means the runtime is designed around:
- local execution
- offline-ready workflows
- explicit permissions
- native modules written in C++
- durable local storage
- embeddable runtime architecture
- predictable system access
- reliability-first application foundations
Most JavaScript runtimes focus on online services, server workloads, web tooling, and package ecosystems.
Kordex starts from a different question:
What if the application must keep working even when the network is unstable or unavailable?This is where Kordex becomes different.
Kordex combines:
- QuickJS for JavaScript execution
- Vix.cpp for the C++ runtime, build, system, and developer foundation
- Softadastra for durable local-first storage, WAL, sync foundations, transport, discovery, and metadata
- Kordex Std for native standard modules
- Kordex CLI for a small developer-facing workflow
The goal is not only to execute JavaScript.
The goal is to make JavaScript useful for reliable local-first applications.
Kordex should stay:
small
modular
local-first
permission-aware
embeddable
reliable by design
easy to test
safe by defaultThe runtime should expose native capabilities only when the application explicitly asks for them.
Create main.js:
const name = "Kordex";
console.log("Hello from " + name);Run it:
kordex run main.jsOutput:
Hello from KordexKordex is built with the Vix.cpp CLI.
Install Vix.cpp first.
curl -fsSL https://vixcpp.com/install.sh | bashirm https://vixcpp.com/install.ps1 | iexVerify Vix.cpp:
vix --versionThen build Kordex:
vix build --preset dev-ninja --build-target all -v -- \
-DKORDEX_ENABLE_QUICKJS=ON \
-DKORDEX_ENABLE_NATIVE_ENGINE=OFF \
-DKORDEX_BUILD_APP=ON \
-DKORDEX_ENABLE_INSTALL=ONBuild Kordex with Softadastra support:
vix build --preset dev-ninja --build-target all -v -- \
-DKORDEX_ENABLE_QUICKJS=ON \
-DKORDEX_ENABLE_NATIVE_ENGINE=OFF \
-DKORDEX_BUILD_APP=ON \
-DKORDEX_ENABLE_INSTALL=ON \
-DKORDEX_ENABLE_STD_SOFTADASTRA=ONVerify Kordex:
kordex version
kordex helpkordex <command> [options] [args]Available commands:
help Show help
init Create a new Kordex project
run Run a JavaScript or TypeScript file
check Check a source file
build Build a source file or project
repl Start an interactive Kordex session
install Install project dependencies
update Update project dependencies
version Show Kordex versionGlobal options:
-h, --help Show help
-V, --version Show version
-v, --verbose Enable verbose output
--debug Enable debug output
-q, --quiet Disable normal output
--json Render machine-readable JSON output
--no-color Disable colored output
--dry-run Show what would happen without executingRuntime permissions:
--allow-fs
--allow-env
--allow-net
--allow-process
--allow-softadastraCreate main.js:
const runtime = "Kordex";
console.log(runtime);Run:
kordex run main.jsOutput:
KordexCreate main.ts:
const name: string = "Kordex";
function hello(value: string): string {
return "Hello from " + value;
}
console.log(hello(name));Run:
kordex run main.tsOutput:
Hello from KordexTypeScript support is currently MVP-level. It performs basic checking and type stripping before sending JavaScript to the engine.
Create message.js:
export function message() {
return "Import works";
}Create main.js:
import { message } from "./message.js";
console.log(message());Run:
kordex run main.jsOutput:
Import worksExtension resolution is supported:
import { message } from "./message";
console.log(message());Create user.json:
{
"name": "Kordex",
"type": "runtime"
}Create main.js:
import user from "./user.json";
console.log(user.name);
console.log(user.type);Run:
kordex run main.jsOutput:
Kordex
runtimeKordex exposes native modules through the kordex: prefix.
Available standard modules:
kordex:console
kordex:path
kordex:timer
kordex:crypto
kordex:fs
kordex:env
kordex:process
kordex:http
kordex:softadastraSafe utility modules can be available without special permissions:
kordex:console
kordex:path
kordex:timer
kordex:cryptoSensitive modules are controlled by explicit runtime permissions:
kordex:fs -> --allow-fs
kordex:env -> --allow-env
kordex:process -> --allow-process
kordex:http -> --allow-net
kordex:softadastra -> --allow-softadastraKordex does not expose sensitive native capabilities silently.
A script must be started with the required permission flag before it can import modules that touch filesystem, environment variables, process execution, network-related helpers, or Softadastra local-first storage.
Example:
kordex run main.js --allow-fsWithout the required permission, Kordex rejects the import.
Example:
permission denied: module "kordex:softadastra" requires --allow-softadastraThis permission model is one of the main design differences between Kordex and traditional JavaScript runtimes.
import { log, info, warn, error, debug } from "kordex:console";
log("log works");
info("info works");
warn("warn works");
error("error works");
debug("debug works");Run:
kordex run main.jsOutput:
[log] log works
[info] info works
[warn] warn works
[error] error works
[debug] debug worksThe global console object is also available:
console.log("global console works");
console.error("global console error works");import {
normalize,
join,
dirname,
basename,
extension,
isAbsolute,
isRelative,
separator,
} from "kordex:path";
console.log(normalize("/tmp/kordex/../kordex/app"));
console.log(join("/tmp", "kordex", "app"));
console.log(dirname("/tmp/kordex/app/main.js"));
console.log(basename("/tmp/kordex/app/main.js"));
console.log(extension("/tmp/kordex/app/main.js"));
console.log(isAbsolute("/tmp/kordex"));
console.log(isRelative("./main.js"));
console.log(separator);Run:
kordex run main.jsOutput on Linux/macOS:
/tmp/kordex/app
/tmp/kordex/app
/tmp/kordex/app
main.js
.js
true
true
/import { now, sleep, unixMs } from "kordex:timer";
const before = now();
sleep(10);
const after = now();
console.log(after >= before);
console.log(unixMs() > 0);Run:
kordex run main.jsOutput:
true
trueimport { hash, random, randomInt, equals } from "kordex:crypto";
console.log(hash("kordex"));
console.log(random() >= 0);
console.log(random() < 1);
console.log(randomInt(1, 10) >= 1);
console.log(equals("hello", "hello"));
console.log(equals("hello", "world"));Run:
kordex run main.jsOutput shape:
<hex hash>
true
true
true
true
falseFilesystem access requires --allow-fs.
import {
exists,
isFile,
isDirectory,
writeText,
readText,
remove,
} from "kordex:fs";
const file = "/tmp/kordex-fs-test.txt";
console.log(exists("/tmp"));
console.log(isDirectory("/tmp"));
writeText(file, "Hello from kordex:fs");
console.log(exists(file));
console.log(isFile(file));
console.log(readText(file));
console.log(remove(file));
console.log(exists(file));Run:
kordex run main.js --allow-fsOutput:
true
true
true
true
Hello from kordex:fs
true
falseWithout --allow-fs, kordex:fs is not available to the script.
Environment access requires --allow-env.
import { get, has, set, unset } from "kordex:env";
console.log(has("HOME"));
console.log(get("HOME") !== null);
set("KORDEX_TEST_ENV", "works");
console.log(has("KORDEX_TEST_ENV"));
console.log(get("KORDEX_TEST_ENV"));
unset("KORDEX_TEST_ENV");
console.log(has("KORDEX_TEST_ENV"));Run:
kordex run main.js --allow-envOutput shape:
true
true
true
works
falseProcess access requires --allow-process.
import { cwd, chdir, run } from "kordex:process";
console.log(cwd());
chdir("/tmp");
console.log(cwd());
console.log(run("true"));Run:
kordex run main.js --allow-processOutput shape:
/path/where/you-started
/tmp
0HTTP helpers require --allow-net.
kordex:http currently provides HTTP helper utilities, not real network requests.
import {
GET,
POST,
isSuccess,
isRedirect,
isClientError,
isServerError,
statusText,
buildUrl,
normalizeMethod,
isMethod,
} from "kordex:http";
console.log(GET);
console.log(POST);
console.log(isSuccess(200));
console.log(isRedirect(302));
console.log(isClientError(404));
console.log(isServerError(500));
console.log(statusText(200));
console.log(statusText(404));
console.log(buildUrl("https://example.com/", "/api/users"));
console.log(normalizeMethod("post"));
console.log(isMethod("PATCH"));
console.log(isMethod("CUSTOM"));Run:
kordex run main.js --allow-netOutput:
GET
POST
true
true
true
true
OK
Not Found
https://example.com/api/users
POST
true
falseSoftadastra access requires --allow-softadastra.
This module is the main reliability difference in Kordex.
It connects JavaScript execution to the Softadastra C++ SDK, giving scripts access to a local-first storage foundation.
Softadastra can be used to open a local store, write values, read values back, check keys, inspect the store size, and close the store.
Create main.js:
import * as softadastra from "kordex:softadastra";
console.log("Opening Softadastra local store...");
softadastra.open("durable", "kordex-example", ".kordex/data/example-store.wal");
softadastra.put("runtime", "kordex");
softadastra.put("feature", "local-first");
const runtime = softadastra.get("runtime");
const feature = softadastra.get("feature");
console.log("runtime:", runtime);
console.log("feature:", feature);
console.log("has runtime:", softadastra.contains("runtime"));
console.log("store size:", softadastra.size());
softadastra.close();
console.log("Softadastra store closed.");Run:
kordex run main.js --allow-softadastraExpected output:
Opening Softadastra local store...
runtime: kordex
feature: local-first
has runtime: true
store size: 2
Softadastra store closed.Without permission:
kordex run main.jsExpected error:
permission denied: module "kordex:softadastra" requires --allow-softadastraMost JavaScript runtimes stop at executing JavaScript and exposing system APIs.
Kordex goes further by connecting JavaScript to a local-first reliability layer.
That means Kordex can become useful for applications where:
- data must be written locally first
- the app must survive unstable networks
- offline mode is not an afterthought
- local state matters
- synchronization can be added later
- system access must stay permission-controlled
This is the long-term difference between Kordex and many other JavaScript runtimes.
You can inspect a module:
import * as path from "kordex:path";
console.log(Object.keys(path).sort().join(", "));Run:
kordex run main.jsOutput:
basename, dirname, extension, isAbsolute, isRelative, join, name, namespace, normalize, separatorThe repository includes examples under examples/.
01-hello
02-typescript
03-relative-import
04-extension-resolution
05-directory-index
06-json-import
07-console
08-path
09-timer
10-crypto
11-fs
12-env
13-process
14-http
15-softadastraRun an example:
kordex run examples/01-hello/main.jsRun the Softadastra example:
kordex run examples/15-softadastra/main.js --allow-softadastrakordex init app
cd appRun the default entry:
kordex runRun a file directly:
kordex run src/main.jsRun TypeScript:
kordex run src/main.tsKordex looks for:
kordex.json
package.jsonExample kordex.json:
{
"name": "my-app",
"version": "0.1.0",
"entry": "src/main.ts",
"scripts": {
"dev": "kordex run src/main.ts",
"build": "kordex build . --project"
}
}When running:
kordex runKordex resolves the entry from the project manifest.
Bundle a file:
kordex build main.js --out-dir dist --forceBundle a project:
kordex build . --project --out-dir dist --forceChoose output file:
kordex build . --project --out-dir dist --out-file app.js --forceGenerate a source map:
kordex build . --project --source-map --forceOutput:
dist/main.js
dist/main.js.mapEvaluate code:
kordex repl --eval "1 + 2"Output:
3Use Softadastra from REPL eval:
kordex repl --eval "import * as s from 'kordex:softadastra'; console.log(typeof s.open)" --allow-softadastraInstall dependencies from kordex.json:
kordex installInstall one package:
kordex install softadastra/plugin-example@0.1.0Update dependencies:
kordex updateThe current package workflow generates and updates:
kordex.lockThis is still an MVP. It resolves declared packages and lock metadata without automatically executing downloaded code.
Project plugin commands can be declared in kordex.json.
{
"plugins": {
"commands": [
{
"name": "hello",
"summary": "Run hello plugin",
"run": "scripts/hello.ts",
"aliases": ["hi"],
"permissions": {
"fs": false,
"env": false,
"net": false,
"process": false,
"softadastra": false
}
}
]
}
}Then:
kordex helloor:
kordex hiPlugin commands have isolated permissions and cannot override built-in commands.
kordex/
├── CMakeLists.txt
├── cmake/
├── docs/
├── examples/
├── modules/
│ ├── runtime/
│ ├── bindings/
│ ├── std/
│ └── cli/
├── README.md
├── CHANGELOG.md
└── LICENSEKordex follows a layered architecture:
CLI
-> Runtime options
-> Permission bridge
-> Bindings engine
-> Module loader
-> TypeScript loader
-> QuickJS backend
-> Standard native modules
-> ScriptResultThe runtime layer handles project-level and execution-level configuration.
The bindings layer handles JavaScript engine execution, native module registration, module loading, TypeScript transformation, and JavaScript backend integration.
The std layer exposes native modules through the kordex: namespace.
The CLI layer connects everything into a user-facing tool.
For:
kordex run src/main.ts --allow-softadastraThe pipeline is:
CLI parses command
-> project/file resolved
-> RuntimeOptions created
-> permissions converted to StdOptions
-> Engine initialized
-> std modules installed according to permissions
-> Script loaded
-> TypeScript transformed if needed
-> imports resolved
-> modules bundled internally
-> QuickJS eval
-> ScriptResult renderedFor:
kordex build . --projectThe pipeline is:
ProjectDiscovery
-> resolve entry
-> load script
-> analyze import graph
-> transform TypeScript
-> resolve JSON modules
-> bundle modules
-> write dist/main.js
-> optionally write dist/main.js.mapCore runtime foundation.
Provides:
- runtime configuration
- runtime lifecycle
- source file loading
- module resolver
- runtime loop
- cancellation
- timers
- tasks
- process facade
- diagnostics
- manifest loading
- permission model foundation
Native bindings and JavaScript engine bridge.
Provides:
- engine abstraction
- QuickJS backend
- script execution
eval()- TypeScript loading
- module loading
- JSON modules
- native module bridge
- native function bridge
- value conversion
- module cache
- permission-aware module loading
Standard native modules exposed to scripts.
Provides:
kordex:consolekordex:pathkordex:timerkordex:cryptokordex:fskordex:envkordex:processkordex:httpkordex:softadastra
User-facing command-line interface.
Provides:
kordex initkordex runkordex replkordex checkkordex buildkordex installkordex updatekordex versionkordex help
Development build:
vix build --preset dev-ninja --build-target all -v -- \
-DKORDEX_ENABLE_QUICKJS=ON \
-DKORDEX_ENABLE_NATIVE_ENGINE=OFF \
-DKORDEX_BUILD_APP=ONDevelopment build with Softadastra support:
vix build --preset dev-ninja --build-target all -v -- \
-DKORDEX_ENABLE_QUICKJS=ON \
-DKORDEX_ENABLE_NATIVE_ENGINE=OFF \
-DKORDEX_BUILD_APP=ON \
-DKORDEX_ENABLE_STD_SOFTADASTRA=ONBuild with tests:
vix build --preset dev-ninja --build-target all -v -- \
-DKORDEX_ENABLE_QUICKJS=ON \
-DKORDEX_ENABLE_NATIVE_ENGINE=OFF \
-DKORDEX_BUILD_APP=ON \
-DKORDEX_BUILD_TESTS=ONRun tests:
vix tests -- --output-on-failureUse this checklist when validating the runtime:
global console
kordex:console
kordex:path
kordex:timer
kordex:crypto
kordex:fs with --allow-fs
kordex:env with --allow-env
kordex:process with --allow-process
kordex:http with --allow-net
kordex:softadastra with --allow-softadastra
relative imports
extension resolution
JSON imports
TypeScript loading
build output
project entryKordex is early-stage.
Implemented foundations:
- runtime module
- bindings module
- std module
- CLI module
- QuickJS execution
- TypeScript MVP loader
- module loader
- std imports
- build bundling
- source map MVP
- permission bridge
- project discovery
- plugin command discovery
- install/update lock generation
- Softadastra standard module
- integration examples
Still planned:
- full TypeScript compiler integration
- package downloads from registry
- real plugin execution
- richer source maps
- package import resolution
- native ES module execution
- object/function value bridge
- deeper Softadastra sync integration
- richer local-first JavaScript APIs
Kordex is moving toward a runtime where JavaScript can be used for reliable local-first applications.
The direction is:
JavaScript execution
+ explicit native permissions
+ local durable state
+ offline-first behavior
+ optional synchronization
+ embeddable C++ foundationThis is the difference Kordex wants to bring.
Not only:
run JavaScriptBut:
run reliable local-first JavaScript applications- Repository: https://github.com/softadastra/kordex
- Releases: https://github.com/softadastra/kordex/releases
- Issues: https://github.com/softadastra/kordex/issues
- Vix.cpp: https://github.com/vixcpp/vix
- Softadastra: https://softadastra.com
- Softadastra Engine: https://github.com/softadastra/softadastra
MIT License.
