Project Configuration with jac.toml#
The jac.toml file is the central configuration file for Jac projects. Similar to pyproject.toml in Python or package.json in Node.js, it defines project metadata, dependencies, and command defaults.
Getting Started#
Creating a New Project#
To create a new Jac project with a jac.toml file:
The jac create command supports several options:
-f, --force: Overwrite existingjac.tomlif present-u, --use: Jacpac template: registered name, file path, or URL
Examples:
# Create a basic project
jac create myapp
# Create with frontend support (requires jac-client plugin)
jac create myapp --use client
# Create in current directory (overwrites existing jac.toml)
jac create --force
This creates a project with a basic jac.toml:
[project]
name = "my-project"
version = "0.1.0"
description = "A Jac project"
entry-point = "main.jac"
[dependencies]
[dev-dependencies]
watchdog = ">=3.0.0" # Required for HMR (jac start --watch)
[run]
main = true
cache = true
Project Structure#
A typical Jac project looks like:
my-project/
├── jac.toml # Project configuration
├── main.jac # Entry point
├── packages/ # Installed dependencies
├── lib/ # Library modules (optional)
│ └── utils.jac
└── tests/ # Test files (optional)
└── test_main.jac
Configuration Reference#
[project] Section#
Defines project metadata:
[project]
name = "my-awesome-app"
version = "1.0.0"
description = "An awesome Jac application"
authors = ["Your Name <you@example.com>"]
license = "MIT"
readme = "README.md"
jac-version = ">=0.7.0"
entry-point = "main.jac"
[project.urls]
homepage = "https://example.com"
repository = "https://github.com/user/repo"
| Field | Type | Description |
|---|---|---|
name |
string | Project name (required) |
version |
string | Semantic version (e.g., "1.0.0") |
description |
string | Brief project description |
authors |
list | List of author strings |
license |
string | License identifier (e.g., "MIT", "Apache-2.0") |
readme |
string | Path to README file |
jac-version |
string | Required Jac version constraint |
entry-point |
string | Main entry file (default: "main.jac") |
urls |
table | Project URLs (homepage, repository, etc.) |
[dependencies] Section#
Specifies project dependencies:
[dependencies]
# Python/PyPI packages
requests = ">=2.28.0"
numpy = "1.24.0"
# Jac plugins
jac-byllm = ">=0.4.8"
# Version specifiers
some-package = ">=1.0,<2.0" # Range
another = "~=1.4.2" # Compatible release
Version Specifier Formats:
| Format | Example | Description |
|---|---|---|
| Exact | "1.0.0" |
Exact version |
| Minimum | ">=1.0.0" |
At least this version |
| Maximum | "<2.0.0" |
Less than this version |
| Range | ">=1.0,<2.0" |
Version range |
| Compatible | "~=1.4.2" |
Compatible with 1.4.x |
[dev-dependencies] Section#
Development-only dependencies (not installed in production):
[dev-dependencies]
watchdog = ">=3.0.0" # Required for HMR (jac start --watch)
pytest = ">=8.2.1"
mypy = ">=1.0.0"
black = ">=23.0.0"
The watchdog package is included by default in new projects to enable Hot Module Replacement during development.
[dependencies.git] Section#
Git-based dependencies:
[dependencies.git]
my-private-lib = { git = "https://github.com/user/repo.git", branch = "main" }
another-lib = { git = "git@github.com:user/repo.git", tag = "v1.0.0" }
[run] Section#
Default options for jac run:
[run]
session = "" # Session name for persistence
main = true # Run as main module
cache = true # Enable bytecode caching
[build] Section#
Build configuration:
[test] Section#
Test runner configuration:
[test]
directory = "tests" # Test directory
filter = "" # Test filter pattern
verbose = false # Verbose output
fail_fast = false # Stop on first failure
max_failures = 0 # Max failures before stopping (0 = unlimited)
[serve] Section#
Server configuration for jac start:
[serve]
port = 8000 # Server port
session = "" # Session name
main = true # Run as main module
cl_route_prefix = "cl" # URL prefix for client apps (default: "cl")
base_route_app = "" # Client app to serve at root "/" (default: none)
| Option | Type | Default | Description |
|---|---|---|---|
port |
int | 8000 |
Server port number |
session |
string | "" |
Session file name for persistence |
main |
bool | true |
Run as main module |
cl_route_prefix |
string | "cl" |
URL prefix for client-side apps. Apps are served at /<prefix>/<app_name>. |
base_route_app |
string | "" |
Name of a client app to serve at root /. When set, visiting / renders this app instead of the API info page. |
[format] Section#
Code formatter configuration:
[check] Section#
Type checker configuration:
[dot] Section#
Graph visualization configuration for jac dot:
[dot]
depth = -1 # Traversal depth (-1 = unlimited)
traverse = false # Traverse connections
bfs = false # Use BFS traversal (vs DFS)
edge_limit = 512 # Maximum edges in output
node_limit = 512 # Maximum nodes in output
format = "dot" # Output format
| Field | Type | Default | Description |
|---|---|---|---|
depth |
int | -1 |
How deep to traverse (-1 = unlimited) |
traverse |
bool | false |
Whether to traverse connections |
bfs |
bool | false |
Use breadth-first search (default is DFS) |
edge_limit |
int | 512 |
Maximum number of edges to include |
node_limit |
int | 512 |
Maximum number of nodes to include |
format |
string | "dot" |
Output format for the graph |
[cache] Section#
Bytecode cache configuration:
[cache]
enabled = true # Enable bytecode caching
[build]
dir = ".jac" # Base directory for all build artifacts (cache, packages, client, data)
All build artifacts are organized under the [build].dir directory (default .jac/):
.jac/cache/- Bytecode cache files.jac/packages/- Installed Python packages.jac/client/- Client-side build artifacts.jac/data/- Runtime data (databases, sessions)
[scripts] Section#
Custom scripts and shortcuts:
[scripts]
dev = "jac run main.jac"
build = "jac build main.jac --typecheck"
test = "jac test tests/"
lint = "jac check ."
format = "jac format . --fix"
Run scripts with:
[plugins] Section#
Plugin configuration:
[plugins]
discovery = "auto" # "auto", "manual", or "disabled"
enabled = ["jac-byllm"] # Explicitly enabled plugins
disabled = [] # Explicitly disabled plugins
# Plugin-specific configuration
[plugins.jac-byllm]
model = "gpt-4"
temperature = 0.7
[environment] and [environments] Sections#
Environment-based configuration profiles:
[environment]
default_profile = "development"
[environments.development]
[environments.development.run]
cache = false
[environments.development.plugins.jac-byllm]
model = "gpt-3.5-turbo"
[environments.production]
inherits = "development" # Inherit from another profile
[environments.production.run]
cache = true
[environments.production.plugins.jac-byllm]
model = "gpt-4"
Activate a profile:
Environment Variable Interpolation#
Use environment variables in configuration values:
[plugins.jac-byllm]
api_key = "${OPENAI_API_KEY}" # Required variable
model = "${MODEL_NAME:-gpt-3.5-turbo}" # With default value
secret = "${API_SECRET:?API secret is required}" # Required with custom error
| Syntax | Description |
|---|---|
${VAR} |
Use variable (error if not set) |
${VAR:-default} |
Use default if not set |
${VAR:?error} |
Custom error message if not set |
Dependency Management#
Installing Dependencies#
# Install all dependencies
jac install
# Install including dev dependencies
jac install --dev
# Install a specific package
jac install requests
# Install and add to jac.toml
jac add requests>=2.28.0
# Add a dev dependency
jac add --dev pytest
Packages Directory#
Dependencies are installed to the packages/ directory in your project root:
The packages/ directory is automatically added to the Python path when running Jac code.
CLI Integration#
Most jac.toml settings can be overridden via CLI flags:
# Override run settings
jac run main.jac --no-cache --session my-session
# Override test settings
jac test --verbose --fail-fast --max-failures 5
# Override serve settings
jac start --port 3000
# Override build settings
jac build main.jac --typecheck
Complete Example#
Here's a comprehensive jac.toml example:
# jac.toml - Jac Project Configuration
[project]
name = "my-ai-app"
version = "1.0.0"
description = "An AI-powered application built with Jac"
authors = ["Developer <dev@example.com>"]
license = "MIT"
entry-point = "main.jac"
[project.urls]
homepage = "https://my-ai-app.example.com"
repository = "https://github.com/user/my-ai-app"
#===============================================================================
# DEPENDENCIES
#===============================================================================
[dependencies]
jac-byllm = ">=0.4.8"
requests = ">=2.28.0"
pydantic = ">=2.0.0"
[dev-dependencies]
watchdog = ">=3.0.0" # Required for HMR
pytest = ">=8.2.1"
pytest-asyncio = ">=0.21.0"
[dependencies.git]
private-utils = { git = "https://github.com/myorg/utils.git", branch = "main" }
#===============================================================================
# COMMAND DEFAULTS
#===============================================================================
[run]
main = true
cache = true
[test]
directory = "tests"
verbose = true
fail_fast = false
[serve]
port = 8000
cl_route_prefix = "cl" # Client apps at /cl/<name>
base_route_app = "" # Set to app name to serve at /
[format]
fix = false
[check]
print_errs = true
warnonly = false
[dot]
depth = -1 # Unlimited depth
edge_limit = 512
node_limit = 512
#===============================================================================
# BUILD AND CACHE SETTINGS
#===============================================================================
[build]
typecheck = true
dir = ".jac" # All build artifacts go here (.jac/cache, .jac/packages, etc.)
[cache]
enabled = true
#===============================================================================
# PLUGINS
#===============================================================================
[plugins]
discovery = "auto"
[plugins.jac-byllm]
model = "${LLM_MODEL:-gpt-4}"
api_key = "${OPENAI_API_KEY}"
temperature = 0.7
#===============================================================================
# ENVIRONMENTS
#===============================================================================
[environment]
default_profile = "development"
[environments.development]
[environments.development.run]
cache = false
[environments.development.plugins.jac-byllm]
model = "gpt-3.5-turbo"
[environments.production]
inherits = "development"
[environments.production.run]
cache = true
[environments.production.plugins.jac-byllm]
model = "gpt-4"
#===============================================================================
# SCRIPTS
#===============================================================================
[scripts]
dev = "jac run main.jac"
build = "jac build main.jac --typecheck"
test = "jac test"
serve = "jac start --port 8000"
format = "jac format . --fix"
Project Discovery#
Jac automatically discovers jac.toml by searching from the current directory upward to the filesystem root. This means you can run Jac commands from any subdirectory within your project:
Programmatic Access#
You can access project configuration programmatically in Jac code:
import from jaclang.project { JacConfig, get_config };
with entry {
config = get_config();
if config {
print(f"Project: {config.project.name}");
print(f"Version: {config.project.version}");
print(f"Dependencies: {list(config.dependencies.keys())}");
}
}
Or in Python: