Crystal Lattice
Open Source

For people who outgrow
one-size-fits-all agents.

Crystal Lattice is a model-native agent platform: the harness changes around the model, including its system message, tool schema, request behavior, provider-native state, and UI controls. Built-in plugins provide Codex, Claude, Gemini, Qwen, Kimi, and Grok-style defaults, and your config can replace them.

Getting started

  1. 01

    Install the CLI

    Install the local Crystal Lattice runtime for your platform. This is the process that owns agents, sessions, tools, and client connections.

    Terminal

    $
    curl -fsSL https://download.crystallattice.dev/crystal-lattice-cli/install.sh | bash

    macOS Intel or Apple silicon · Linux x64 or ARM64

    Installation guide
  2. 02

    Start a workspace

    Run Crystal Lattice in the project directory where you want the agent to work, expose the local server, and enable same-network discovery.

    bash — 80×24
    $ mkdir -p ~/crystal-lattice-demo
    $ cd ~/crystal-lattice-demo
    $ crystal-lattice \
    --server \
    --console \
    --config-local \
    --host 0.0.0.0 \
    --port 9000 \
    --enable-bonjour
  3. 03

    Download Crystal Lattice Desktop

    Install the app UI after the CLI runtime is available. The current macOS DMG contains the app only and does not install or launch the CLI.

    macOS

    Universal DMG · Apple silicon + Intel

    macOS 14.0+ · Version 0.9.0

    Download for macOS

    All platforms

    Windows Desktop Coming soon
    Linux Desktop Coming soon
  4. 04

    Connect Desktop to the workspace

    Desktop uses the local computer by default. Enter the same port used when starting the CLI runtime.

    Enter the port

    The host defaults to 127.0.0.1. For the command above, enter port 9000.

    9000
  5. 05

    Get the mobile app

    Public App Store and Google Play distribution are planned. The working waitlist form will be added only after its AWS service is deployed and reviewed.

    iOS Coming soon
    Android Coming soon
    Join the mobile release waitlist Form added in the waitlist phase
  6. 06

    Connect from mobile

    Use the same runtime sessions from a phone through a manual address, automatic local discovery, or a self-hosted bridge.

    Manual address

    Enter the runtime's local HTTP address when you already know it.

    http://192.168.1.42:9000

    Automatic discovery

    Find the runtime automatically while both devices are on the same network.

    crystal-lattice ... --enable-bonjour

    Bridge pairing

    Use a reachable self-hosted bridge when the phone is outside the local network.

    crystal-lattice ... --bridge-url wss://<bridge>/ws/websocket

Built-in model-family harnesses

Codex-style toolsClaude-style workflowsGemini-oriented toolsQwen-oriented toolsKimi-oriented toolsGrok-oriented tools

Computer to phone

Start at your desk. Keep going from your phone.

Start Crystal Lattice in the project folder where you want the agent to work. The terminal UI can stay open, but the work is not trapped there: the app UIs can open the same sessions and watch responses stream.

On the same Wi-Fi, Crystal Lattice Control can find your computer automatically. Choose Automatic Discovery, select your computer, and continue the same workspace from your phone.

Automatic discovery uses the local network. If your phone is outside that network, use the bridge section below.

Run the local workspace

01

Install the CLI

Choose the installation method for your platform above, then verify that the command is available.

Choose an installation method
bash — 80×24
$ crystal-lattice --help
02

Start Crystal Lattice with local discovery

bash — 80×24
mkdir -p ~/crystal-lattice-demo
cd ~/crystal-lattice-demo
crystal-lattice \
--server \
--console \
--config-local \
--host 0.0.0.0 \
--port 9000 \
--enable-bonjour
03

Open the mobile app

Open Crystal Lattice Control, choose Automatic Discovery, and select your computer.

Outside your local network

Pair through a self-hosted bridge

Hosted bridge service is coming soon. Today, when your phone is not on the same network as your computer, deploy your own bridge and pair through it.

The bridge gives Crystal Lattice clients a way to reconnect from outside the local network. Local bridge hosting is useful for development and testing, but production use should deploy the bridge somewhere reachable.

