CLI Reference#
The jac command is your primary interface for working with Jac projects. It handles the full development lifecycle: running programs (jac run), type-checking code (jac check), running tests (jac test), formatting and linting (jac format, jac lint), managing dependencies (jac add, jac install), serving APIs (jac start), and even compiling to native binaries (jac nacompile). Think of it as combining the roles of python, pip, pytest, black, and flask into a single unified tool.
The CLI is extensible through plugins. When you install plugins like jac-scale or jac-client, they add new commands and flags automatically -- for example, jac start --scale for Kubernetes deployment or jac build --client desktop for desktop app packaging.
💡 Enhanced Output: For beautiful, colorful terminal output with Rich formatting, install the optional
jac-superplugin:pip install jac-super. All CLI commands will automatically use enhanced output with themes, panels, and spinners.
Quick Reference#
| Command | Description |
|---|---|
jac run |
Execute a Jac file |
jac start |
Start REST API server (use --scale for K8s deployment) |
jac create |
Create new project |
jac check |
Type check code |
jac test |
Run tests |
jac format |
Format code |
jac lint |
Lint code (use --fix to auto-fix) |
jac clean |
Clean project build artifacts |
jac purge |
Purge global bytecode cache (works even if corrupted) |
jac enter |
Run specific entrypoint |
jac dot |
Generate graph visualization |
jac debug |
Interactive debugger |
jac plugins |
Manage plugins |
jac config |
Manage project configuration |
jac destroy |
Remove Kubernetes deployment (jac-scale) |
jac status |
Show deployment status of Kubernetes resources (jac-scale) |
jac add |
Add packages to project |
jac install |
Install project dependencies |
jac remove |
Remove packages from project |
jac update |
Update dependencies to latest compatible versions |
jac jacpack |
Manage project templates (.jacpack files) |
jac eject |
Compile a project to standalone Python + JavaScript (zero .jac files) |
jac grammar |
Extract and print the Jac grammar |
jac script |
Run project scripts |
jac py2jac |
Convert Python to Jac |
jac jac2py |
Convert Jac to Python |
jac tool |
Language tools (IR, AST) |
jac lsp |
Language server |
jac jac2js |
Convert Jac to JavaScript |
jac build |
Build for target platform (jac-client) |
jac setup |
Setup build target (jac-client) |
jac db |
Inspect persistence DB, manage rescue aliases, recover quarantined data |
Version Info#
Displays the Jac version, Python version, platform, and all detected plugins with their versions:
_
(_) __ _ ___ Jac Language
| |/ _` |/ __|
| | (_| | (__ Version: 0.11.1
_/ |\__,_|\___| Python 3.12.3
|__/ Platform: Linux x86_64
🔌 Plugins Detected:
byllm==0.4.15
jac-client==0.2.11
jac-scale==0.2.1
Core Commands#
jac run#
Execute a Jac file.
Note: jac <file> is shorthand for jac run <file> - both work identically.
jac run [-h] [-m] [--no-main] [-c] [--no-cache] [-e DIAGNOSTICS] [--profile PROFILE] filename [args ...]
| Option | Description | Default |
|---|---|---|
filename |
Jac file to run | Required |
-m, --main |
Treat module as __main__ |
True |
-c, --cache |
Enable compilation cache | True |
-e, --diagnostics |
Diagnostic verbosity: error, all, or none |
error |
--profile |
Configuration profile to load (e.g. prod, staging) | "" |
args |
Arguments passed to the script (available via sys.argv[1:]) |
Like Python, everything after the filename is passed to the script. Jac flags must come before the filename.
Diagnostics modes:
| Mode | Errors | Warnings | Exit code on errors |
|---|---|---|---|
error (default) |
Shown with full details | Silent | 1 |
all |
Shown with full details | Shown | 1 |
none |
Silent | Silent | 0 |
The diagnostics level can also be set in jac.toml under [run].diagnostics. The CLI flag takes precedence over the config file.
Examples:
# Run a file (fails on compile errors by default)
jac run main.jac
# Run without cache (flags before filename)
jac run --no-cache main.jac
# Pass arguments to the script
jac run script.jac arg1 arg2
# Show all diagnostics (errors + warnings)
jac run -e all main.jac
# Suppress all diagnostics
jac run -e none main.jac
# Pass flag-like arguments to the script
jac run script.jac --verbose --output result.txt
Passing arguments to scripts:
Arguments after the filename are available in the script via sys.argv:
# greet.jac
import sys;
with entry {
name = sys.argv[1] if len(sys.argv) > 1 else "World";
print(f"Hello, {name}!");
}
sys.argv[0] is the script filename (like Python). For scripts that accept
flags, use Python's argparse module:
import argparse;
with entry {
parser = argparse.ArgumentParser();
parser.add_argument("--name", default="World");
args = parser.parse_args();
print(f"Hello, {args.name}!");
}
jac start#
Start a Jac application as an HTTP API server. With the jac-scale plugin installed, use --scale to deploy to Kubernetes. Use --dev for Hot Module Replacement (HMR) during development.
jac start [-h] [-p PORT] [-m] [--no-main] [-f] [--no-faux] [-d] [--no-dev] [-a API_PORT] [-n] [--no-no_client] [--profile PROFILE] [--client {web,desktop,pwa}] [--scale] [--no-scale] [-b] [--no-build] [filename]
| Option | Description | Default |
|---|---|---|
filename |
Jac file to serve | main.jac |
-p, --port |
Port number | 8000 |
-m, --main |
Treat as __main__ |
True |
-f, --faux |
Print docs only (no server) | False |
-d, --dev |
Enable HMR (Hot Module Replacement) mode | False |
--api_port |
Separate API port for HMR mode (0=same as port) | 0 |
--no_client |
Skip client bundling/serving (API only) | False |
--profile |
Configuration profile to load (e.g. prod, staging) | "" |
--client |
Client build target (web, desktop, pwa) |
None |
--scale |
Deploy to Kubernetes (requires jac-scale) | False |
-b, --build |
Build Docker image before deploy (with --scale) |
False |
Examples:
# Start with default main.jac on default port
jac start
# Start on custom port
jac start -p 3000
# Start with Hot Module Replacement (development)
jac start --dev
# HMR mode without client bundling (API only)
jac start --dev --no_client
# Deploy to Kubernetes (requires jac-scale plugin)
jac start --scale
# Build and deploy to Kubernetes
jac start --scale --build
Note:
- If your project uses a different entry file (e.g.,
app.jac,server.jac), you can specify it explicitly:jac start app.jac
jac create#
Initialize a new Jac project with configuration. Creates a project folder with the given name containing the project files.
| Option | Description | Default |
|---|---|---|
name |
Project name (creates folder with this name) | Current directory name |
-f, --force |
Overwrite existing project | False |
-u, --use |
Jacpac template: registered name, file path, or URL | default |
-l, --list-jacpacks |
List available jacpack templates | False |
Examples:
# Create basic project (creates myapp/ folder)
jac create myapp
cd myapp
# Create full-stack project with client template (requires jac-client)
jac create myapp --use client
# Create from a local .jacpack file
jac create myapp --use ./my-template.jacpack
# Create from a local template directory
jac create myapp --use ./my-template/
# Create from a URL
jac create myapp --use https://example.com/template.jacpack
# List available jacpack templates
jac create --list-jacpacks
# Force overwrite existing
jac create myapp --force
# Create in current directory
jac create
See Also: Use jac jacpack to create and bundle custom templates.
jac check#
Type check Jac code for errors.
| Option | Description | Default |
|---|---|---|
paths |
Files/directories to check | Required |
-e, --print_errs |
Print detailed error messages | True |
-i, --ignore |
Space-separated list of files/folders to ignore | None |
-p, --parse_only |
Only check syntax (skip type checking) | False |
--nowarn |
Suppress warning output | False |
Examples:
# Check a file
jac check main.jac
# Check a directory
jac check src/
# Check directory excluding specific folders/files
jac check myproject/ --ignore fixtures tests
# Check excluding multiple patterns
jac check . --ignore node_modules dist __pycache__
Errors and warnings are displayed with structured diagnostic codes (e.g., E1030, W2001). You can suppress individual diagnostics inline with # jac:ignore[CODE]:
See the full Errors & Warnings reference for all diagnostic codes.
jac test#
Run tests in Jac files.
| Option | Description | Default |
|---|---|---|
filepath |
Test file to run | None |
-t, --test_name |
Specific test name | None |
-f, --filter |
Filter tests by pattern | None |
-x, --xit |
Exit on first failure | False |
-m, --maxfail |
Max failures before stop | None |
-d, --directory |
Test directory | None |
-v, --verbose |
Verbose output | False |
Examples:
# Run all tests in a file
jac test main.jac
# Run a specific test - spaces in name (quoted)
jac test main.jac -t "my test name"
# Run a specific test - underscores in name
jac test main.jac -t my_test_name
# Run tests in directory
jac test -d tests/
# Run all tests in current directory
jac test
# Stop on first failure
jac test main.jac -x
# Verbose output
jac test main.jac -v
Error handling:
| Mistake | Error shown |
|---|---|
jac test --test_name foo (no file or directory) |
--test_name requires a filepath |
jac test missing.jac (file doesn't exist) |
File not found: 'missing.jac' |
jac test main.jac -t foo bar (unquoted multi-word) |
hint to use quotes |
jac format#
Format Jac code according to style guidelines. For auto-linting (code corrections like combining consecutive has statements, converting @staticmethod to static), use jac lint --fix instead.
| Option | Description | Default |
|---|---|---|
paths |
Files/directories to format | Required |
-s, --to_screen |
Print to stdout instead of writing | False |
-l, --lintfix |
Also apply auto-lint fixes in the same pass | False |
-c, --check |
Check if files are formatted without modifying them (exit 1 if unformatted) | False |
Examples:
# Preview formatting
jac format main.jac -s
# Apply formatting
jac format main.jac
# Format entire directory
jac format .
# Check formatting without modifying (useful in CI)
jac format . --check
Note: For auto-linting (code corrections), use
jac lint --fixinstead. Seejac lintbelow.Safety: If the formatter detects that comments were displaced (e.g., moved to the end of the file), it emits error
E5051and refuses to save the file. Runjac format <file> -sto inspect the output without writing.
jac lint#
Lint Jac files and report violations. Use --fix to auto-fix violations.
| Option | Description | Default |
|---|---|---|
paths |
Files/directories to lint | Required |
-f, --fix |
Auto-fix lint violations | False |
--ignore |
Comma-separated files/folders to ignore | "" |
Examples:
# Report lint violations
jac lint main.jac
# Auto-fix violations
jac lint main.jac --fix
# Lint entire directory
jac lint .
# Lint excluding folders
jac lint . --ignore fixtures
Lint Rules: Configure rules via
[check.lint]injac.toml. See Lint Rules for the full list with diagnostic codes.
jac enter#
Run a specific entrypoint in a Jac file.
| Option | Description | Default |
|---|---|---|
filename |
Jac file | Required |
entrypoint |
Function/walker to invoke (positional) | Required |
args |
Arguments to pass | None |
-m, --main |
Treat as __main__ |
True |
-r, --root |
Root executor ID | None |
-n, --node |
Starting node ID | None |
Examples:
# Run specific entrypoint
jac enter main.jac my_walker
# With arguments
jac enter main.jac process_data arg1 arg2
# With root and node
jac enter main.jac my_walker -r root_id -n node_id
Visualization & Debug#
jac dot#
Generate DOT graph visualization.
jac dot [-h] [-s SESSION] [-i INITIAL] [-d DEPTH] [-t] [-b] [-e EDGE_LIMIT] [-n NODE_LIMIT] [-o SAVETO] [-p] [-f FORMAT] filename [connection ...]
| Option | Description | Default |
|---|---|---|
filename |
Jac file | Required |
-s, --session |
Session identifier | None |
-i, --initial |
Initial node ID | None |
-d, --depth |
Max traversal depth | -1 (unlimited) |
-t, --traverse |
Enable traversal mode | False |
-c, --connection |
Connection filters | None |
-b, --bfs |
Use BFS traversal | False |
-e, --edge_limit |
Max edges | 512 |
-n, --node_limit |
Max nodes | 512 |
-o, --saveto |
Output file path | None |
-p, --to_screen |
Print to stdout | False |
-f, --format |
Output format | dot |
Examples:
# Generate DOT output
jac dot main.jac -s my_session --to_screen
# Save to file
jac dot main.jac -s my_session --saveto graph.dot
# Limit depth
jac dot main.jac -s my_session -d 3
jac debug#
Start interactive debugger.
| Option | Description | Default |
|---|---|---|
filename |
Jac file to debug | Required |
-m, --main |
Run main entry | True |
-c, --cache |
Use cache | False |
Examples:
VS Code Debugger Setup#
To use the VS Code debugger with Jac:
- Install the Jac extension from the VS Code Extensions marketplace
- Enable Debug: Allow Breakpoints Everywhere in VS Code Settings (search "breakpoints")
- Create a
launch.jsonvia Run and Debug panel (Ctrl+Shift+D) → "Create a launch.json file" → select "Jac Debug"
The generated .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "jac",
"request": "launch",
"name": "Jac Debug",
"program": "${file}"
}
]
}
Debugger controls: F5 (continue), F10 (step over), F11 (step into), Shift+F11 (step out).
Graph Visualization (jacvis)#
The Jac extension includes live graph visualization:
- Open VS Code Command Palette (Ctrl+Shift+P / Cmd+Shift+P)
- Type
jacvisand select jacvis: Visualize Jaclang Graph - A side panel opens showing your graph structure
Set breakpoints and step through code -- nodes and edges appear in real time as your program builds the graph. Open jacvis before starting the debugger for best results.
For a complete walkthrough, see the Debugging in VS Code Tutorial.
Plugin Management#
jac plugins#
Manage Jac plugins.
| Action | Description |
|---|---|
list |
List installed plugins (default) |
info |
Show plugin information |
enable |
Enable plugins |
disable |
Disable plugins |
disabled |
List disabled plugins |
| Option | Description | Default |
|---|---|---|
-v, --verbose |
Verbose output | False |
Examples:
# List plugins (action defaults to 'list')
jac plugins
# Explicitly list plugins
jac plugins list
# Show info about a plugin
jac plugins info byllm
# Disable a plugin
jac plugins disable byllm
# Enable a plugin
jac plugins enable byllm
# List disabled plugins
jac plugins disabled
Note: To install or uninstall plugins, use
pip install/pip uninstalldirectly. Thejac pluginscommand manages enabled/disabled state for already-installed plugins.💡 Popular Plugins:
- jac-super: Enhanced console output with Rich formatting, colors, and spinners (
pip install jac-super)- jac-client: Full-stack web development with client-side rendering (
pip install jac-client)- jac-scale: Kubernetes deployment and scaling (
pip install jac-scale)
Database Operations#
The jac db command group inspects the live persistence backend, manages DB-resident rescue aliases, and recovers quarantined anchors. It works against any PersistentMemory backend -- SqliteMemory (default), MongoBackend (with jac-scale), or any plugin-provided backend that implements the interface -- through the same set of subcommands.
For the architectural background (fingerprints, drift detection, quarantine philosophy, alias decorator), see Persistence & Schema Migration.
Backend dispatch#
jac db always operates on the backend the user's app is configured to use:
- Pass
--app PATHto point at the entry.jacfile. - Or run the command from the app's directory; if there's exactly one
.jacin the current directory, it's picked automatically.
The command imports the user's app to set up the runtime context, then talks to whatever PersistentMemory backend the configuration installs -- SQLite locally, Mongo in production, etc. There is no separate mode for each backend.
# Explicit
jac db inspect --app path/to/app.jac
# Implicit when there's one .jac in cwd
cd my_app/
jac db inspect
jac db inspect#
Print a one-line summary of the live persistence backend plus per-archetype count tables for both anchors and quarantine.
Output:
Jac DB: /tmp/myapp/.jac/data/anchor_store.db
[INFO] format_version=1 anchors=5 quarantined=0 aliases=0
Anchors
┏━━━━━━━━━━━━━┳━━━━━━━┓
┃ arch_type ┃ count ┃
┡━━━━━━━━━━━━━╇━━━━━━━┩
│ Person │ 2 │
│ GenericEdge │ 2 │
│ Root │ 1 │
└─────────────┴───────┘
The summary line covers: storage format version, total live anchor count, total quarantined count, and total alias count. Quarantine + Anchors tables only print when non-empty.
jac db quarantine list#
List the most recent quarantined anchors with their class, fingerprint, error, and timestamp.
Sorted newest first. UUID columns are truncated to a recognizable prefix; pass any unique prefix to quarantine show or recover.
jac db quarantine show \<id-prefix>#
Dump one quarantined row in full (parsed JSON), including the original data payload -- useful for understanding why a row failed to load.
A unique prefix is sufficient. If the prefix is ambiguous, the command tells you and asks for a longer prefix.
jac db alias add / list / remove#
DB-resident rescue aliases. Persisted in an aliases table (SQLite) or <collection>_aliases companion collection (Mongo, e.g. _anchors_aliases) and merged into the in-process Serializer._aliases map at backend connect time. Survives across process restarts; affects every consumer of that database.
# List current aliases.
jac db alias list
# Register a rescue alias for a class rename / module move.
jac db alias add "old.module.LegacyName" "new.module.NewName"
# Remove one.
jac db alias remove "old.module.LegacyName"
Both arguments to alias add are fully-qualified module.ClassName strings -- the module part is what would have appeared in the stored row's arch_module field. For files imported via jac enter app.jac, the module is __main__.
When to use this vs. the decorator. The
@archetype_aliasdecorator is the normal path: it's code-resident, travels through git, applies wherever the code runs.jac db alias addis the rescue path: emergency recovery in production without a code deploy. Decorator first, CLI as the safety net.
jac db recover \<id-prefix>#
Re-attempt deserialization on one quarantined row. On success, the row is moved back to the live anchors collection and re-stamped with the live class's identity + fingerprint so subsequent reads bypass alias resolution and drift detection.
Recovery only succeeds when the user's archetype classes (and any @archetype_alias decorators) are registered, so the user app must be discoverable -- via --app PATH or the cwd auto-discovery described above. Without it, every quarantined row will be reported as class X.Y still unresolvable.
jac db recover-all#
Batch variant. Re-attempts every quarantined row and reports counts, plus a per-row reason for whatever still can't be recovered.
Typical output:
Or, when some rows are still stuck (often because the class involved isn't covered by any alias yet):
✔ Recovered 3 of 5 quarantined rows.
[WARN] 2 rows still quarantined.
Still quarantined
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ id ┃ reason ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ d44e2c7a… │ class oldmod.GoneAway still unresolvable │
│ 902b14ee… │ deserialize raised: ValueError: bad enum value │
└───────────┴─────────────────────────────────────────────────┘
Typical rescue workflow#
# 1. Discover what's quarantined.
jac db inspect --app app.jac
jac db quarantine list --app app.jac
# 2. Drill into one row to understand why.
jac db quarantine show <prefix> --app app.jac
# 3. If it's a class rename: register an alias.
jac db alias add "__main__.OldName" "__main__.NewName"
# 4. Re-attempt every stuck row.
jac db recover-all --app app.jac
# 5. Confirm.
jac db inspect --app app.jac
After step 5 the quarantine count should be zero (or list only rows that genuinely need a different fix -- type changes too aggressive for the coercion table, etc.).
Configuration Management#
jac config#
View and modify project configuration settings in jac.toml.
| Action | Description |
|---|---|
show |
Display explicitly set configuration values (default) |
list |
Display all settings including defaults |
get |
Get a specific setting value |
set |
Set a configuration value |
unset |
Remove a configuration value (revert to default) |
path |
Show path to config file |
groups |
List available configuration groups |
| Option | Description | Default |
|---|---|---|
key |
Configuration key (positional, e.g., project.name) |
None |
value |
Value to set (positional) | None |
-g, --group |
Filter by configuration group | None |
-o, --output |
Output format (table, json, toml) |
table |
Configuration Groups:
project- Project metadata (name, version, description)run- Runtime settings (cache, session)build- Build settings (typecheck, output directory)test- Test settings (verbose, filters)serve- Server settings (port, host)format- Formatting optionscheck- Type checking optionsdot- Graph visualization settingscache- Cache configurationplugins- Plugin managementenvironment- Environment variables
Examples:
# Show explicitly set configuration
jac config show
# Show all settings including defaults
jac config list
# Show settings for a specific group
jac config show -g project
# Get a specific value
jac config get project.name
# Set a value
jac config set project.version "2.0.0"
# Remove a value (revert to default)
jac config unset run.cache
# Show config file path
jac config path
# List available groups
jac config groups
# Output as JSON
jac config show -o json
# Output as TOML
jac config list -o toml
Deployment (jac-scale)#
jac start --scale#
Deploy to Kubernetes using the jac-scale plugin. See the jac start command above for full options.
jac status#
Show the deployment status of your Jac application on Kubernetes. Displays a color-coded table with the health of each component (application, Redis, MongoDB, Prometheus, Grafana), pod readiness counts, and service URLs.
| Option | Description | Default |
|---|---|---|
file_path |
Path to the .jac file |
Required |
--target |
Deployment target platform | kubernetes |
Example output:
Jac Scale - Deployment Status
App: my-app Namespace: default
┌───────────────────┬────────────────────────┬───────┐
│ Component │ Status │ Pods │
├───────────────────┼────────────────────────┼───────┤
│ Jaseci App │ ● Running │ 1/1 │
│ Redis │ ● Running │ 1/1 │
│ MongoDB │ ● Running │ 1/1 │
│ Prometheus │ ● Running │ 1/1 │
│ Grafana │ ● Running │ 1/1 │
└───────────────────┴────────────────────────┴───────┘
Service URLs
────────────────────────────────────────────
Application: http://localhost:30001
Grafana: http://localhost:30003
Status indicators:
| Symbol | Meaning |
|---|---|
● Running |
All pods healthy and ready |
◑ Degraded |
Some pods ready, but not all |
⟳ Pending |
Pods are starting up |
↺ Restarting |
Pods are crash-looping |
✗ Failed |
Component has failed |
○ Not Deployed |
Component is not present in the cluster |
Examples:
# Check deployment status
jac status app.jac
# Check status with explicit target
jac status app.jac --target kubernetes
jac destroy#
Remove a deployment.
| Option | Description | Default |
|---|---|---|
file_path |
Jac file to undeploy | Required |
Examples:
Package Management#
jac add#
Add packages to your project's dependencies. Requires at least one package argument (use jac install to install all existing dependencies). When no version is specified, the package is installed unconstrained and then the installed version is queried to record a ~=X.Y compatible-release spec in jac.toml.
| Option | Description | Default |
|---|---|---|
packages |
Package specifications (required) | None |
-d, --dev |
Add as dev dependency | False |
-g, --git |
Git repository URL | None |
-v, --verbose |
Show detailed output | False |
With jac-client plugin:
| Option | Description | Default |
|---|---|---|
--npm |
Add as client-side (npm) package | False |
Examples:
# Add a package (records ~=2.32 based on installed version)
jac add requests
# Add with explicit version constraint
jac add "numpy>=1.24"
# Add multiple packages
jac add numpy pandas scipy
# Add as dev dependency
jac add pytest --dev
# Add from git repository
jac add --git https://github.com/user/package.git
# Add npm package (requires jac-client)
jac add react --npm
For private packages from custom registries (e.g., GitHub Packages), configure scoped registries and auth tokens in jac.toml under [plugins.client.npm]. See NPM Registry Configuration.
jac install#
Sync the project environment to jac.toml. Installs all Python (pip), git, and plugin-provided (npm, etc.) dependencies in one command. Creates or validates the project virtual environment at .jac/venv/.
| Option | Description | Default |
|---|---|---|
-d, --dev |
Include dev dependencies | False |
-v, --verbose |
Show detailed output | False |
Examples:
# Install all dependencies
jac install
# Install including dev dependencies
jac install --dev
# Install with verbose output
jac install -v
jac remove#
Remove packages from your project's dependencies.
| Option | Description | Default |
|---|---|---|
packages |
Package names to remove | None |
-d, --dev |
Remove from dev dependencies | False |
With jac-client plugin:
| Option | Description | Default |
|---|---|---|
--npm |
Remove client-side (npm) package | False |
Examples:
# Remove a package
jac remove requests
# Remove multiple packages
jac remove numpy pandas
# Remove dev dependency
jac remove pytest --dev
# Remove npm package (requires jac-client)
jac remove react --npm
jac update#
Update dependencies to their latest compatible versions. For each updated package, the installed version is queried and a ~=X.Y compatible-release spec is written back to jac.toml.
| Option | Description | Default |
|---|---|---|
packages |
Specific packages to update (all if empty) | None |
-d, --dev |
Include dev dependencies | False |
-v, --verbose |
Show detailed output | False |
Examples:
# Update all dependencies to latest compatible versions
jac update
# Update a specific package
jac update requests
# Update all including dev dependencies
jac update --dev
jac clean#
Clean project build artifacts from the .jac/ directory.
| Option | Description | Default |
|---|---|---|
-a, --all |
Clean all .jac artifacts (data, cache, packages, client) |
False |
-d, --data |
Clean data directory (.jac/data) |
False |
-c, --cache |
Clean cache directory (.jac/cache) |
False |
-p, --packages |
Clean virtual environment (.jac/venv) |
False |
-f, --force |
Force clean without confirmation prompt | False |
By default (no flags), jac clean removes only the data directory (.jac/data).
Examples:
# Clean data directory (default)
jac clean
# Clean all build artifacts
jac clean --all
# Clean only cache
jac clean --cache
# Clean data and cache directories
jac clean --data --cache
# Force clean without confirmation
jac clean --all --force
💡 Troubleshooting Tip: If you encounter unexpected syntax errors, "NodeAnchor is not a valid reference" errors, or other strange behavior after modifying your code, try clearing the cache with
jac clean --cache(rm -rf .jac) orjac purge. Stale bytecode can cause issues when source files change.
jac purge#
Purge the global bytecode cache. Works even when the cache is corrupted.
When to use:
- After upgrading Jaseci packages
- When encountering cache-related errors (
jaclang.pycore,NodeAnchor, etc.) - When setup stalls during first-time compilation
| Command | Scope |
|---|---|
jac clean --cache |
Local project (.jac/cache/) |
jac purge |
Global system cache |
Template Management#
jac jacpack#
Manage project templates. Bundle template directories into distributable .jacpack files or list available templates.
| Action | Description |
|---|---|
pack |
Bundle a template directory into a .jacpack file |
list |
List available templates (default) |
info |
Show information about a template |
| Option | Description | Default |
|---|---|---|
path |
Template directory (for pack) or .jacpack file (for info) |
None |
-o, --output |
Output file path for bundled template | <name>.jacpack |
Template Directory Structure:
A template directory should contain:
jac.toml- Project config with a[jacpack]section for metadata- Template files (
.jac,.md, etc.) with{{name}}placeholders
To make any Jac project packable as a template, simply add a [jacpack] section to your jac.toml. All other sections become the config for created projects.
Example jac.toml for a template:
# Standard project config (becomes the created project's jac.toml)
[project]
name = "{{name}}"
version = "0.1.0"
entry-point = "main.jac"
[dependencies]
# Jacpac metadata - used when packing, stripped from created projects
[jacpack]
name = "mytemplate"
description = "My custom project template"
jaclang = "0.9.0"
[[jacpack.plugins]]
name = "jac-client"
version = "0.1.0"
[jacpack.options]
directories = [".jac"]
root_gitignore_entries = [".jac/"]
Examples:
# List available templates
jac jacpack list
# Bundle a template directory
jac jacpack pack ./my-template
# Bundle with custom output path
jac jacpack pack ./my-template -o custom-name.jacpack
# Show template info
jac jacpack info ./my-template
jac jacpack info mytemplate.jacpack
Using Templates with jac create:
Once a template is registered, use it with the --use flag:
jac eject#
Compile a Jac project to a self-contained output folder containing only Python and JavaScript files. The ejected project has zero .jac files and can be run, edited, and deployed without invoking the Jac compiler. Use it when you want to hand off a Jac-built application to a team that doesn't use Jac, freeze a snapshot of a project, or deploy on infrastructure where installing the toolchain is impractical.
| Option | Description | Default |
|---|---|---|
source |
Project directory to eject (must contain jac.toml) |
. |
-o, --output |
Output directory | <source>-ejected next to source |
-f, --force |
Overwrite the output directory if it already exists | False |
What gets emitted
- Server-side
.sv.jacmodules become plain Python via the compiler's existinggen.pyoutput (walkers compile to classes with@on_entry/@on_exit, spatial operations like-->andvisitlower toconnect/refs/visitcalls). - Client-side
.cl.jacmodules become plain JavaScript viagen.js(JSX lowers to__jacJsx(...)calls,hasdeclarations touseStatehooks,sv importto auto-generated HTTP RPC stubs). .impl.jacfiles merge automatically into their declaration sibling at compile time, so the eject pipeline never processes them directly.- Filenames drop the
.sv/.clcontext tag (endpoints.sv.jac→endpoints.py,frontend.cl.jac→frontend.js), matching what the compiler already emits in cross-module imports. - Static assets under
assets/are copied verbatim intofrontend/src/assets/.
Output layout
<name>-ejected/
├── README.md how to run, layout, caveats
├── run.sh starts backend + frontend dev server
├── backend/
│ ├── serve.py entry script (python serve.py)
│ ├── requirements.txt pip dependencies (includes jaclang)
│ ├── main.py ejected entry module
│ └── ... other ejected server modules
└── frontend/
├── package.json npm dependencies (includes Vite)
├── vite.config.js dev server with backend proxy
├── index.html SPA shell loading src/main.js
└── src/
├── main.js
├── components/ ejected client components
└── assets/ static files
The generated backend/serve.py boots the existing JacAPIServer HTTP request handler against the ejected modules: it loads the entry module via importlib, injects it into Jac.loaded_modules so the introspector skips its own jac_import, and constructs http.server.HTTPServer directly to bypass the Jac.create_server plugin hook. It also forces the base SQLite-backed UserManager so register/login/auth work consistently regardless of which jaclang plugins are installed in the runtime environment.
Examples
# Eject the current project to ./<name>-ejected/
jac eject
# Eject a specific project to a chosen output directory
jac eject ./myapp -o /tmp/myapp-standalone
# Overwrite an existing output directory
jac eject ./myapp -o /tmp/myapp-standalone --force
Running the ejected project
The backend listens on PORT (default 8000) and the Vite dev server listens on FRONTEND_PORT (default 5173); the Vite config proxies /walker, /walkers, /function, /functions, /user, and /cl to the backend so the SPA can call API endpoints without CORS plumbing.
Caveats
- This first version still requires
jaclangto be installed at runtime. The ejected backend imports walker primitives fromjaclang.jac0core.jacliband the HTTP request handler fromjaclang.runtimelib.server. The goal is zero.jacfiles in the output, not zerojaclangdependency. .impl.jacand.test.jacfiles are skipped (they have no standalone meaning); so are well-known build directories (.jac,.git,.venv,node_modules,__pycache__,dist,build, etc.).- Persistent state (users, root nodes, graph data) lives under
backend/.jac/data/after first run, just as it would forjac start.
Extending eject from a plugin
Like every other command, jac eject is extensible through the standard plugin hook mechanism -- a plugin can add flags via registry.extend_command("eject", ...) and either replace the default behavior in a pre-hook (jac-scale --scale style) or augment the output in a post-hook (jac-client --client desktop style). See the Plugin Authoring Guide for the full extension model.
For eject specifically, jaclang.cli.commands.impl.eject exports two helpers so plugin pre/post hooks can stay in sync with whatever the default command produces:
| Helper | Purpose |
|---|---|
resolve_eject_output(src: Path, output: str) -> Path |
Returns the resolved output directory, applying the same <source>-ejected fallback the command uses when --output is not given. |
load_eject_project_metadata(src: Path) -> dict |
Parses jac.toml and returns a dict with project_name, entry_point, entry_module, and the raw toml_data so plugins can read sections like [plugins.scale] or [dependencies.npm] without re-parsing. |
jac jac2js#
Generate JavaScript output from Jac code (used for jac-client frontend compilation).
| Option | Description | Default |
|---|---|---|
filename |
Jac file to compile to JS | Required |
Examples:
Deprecated:
jac jsis a deprecated alias forjac jac2jsand will be removed in a future release. It still works but emits a deprecation warning on stderr; update scripts to usejac jac2js.
Utility Commands#
jac grammar#
Extract and print the Jac grammar.
| Option | Description | Default |
|---|---|---|
--lark |
Output in Lark format instead of EBNF | False |
-o, --output |
Write output to file instead of stdout | None |
Examples:
# Print grammar in EBNF format
jac grammar
# Print in Lark format
jac grammar --lark
# Save to file
jac grammar -o grammar.ebnf
jac script#
Run custom scripts defined in the [scripts] section of jac.toml.
| Option | Description | Default |
|---|---|---|
name |
Script name to run | None |
-l, --list_scripts |
List available scripts | False |
Examples:
See Configuration: Scripts for defining scripts in jac.toml.
jac py2jac#
Convert Python code to Jac.
Examples:
jac jac2py#
Convert Jac code to Python.
Examples:
jac tool#
Access language tools (IR, AST, etc.).
Available tools:
# View IR options
jac tool ir
# View AST
jac tool ir ast main.jac
# View symbol table
jac tool ir sym main.jac
# View generated Python
jac tool ir py main.jac
jac nacompile#
Compile a .na.jac file to a standalone native ELF executable. No external compiler, assembler, or linker is required. The entire pipeline runs in pure Python using llvmlite and a built-in ELF linker.
| Option | Description | Default |
|---|---|---|
filename |
Path to the .na.jac file (must have with entry {} block) |
required |
-o, --output |
Output binary path | filename without .na.jac |
The file must contain a with entry { } block (which defines the jac_entry() function). Files with Python/server dependencies (native_imports) cannot be compiled to standalone binaries.
What happens under the hood:
- Compiles the
.na.jacthrough the Jac pipeline to get LLVM IR - Injects
main()and_startas pure LLVM IR (zero inline assembly) - Emits native object code via llvmlite's
emit_object() - Links into an ELF executable via the built-in pure-Python ELF linker
The resulting binary dynamically links against libc.so.6. Memory management uses a self-contained reference counting scheme -- no external garbage collector (libgc) is required.
Examples:
# Compile to ./chess
jac nacompile chess.na.jac
# Compile with custom output name
jac nacompile chess.na.jac -o mychess
# Run the binary
./mychess
jac completions#
Generate and install shell completion scripts for the jac CLI.
| Option | Description | Default |
|---|---|---|
-s, --shell |
Shell type (bash, zsh, fish) |
bash |
-i, --install |
Auto-install completion to shell config | False |
When --install is used, the completion script is written to ~/.jac/completions.<shell> (e.g. ~/.jac/completions.bash) and a source line is added to your shell config file (~/.bashrc, ~/.zshrc, or ~/.config/fish/config.fish).
Installed files:
| Shell | Completion script | Config modified |
|---|---|---|
| bash | ~/.jac/completions.bash |
~/.bashrc |
| zsh | ~/.jac/completions.zsh |
~/.zshrc |
| fish | ~/.jac/completions.fish |
~/.config/fish/config.fish |
Examples:
# Print bash completion script to stdout
jac completions
# Auto-install for bash (writes to ~/.jac/completions.bash)
jac completions --install
# Generate zsh completions
jac completions --shell zsh
# Auto-install for fish
jac completions --shell fish --install
Note: After installing, run
source ~/.bashrc(or restart your shell) to activate completions. Completions cover subcommands, options, and file paths.
jac lsp#
Start the Language Server Protocol server (for IDE integration).
Plugin Commands#
Plugins can add new commands and extend existing ones. These commands are available when the corresponding plugin is installed.
jac-client Commands#
Requires: pip install jac-client
jac build#
Build a Jac application for a specific target.
| Option | Description | Default |
|---|---|---|
filename |
Path to .jac file | main.jac |
--client |
Build target (web, desktop) |
web |
-p, --platform |
Desktop platform (windows, macos, linux, all) |
Current platform |
Examples:
# Build web target (default)
jac build
# Build desktop app
jac build --client desktop
# Build for Windows
jac build --client desktop --platform windows
jac setup#
One-time initialization for a build target.
Examples:
Extended Flags#
| Base Command | Added Flag | Description |
|---|---|---|
jac create |
--use client |
Create full-stack project template |
jac create |
--skip |
Skip npm package installation |
jac start |
--client <target> |
Client build target for dev server |
jac add |
--npm |
Add npm (client-side) dependency |
jac remove |
--npm |
Remove npm (client-side) dependency |
Common Workflows#
Development#
# Create project
jac create myapp
cd myapp
# Run
jac run main.jac
# Test
jac test -v
# Lint and fix
jac lint . --fix
Production#
# Start locally
jac start -p 8000
# Deploy to Kubernetes
jac start main.jac --scale
# Check deployment status
jac status main.jac
# Remove deployment
jac destroy main.jac