Skip to content

Scripting Languages

Crucible uses Lua for plugins, tools, and hooks. Fennel (a Lisp that compiles to Lua) is also supported.

Overview

LanguageBest ForKey Feature
LuaGeneral use, LLM-generated codeFamiliar syntax, simple
FennelPower users wanting macrosLisp syntax, compiles to Lua

Both languages can:

  • Define tools in a plugin’s spec table, served to agents and cru mcp alike
  • Register event hooks
  • Access the Crucible API (search, notes, graph)
  • Execute shell commands (with policy controls)

Lua

Lua is a simple, embeddable scripting language with massive adoption. Crucible embeds PUC Lua 5.4 via the mlua crate.

Strengths:

  • Familiar syntax (if you know JavaScript/Python)
  • LLM-friendly (models generate excellent Lua)
  • Simple and easy to debug

See Language Basics for syntax and examples.

Fennel

Fennel is a Lisp that compiles to Lua. It provides:

  • S-expression syntax
  • Compile-time macros
  • Full Lua interoperability
  • Pattern matching

Fennel files (.fnl) are compiled to Lua at load time, so they have the same runtime characteristics.

Choosing a Language

Use Lua when…

  • You want simple, readable code
  • LLMs will generate your plugins
  • You’re prototyping quickly
  • You prefer familiar syntax

Use Fennel when…

  • You love Lisp
  • You want compile-time macros
  • You’re building DSLs
  • You prefer s-expressions

Plugin Discovery

Place files in:

~/.config/crucible/plugins/ # Global personal
<runtimepath entry>/plugins/ # Opt-in extra trees, named in config.toml

Plugins are user-scoped: no kiln, project or workspace directory is searched on its own. See Creating Plugins for why, and for how runtimepath opts a tree in.

File extensions determine the runtime:

  • .lua — Lua
  • .fnl — Fennel (compiles to Lua)

Configuration

Crucible also loads configuration from ~/.config/crucible/init.lua. This allows customizing the TUI, defining keybindings, and more.

See Configuration for details.

Oil UI DSL

Both Lua and Fennel can build TUI components using the Oil (Obvious Interface Language) API. Oil provides a functional, React-like model where components are functions that return node trees.

-- Lua
local view = cru.oil.col({ gap = 1 },
cru.oil.text("Hello", { bold = true }),
cru.oil.when(loading, cru.oil.spinner())
)
;; Fennel
(local oil (require :oil))
(oil.col {:gap 1}
(oil.text "Hello" {:bold true})
(oil.when loading (oil.spinner)))

See Oil Lua API for the full Oil component reference; Scripted UI covers theming and statuslines.

See Also