CLI Reference
Scriptling includes a command-line interface for running scripts, interactive mode, and HTTP/MCP server.
Installation
Homebrew (macOS & Linux)
brew install paularlott/tap/scriptlingGitHub Releases
Download pre-built binaries from GitHub Releases:
| Platform | Architectures |
|---|---|
| Linux | AMD64, ARM64 |
| macOS | AMD64, ARM64 |
| Windows | AMD64, ARM64 |
Go Install
If you have Go installed:
go install github.com/paularlott/scriptling/scriptling-cli@latestBuild from Source
# Clone the repository
git clone https://github.com/paularlott/scriptling.git
cd scriptling
# Build for current platform
make build
# or use Task: task build
# Build for all platforms
make build-all
# or use Task: task build-allBasic Usage
Run a Script
scriptling script.pyPipe Script
echo 'print("Hello")' | scriptling
cat script.py | scriptlingInteractive Mode
scriptling --interactive
# or
scriptling -iLint Mode
Lint scripts for syntax errors without executing them:
# Lint a file
scriptling --lint script.py
# Lint from stdin
echo 'x = 1 +' | scriptling --lint
# JSON output format
scriptling --lint --lint-format json script.pyText output format:
script.py:3: expected token COLON (error)JSON output format:
{
"files_checked": 1,
"has_errors": true,
"errors": [
{
"file": "script.py",
"line": 3,
"message": "expected token COLON",
"severity": "error",
"code": "parse-error"
}
]
}The linter exits with code 0 if no errors are found, and code 1 if any errors exist.
Command Line Options
| Flag | Environment Variable | Description | Default |
|---|---|---|---|
-i, --interactive |
- | Start interactive mode | false |
-l, --lint |
- | Lint script files without executing | false |
--lint-format |
SCRIPTLING_LINT_FORMAT |
Output format for lint (text/json) | text |
--libdir |
SCRIPTLING_LIBDIR |
Directory to load libraries from | (current dir) |
--log-level |
SCRIPTLING_LOG_LEVEL |
Log level (trace/debug/info/warn/error) | info |
--log-format |
SCRIPTLING_LOG_FORMAT |
Log format (console/json) | console |
-S, --server |
SCRIPTLING_SERVER |
HTTP server address (host:port) | (disabled) |
--mcp-tools |
SCRIPTLING_MCP_TOOLS |
Directory containing MCP tools | (disabled) |
--mcp-exec-script |
- | Enable MCP script execution tool | false |
--bearer-token |
SCRIPTLING_BEARER_TOKEN |
Bearer token for authentication | none |
--allowed-paths |
SCRIPTLING_ALLOWED_PATHS |
Comma-separated allowed filesystem paths | (no restriction) |
--tls-cert |
SCRIPTLING_TLS_CERT |
TLS certificate file | none |
--tls-key |
SCRIPTLING_TLS_KEY |
TLS key file | none |
--tls-generate |
- | Generate self-signed certificate | false |
Environment Configuration
The CLI automatically loads environment variables from a .env file in the current directory (if it exists). This is useful for setting default values for flags without typing them on the command line.
Example .env file:
# Log configuration
SCRIPTLING_LOG_LEVEL=debug
SCRIPTLING_LOG_FORMAT=console
# Library directory
SCRIPTLING_LIBDIR=./mylibs
# Server configuration
SCRIPTLING_SERVER=:8000
SCRIPTLING_MCP_TOOLS=./tools
SCRIPTLING_BEARER_TOKEN=your-secret-token
# Filesystem restrictions
SCRIPTLING_ALLOWED_PATHS=/tmp/data,./uploadsScript Execution Modes
Scriptling supports three levels of filesystem access control:
| Mode | Flag | Filesystem Access | Path Restrictions |
|---|---|---|---|
| Full | (default) | All libraries | None |
| Restricted | --allowed-paths /path1,/path2 |
All libraries | Only specified paths |
| None | --allowed-paths - |
All libraries | No paths allowed |
Full Mode (default)
All libraries available, no restrictions:
scriptling script.pyRestricted Mode
All libraries available, but filesystem operations restricted to specified paths:
# Restrict to specific directories
scriptling --allowed-paths "/tmp/data,./uploads" script.py
# With relative paths
scriptling --allowed-paths "./data,../shared" script.py
# Via environment variable
SCRIPTLING_ALLOWED_PATHS="/var/www,./public" scriptling script.pyNo File Access Mode
Disable all filesystem access (useful for running untrusted scripts):
scriptling --allowed-paths - script.pyAll file operations (os.read_file, os.write_file, pathlib, glob, sandbox.exec_file) will be denied.
When a script tries to access a path outside the allowed directories:
import os
# This will raise an error if /etc/passwd is not in allowed paths
try:
content = os.read_file("/etc/passwd")
except Exception as e:
print(f"Access denied: {e}")
# Output: Access denied: access denied: path '/etc/passwd' is outside allowed directoriesAvailable libraries:
- Standard libraries:
json,math,random,re,time,base64,hashlib,urllib datetime- Date and time operationsyaml,toml- YAML and TOML parsinghtml.parser- HTML parsingrequests- HTTP clientos- Environment variables and file operations (path-restricted)pathlib,glob- File system access (path-restricted)secrets- Cryptographic random number generationscriptling.runtime- Runtime utilities including sandbox and background taskssubprocess- Process executionwait_for- Process monitoring- AI, agent, and MCP libraries
Accessing Environment Variables in Scripts
You can access environment variables from within Scriptling scripts using the os library:
import os
# Get a specific environment variable
api_key = os.getenv("API_KEY", "default-key")
print(f"API Key: {api_key}")
# Get all environment variables
env = os.environ()
print(f"Home: {env['HOME']}")
print(f"Path: {env['PATH']}")HTTP Server Mode
Start an HTTP server with optional MCP tools:
# Start HTTP server on port 8000
scriptling --server :8000 setup.py
# With TLS (self-signed certificate)
scriptling --server :8443 --tls-generate setup.py
# With MCP tools from directory
scriptling --server :8000 --mcp-tools ./tools setup.py
# With MCP script execution tool
scriptling --server :8000 --mcp-exec-script setup.py
# With both MCP tools and exec tool
scriptling --server :8000 --mcp-tools ./tools --mcp-exec-script setup.py
# With authentication
scriptling --server :8000 --bearer-token my-secret-token setup.py
# With filesystem restrictions
scriptling --server :8000 --allowed-paths "/var/www,./uploads" setup.pyMCP Script Execution Tool
The --mcp-exec-script flag enables a built-in MCP tool that allows LLMs to execute Scriptling code directly:
# Enable script execution tool
scriptling --server :8000 --mcp-exec-script setup.py
# Combine with custom tools
scriptling --server :8000 --mcp-tools ./tools --mcp-exec-script setup.pyTool Details:
- Name:
execute_script - Description: Execute Scriptling code and return the result. Scriptling is a Python 3-like scripting language.
- Parameters:
code(string, required): Scriptling code to execute
Return Behavior:
- Output from
print()statements is automatically captured and returned - For structured data (JSON), use
import scriptling.mcp.tooland calltool.return_object(data) - For text output, use
tool.return_string(text)
Usage Example:
# Call the tool via MCP - print() output is captured
curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc":"2.0",
"id":1,
"method":"tools/call",
"params":{
"name":"execute_script",
"arguments":{
"code":"for i in range(1, 21, 3):\n print(i)"
}
}
}'Returning Structured Data:
import scriptling.mcp.tool as tool
# Return JSON object
data = {"users": ["Alice", "Bob"], "count": 2}
tool.return_object(data)
# Or return text
tool.return_string("Operation completed successfully")The tool description instructs LLMs to use help(topic) to discover available functions and libraries:
# Get help on built-in functions
help('builtins')
# Get help on string methods
help('str')
# Get help on a library
import json
help('json')MCP Tools
Tools consist of two files: a .toml metadata file and a .py script file.
Metadata File (.toml)
Defines the tool’s description, parameters, and registration mode:
hello.toml:
description = "Greet a person by name"
keywords = ["hello", "greet", "welcome"]
# Optional: Registration mode
# discoverable = false (default) - Native mode: tool appears in tools/list, directly callable
# discoverable = true - Discovery mode: hidden from tools/list, found via tool_search
[[parameters]]
name = "name"
type = "string"
description = "Name of the person to greet"
required = true
[[parameters]]
name = "times"
type = "int"
description = "Number of times to repeat the greeting"Parameter Types:
| Type | Aliases | Description |
|---|---|---|
string |
Text values | |
int |
integer |
Integer numbers |
float |
number |
Floating point numbers |
bool |
boolean |
True/false values |
array:string |
Array of strings | |
array:number |
array:int, array:integer, array:float |
Array of numbers |
array:bool |
array:boolean |
Array of booleans |
Parameter Fields:
| Field | Required | Description |
|---|---|---|
name |
Yes | Parameter name |
type |
Yes | Data type (see table above) |
description |
Yes | Description shown to the LLM |
required |
No | Whether the parameter must be provided (default: false) |
Registration Modes:
- Native mode (default): Tool appears in
tools/listand can be called directly - Discovery mode (
discoverable = true): Tool is hidden fromtools/list, searchable viatool_search, and callable viaexecute_tool
Script File (.py)
Implements the tool logic using the scriptling.mcp.tool library:
hello.py:
import scriptling.mcp.tool as tool
# Get parameters with defaults
name = tool.get_string("name", "World")
times = tool.get_int("times", 1)
# Implement tool logic
greetings = []
for i in range(times):
greetings.append(f"Hello, {name}!")
result = "\n".join(greetings)
# Return result
tool.return_string(result)Available Tool Functions:
# Get parameters
tool.get_string(name, default="") # Get string parameter
tool.get_int(name, default=0) # Get integer parameter
tool.get_float(name, default=0.0) # Get float parameter
tool.get_bool(name, default=False) # Get boolean parameter
tool.get_list(name, default=[]) # Get list parameter
# Return results
tool.return_string(text) # Return text result
tool.return_object(obj) # Return object as JSON
tool.return_toon(obj) # Return object as TOON format
tool.return_error(message) # Return error messageComplete Example
A tool that calculates the sum of two numbers:
add.toml:
description = "Calculate the sum of two numbers"
keywords = ["math", "add", "sum", "calculate"]
discoverable = true # Hidden from tools/list, searchable
[[parameters]]
name = "a"
type = "int"
description = "First number"
required = true
[[parameters]]
name = "b"
type = "int"
description = "Second number"
required = trueadd.py:
import scriptling.mcp.tool as tool
a = tool.get_int("a")
b = tool.get_int("b")
result = a + b
tool.return_string(f"{a} + {b} = {result}")Testing Tools
# Start server with MCP tools
scriptling --server :8000 --mcp-tools ./tools setup.py &
# List available tools
curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# Call a native tool directly
curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"hello","arguments":{"name":"Alice","times":2}}}'
# Search for discoverable tools
curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"tool_search","arguments":{"query":"math"}}}'
# Execute a discoverable tool
curl -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"execute_tool","arguments":{"name":"add","arguments":{"a":5,"b":3}}}}'Features
- File execution: Run Scriptling scripts from files
- Stdin execution: Pipe scripts to stdin
- Interactive mode: REPL-like interactive execution
- Lint mode: Check scripts for syntax errors without execution
- HTTP Server: Start HTTP server with custom routes via
--server - MCP Server: Serve tools via Model Context Protocol with
--mcp-tools - MCP Script Execution: Allow LLMs to execute Scriptling code via
--mcp-exec-script - Path restrictions: Restrict filesystem access with
--allowed-paths - Custom libraries: Load libraries from custom directories with
--libdir - Environment configuration: Auto-load settings from
.envfile - Configurable logging: Set log level with
--log-level(debug, info, warn, error) - Cross-platform: Built for Linux, macOS, and Windows on AMD64 and ARM64
- Minimal size: Optimized with stripped binaries (~10MB)
Examples
REST API Client
scriptling api_client.py# api_client.py
import json
import requests
response = requests.get("https://api.example.com/users")
if response.status_code == 200:
users = response.json()
for user in users:
print(user["name"])HTTP Server with Routes
scriptling --server :8000 setup.py# setup.py
import scriptling.runtime as runtime
# Register routes (handler functions referenced as "module.function")
runtime.http.get("/api/hello", "handlers.hello")
runtime.http.post("/api/echo", "handlers.echo")# handlers.py
import scriptling.runtime as runtime
def hello(request):
return runtime.http.json(200, {"message": "Hello, World!"})
def echo(request):
return runtime.http.json(200, request.json())Help
scriptling --help