Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Evincere/klisk/llms.txt

Use this file to discover all available pages before exploring further.

Klisk uses a combination of YAML configuration files and environment variables to manage project settings and credentials.

Configuration File

klisk.config.yaml

The root configuration file defines project settings:
klisk.config.yaml
entry: src/main.py
name: "MyAgent"
studio:
  port: 3000
api:
  port: 8000

Configuration Schema

ProjectConfig

Klisk uses Pydantic models to parse and validate configuration:
# From config.py
from pydantic import BaseModel

class StudioConfig(BaseModel):
    port: int = 3000

class ApiConfig(BaseModel):
    port: int = 8000

class ProjectConfig(BaseModel):
    entry: str = "src/main.py"
    name: str = "MyAgent"
    studio: StudioConfig = StudioConfig()
    api: ApiConfig = ApiConfig()
entry
string
default:"src/main.py"
Path to the Python file containing agent definitions (relative to project root)
name
string
default:"MyAgent"
Project display name shown in Studio and CLI output
studio.port
number
default:3000
Port for Studio interface (reserved for future use)
api.port
number
default:8000
Port for development server and API endpoints

Loading Configuration

The ProjectConfig.load() method reads and validates configuration:
# From config.py
@classmethod
def load(cls, project_dir: str | Path) -> ProjectConfig:
    config_path = Path(project_dir) / "klisk.config.yaml"
    if not config_path.exists():
        return cls()  # Use defaults
    with open(config_path) as f:
        data = yaml.safe_load(f) or {}
    return cls.model_validate(data)
If klisk.config.yaml is missing, Klisk uses default values:
config = ProjectConfig.load("/path/to/project")
# config.entry == "src/main.py"
# config.name == "MyAgent"
# config.api.port == 8000

Environment Variables

Store API keys and secrets in a .env file at the project root.

API Keys

Klisk loads environment variables using python-dotenv:
.env
OPENAI_API_KEY=sk-your-key-here
ANTHROPIC_API_KEY=sk-ant-your-key-here
GEMINI_API_KEY=your-key-here
These are loaded automatically when you run klisk dev or klisk run:
# From dev.py
from dotenv import load_dotenv

project_path = resolve_project(name_or_path)
load_dotenv(project_path / ".env")  # Loads .env into os.environ
.env files should never be committed to version control. Add .env to .gitignore to prevent accidental exposure.

Multi-Provider Support

Klisk uses LiteLLM under the hood, which supports multiple providers. Set the appropriate API key for your chosen model:
OPENAI_API_KEY=sk-your-key-here

Custom Environment Variables

You can define custom environment variables for your tools:
.env
OPENAI_API_KEY=sk-your-key-here

# Custom variables for your tools
WEATHER_API_KEY=your-weather-key
DATABASE_URL=postgresql://localhost/mydb
DEBUG=true
Access them in your tools using os.environ:
src/tools/weather.py
import os
from klisk import tool

@tool
async def fetch_weather(city: str) -> str:
    """Get current weather for a city."""
    api_key = os.environ.get("WEATHER_API_KEY")
    if not api_key:
        return "Weather API key not configured"
    
    # Call weather API with api_key
    ...

Port Configuration

The development server uses the port specified in klisk.config.yaml:
# From dev.py
config = ProjectConfig.load(project_path)

typer.echo(f"  Studio + API: http://localhost:{config.api.port}")
typer.echo(f"  Project:      {project_path}")
typer.echo("  Watching for changes...")

app = create_app(project_path)
run_server(app, host="0.0.0.0", port=config.api.port)

Port Conflicts

If the configured port is already in use, Klisk will fail to start:
ERROR:    [Errno 48] Address already in use
Change the port in klisk.config.yaml:
api:
  port: 8001  # Use a different port

Workspace Configuration

In workspace mode (klisk dev without arguments), Klisk loads all projects from ~/.klisk/projects/:
# From dev.py
if name_or_path is None:
    # Workspace mode: load all projects
    from klisk.core.discovery import load_all_project_envs
    from klisk.core.paths import PROJECTS_DIR

    load_all_project_envs()  # Load .env from all projects

    port = 8000
    typer.echo(f"  Studio + API: http://localhost:{port}")
    typer.echo(f"  Workspace:    {PROJECTS_DIR}")
    typer.echo("  Watching all projects for changes...")

    app = create_app(None)
    run_server(app, host="0.0.0.0", port=port)
In workspace mode, the port defaults to 8000 and cannot be customized per-project. All projects share a single server instance.

Model Configuration

Curated Model Lists