Deploy the bridge on AWS

01

Create the bridge deployment

bash — 80×24
ALLOW_AWS_DEPLOY=1 deploy/aws-ec2/build.sh \
--profile secure \
--stack-name crystal-lattice-bridge \
--region us-east-1
ALLOW_AWS_DEPLOY=1 deploy/aws-ec2/up.sh \
--profile secure \
--stack-name crystal-lattice-bridge \
--region us-east-1
02

Start Crystal Lattice with the bridge URL

bash — 80×24
crystal-lattice \
--server \
--console \
--config-local \
--host 0.0.0.0 \
--port 9000 \
--bridge-url wss://<your-cloudfront-domain>/ws/websocket
03

Pair from the phone

Open Crystal Lattice Control, choose Bridge Service, enter the bridge URL, select your computer, and enter the pairing code.

Model-native harnesses

Stop forcing every model through the same prompt and tools.

Model-native means Crystal Lattice changes the harness around the model: system message, tool schema, request behavior, provider-native state, and UI controls. The built-in defaults do this with plugins, and those plugins can be replaced.

Model familyBuilt-in harnessWhat changes
Codex / GPT coding modelscodex-toolsCodex-style shell tools, apply patch semantics, skills block, model-family system instructions.
Claudeclaude-toolsClaude-oriented tool schema and workflow conventions.
Geminigemini-tools + compaction pluginsGemini-oriented system message and tool behavior, optional compaction flow.
Qwenqwen-toolsQwen-oriented tool and instruction style.
Kimikimi-toolsKimi-oriented tools and prompt behavior.
Grokgrok-toolsGrok-oriented tools and request behavior.
OpenAI Responsesopenai_responsesResponses-native reasoning, usage/cost metadata, attachments, prompt caching, native compaction.
OpenRouteropenrouterOpenRouter model routing, reasoning/web/image extensions depending on provider path.

Native provider features

Provider-specific behavior can become real UI.

Some capabilities are not generic chat settings. Reasoning effort, verbosity, usage, token counts, cache information, duration, and cost metadata depend on the provider path.

Crystal Lattice lets provider and feature plugins expose those controls and outputs directly to the UI, so native behavior is visible instead of hidden behind a generic wrapper.

Reasoning and verbosity

Expose model-specific controls when the provider supports them.

Session settings with magnified medium reasoning effort and medium verbosity controls.

Usage and cost transparency

Surface token, cache, duration, and cost metadata when the provider supplies it.

A completed coding-plan response with magnified input, estimated cached, completion, reasoning-token, and estimated-cost metadata.

Everything is replaceable

Serious users eventually disagree with the harness.

Crystal Lattice treats that as normal. Providers, provider extensions, features, tools, application actions, session behavior, and UI elements are all plugin surfaces.

The built-in plugins give you useful defaults. Your own plugins can replace the parts your workflow disagrees with, and config can point at those plugins without waiting for upstream approval.

Code examples are illustrative placeholders, not final API.

Provider

Add native support for a model API.

python
# Placeholder example, not final API.
class MyProvider:
    name = "my_provider"

    def to_native_messages(self, messages, state, *, context=None):
        return convert_to_my_api(messages)

    def stream_api(self, native_messages, state):
        yield from call_my_model(native_messages, state)

Provider extension

Surface provider metadata, reasoning, citations, or UI fields.

python
# Placeholder example, not final API.
class UsageFooter:
    name = "usage_footer"

    def finalize(self, final_messages, native_messages, state):
        return add_usage_metadata(final_messages, state)

    def get_ui_elements(self, config, context=None):
        return [
            {"ui_type": "message_footer", "data": "metadata.total_cost"}
        ]

Feature

Transform context, request behavior, or final messages.

python
# Placeholder example, not final API.
class ProjectContext:
    name = "project_context"

    def to_native_messages(self, messages, native_messages, state):
        return inject_project_context(native_messages)

Tool

Expose Python, Node, Bash, or MCP-backed capabilities.

python
# Placeholder example, not final API.
class SearchTickets:
    name = "search_tickets"

    def get_tool_schemas(self, state):
        return [ticket_search_schema]

    def execute_tool(self, tool_name, payload, state):
        return search_linear_or_jira(payload)

Application plugin

Add session-level workflow actions.

python
# Placeholder example, not final API.
class CreateReleaseNotes:
    name = "release_notes"

    def get_actions(self, state):
        return [
            {
                "id": "release_notes.create",
                "label": "Create release notes",
            }
        ]

    def execute_action(self, app, action_id, params, context, state):
        return create_release_notes(app, params)

UI schema

Render settings and actions in app UIs without hardcoding them.

python
# Placeholder example, not final API.
def get_ui_elements(self, config, context=None):
    return [
        {
            "ui_type": "session_action",
            "label": "Sync down",
            "action_id": "cloud.sync_down",
        },
        {
            "type": "select",
            "key": "reasoning_effort",
            "label": "Reasoning effort",
        },
    ]

Session workbench

Treat sessions as workspaces, not disposable chats.

Agent work is more than a transcript. Built-in session plugins add reusable actions, checkpoints, settings, and other controls to the session workflow.

The workbench is plugin-driven too: built-in plugins provide the default behavior, and your own plugins can add or replace workflow actions.

Chat actions

Message and session actions exposed by plugins.

Session actions menu showing plugin-provided copy, title, deletion, summarization, and native compaction controls alongside session settings.

Snapshots

Create, inspect, select, and restore session checkpoints.

Snapshots dialog showing automatic pre-compaction and pre-deletion recovery points with Select, Restore, and Delete controls.

Settings and plugins

Per-session controls from plugin UI schema.

Session settings showing OpenAI model, reasoning, verbosity, prompt cache, web search, and compaction transcript controls contributed by plugins.

Plugin authoring

Ask an agent to plan the plugin.

A user-owned plugin workflow still needs product polish, but the design goal is straightforward: inspect the docs, pick the right plugin type, copy the closest template, write tests, and load the plugin from config.

prompt
I want to build a Crystal Lattice plugin.

Please inspect the plugin documentation in this repository, especially:
- plugins/docs/index.md
- plugins/docs/tool-plugins.md
- plugins/docs/application-plugins.md
- plugins/docs/provider-plugins.md
- plugins/docs/provider-extensions.md
- plugins/docs/feature-plugins.md
- plugins/docs/ui-elements.md
- plugins/docs/plugin-packaging-and-loading.md

Goal:
Create a plugin that [describe what I want].

Please:
1. Identify whether this should be a provider, provider extension, feature, tool, or application plugin.
2. Find the closest existing plugin or template to copy from.
3. Explain what UI, if any, the plugin should expose.
4. Propose the file layout.
5. Draft an implementation plan.
6. Tell me what tests should be added before coding.
json
{
  "plugins": [
    "path:./plugins/my-custom-plugin"
  ]
}

Python SDK

Automate the same harness with Python.

When the work becomes repetitive, use the same configured agents and plugins from Python. The example below sketches a short sales-letter workflow over a CSV of leads.

The final webpage should verify this against the current SDK and may add a small helper if the public API needs a simpler "run until final" path.

sdk-api-needs-verification
python
import pandas as pd
from agent_app import AgentApplication

app = AgentApplication.from_config("./.crystal/config.json")
leads = pd.read_csv("leads.csv")

def draft(row):
    session = app.create_session(agent_id="codex-openrouter")
    app.add_message(
        session.session_id,
        "user",
        f"""
        Write a concise first sales email.

        Name: {row.name}
        Role: {row.role}
        Company: {row.company}
        Notes: {row.notes}
        """,
    )
    result = app.run_until_final(session.session_id)
    return result.content

leads["draft"] = leads.apply(draft, axis=1)
leads.to_csv("drafts.csv", index=False)

Use the harness you can inspect and replace.

Start with built-in model-family plugins, run Crystal Lattice on your computer, continue from phone or app UI, and replace the parts of the harness your workflow disagrees with.