The Studio provides curated model lists for common providers:
# From app.py
_CURATED_MODELS: dict[str, list[str]] = {
    "openai": [
        "gpt-5.2",
        "gpt-5.2-pro",
        "gpt-5.1",
        "gpt-5",
        "gpt-5-mini",
        "gpt-5-nano",
        "gpt-5-pro",
        "gpt-4.1",
        "gpt-4.1-mini",
        "gpt-4.1-nano",
        "o4-mini",
        "o3",
        "o3-mini",
        "o3-pro",
        "o1",
        "o1-mini",
        "o1-pro",
    ],
    "anthropic": [
        "claude-opus-4-6",
        "claude-opus-4-5",
        "claude-opus-4-1",
        "claude-sonnet-4-5",
        "claude-haiku-4-5",
    ],
    "gemini": [
        "gemini-3-pro-preview",
        "gemini-3-flash-preview",
        "gemini-2.5-pro",
        "gemini-2.5-flash",
        "gemini-2.5-flash-lite",
        "gemini-2.0-flash",
        "gemini-2.0-flash-lite",
    ],
}

Model Filtering

Klisk filters out legacy and non-chat models to keep dropdowns clean:
# From app.py
_EXCLUDE_PREFIXES = (
    "ft:", "gpt-3.5", "gpt-4-", "gpt-4-32k", "chatgpt-",
    "claude-3-", "claude-4-",
    "gemini-pro", "gemini-exp-", "gemini-gemma-", "gemma-",
    "gemini-1.5-", "learnlm-", "gemini-robotics-",
)
_EXCLUDE_SUBSTRINGS = (
    "realtime", "audio", "search-preview", "vision",
    "deep-research", "container", "-codex", "-chat",
    "-tts", "-live-", "image-generation",
    "-exp-", "thinking-exp", "computer-use",
)
You can still use any model supported by LiteLLM by selecting “Custom” in the Studio or specifying it directly in your code.

Runtime Configuration

Some settings are determined at runtime and cannot be configured:

Server Host

The dev server always binds to 0.0.0.0 (all interfaces):
# From dev.py
run_server(app, host="0.0.0.0", port=config.api.port)
This allows access from other devices on your network at http://<your-ip>:8000.

WebSocket Endpoints

WebSocket endpoints are fixed:
  • /ws/chat — agent interactions
  • /ws/reload — hot reload notifications

Static Files

The Studio UI is served from:
  1. Installed package: klisk/studio_dist/ (production)
  2. Development: studio/dist/ relative to repo root (dev mode)
# From app.py
def _find_studio_dist() -> Path | None:
    import importlib.resources
    # 1. Inside the installed package
    pkg_dist = Path(str(importlib.resources.files("klisk"))) / "studio_dist"
    if pkg_dist.exists():
        return pkg_dist
    # 2. Development fallback
    dev_dist = Path(__file__).resolve().parent.parent.parent.parent / "studio" / "dist"
    if dev_dist.exists():
        return dev_dist
    return None

Configuration Best Practices

Use .env for secrets

Never hardcode API keys in configuration or source files

Commit klisk.config.yaml

Configuration should be versioned and shared with your team

Document custom variables

Add comments to .env.example explaining what each variable does

Use descriptive project names

Project names appear in Studio and CLI output—make them clear

Environment Precedence

Environment variables are loaded in this order (later overrides earlier):
  1. System environment variables (export OPENAI_API_KEY=...)
  2. .env file in project root
  3. Runtime overrides (e.g., command-line flags)
# System environment takes precedence
export OPENAI_API_KEY=sk-system-key

# .env file (ignored if already set)
OPENAI_API_KEY=sk-dotenv-key

# Final value: sk-system-key

Configuration Validation

Pydantic validates configuration at load time:
api:
  port: "not a number"  # ❌ ValidationError: port must be int
api:
  port: -1  # ✅ Parses successfully (no range validation)
Klisk does not validate port ranges or check if ports are available. Invalid ports will cause runtime errors when starting the server.

Debugging Configuration

Use Python to inspect loaded configuration:
from pathlib import Path
from klisk.core.config import ProjectConfig

config = ProjectConfig.load(Path.cwd())
print(config.model_dump_json(indent=2))
Output:
{
  "entry": "src/main.py",
  "name": "MyAgent",
  "studio": {
    "port": 3000
  },
  "api": {
    "port": 8000
  }
}

Advanced: Programmatic Configuration

You can load and modify configuration programmatically:
from pathlib import Path
from klisk.core.config import ProjectConfig, ApiConfig

# Load existing config
config = ProjectConfig.load(Path("/path/to/project"))

# Modify settings
config.api.port = 9000
config.name = "CustomAgent"

# Save (you need to implement serialization)
import yaml
config_path = Path("/path/to/project") / "klisk.config.yaml"
with open(config_path, "w") as f:
    yaml.dump(config.model_dump(exclude_defaults=True), f)

Configuration Schema Reference

entry
string
Python file path containing agent definitions
name
string
Project display name
studio
object
api
object

Build docs developers (and LLMs) love