Draconic
The Draconic language: a scripting language based off Python to run user scripts on the server safely.
Install / Use
/learn @avrae/DraconicREADME
draconic
The Draconic scripting language, designed to allow a safe in-memory runtime for user scripting with bindings to native APIs hosted in the parent application.
Requires Python 3.8+.
Notable Differences from Python
The Draconic language is based on, and implemented in, the CPython implementation of the Python language. However, there are a number of notable differences between Draconic and Python:
In-Place Operator Unfurling
In Python, in-place operators (e.g. a += 1) are handled differently from binary operators and assignments (
e.g. a = a + 1). In Draconic, all in-place operators are unfurled to their binary-operator equivalent. In most cases
this does not create a semantic difference, except in the following cases:
Dict/Set Union Operations
Python
>>> a = {"a": 1, "b": 2}
>>> b = {"b": 3, "c": 4}
>>> a_reference = a
>>> a |= b
>>> a
{"a": 1, "b": 3, "c": 4}
>>> a_reference
{"a": 1, "b": 3, "c": 4}
>>> a is a_reference
True
Draconic
>>> a = {"a": 1, "b": 2}
>>> b = {"b": 3, "c": 4}
>>> a_reference = a
>>> a |= b
>>> a
{"a": 1, "b": 3, "c": 4}
>>> a_reference
{"a": 1, "b": 2}
>>> a is a_reference
False
Use dict.update() or set.update() instead for an in-place operation.
Function Nonlocal References
Python
>>> a = 1
>>> def incr_locally():
... a += 1
... return a
>>> incr_locally()
UnboundLocalError: local variable 'a' referenced before assignment
Draconic
>>> a = 1
>>> def incr_locally():
... a += 1
... return a
>>> incr_locally()
2
Unequal Patma Bindings
While Python checks that all bindings in a pattern matching case with multiple options are the same across all branches, Draconic does not do any such check.
Python
>>> a = 1
>>> match a:
... case (1 as one) | (2 as two):
... print(one)
SyntaxError: alternative patterns bind different names
Draconic
>>> a = 1
>>> match a:
... case (1 as one) | (2 as two):
... print(one)
1
Function Dunder Attributes
As access to __dunder__ attributes is not allowed in Draconic, the function.__name__ and function.__doc__
attributes are exposed as function.name and function.doc instead.
Python
>>> def foo():
... """I am foo"""
... pass
>>> print(foo.__name__)
foo
>>> print(foo.__doc__)
I am foo
Draconic
>>> def foo():
... """I am foo"""
... pass
>>> print(foo.name)
foo
>>> print(foo.doc)
I am foo
Try/Except
As Draconic currently has no user-defined class implementation, it is impossible to provide a type by name to an
except clause. Instead, Draconic requires except clause types to be a string literal or tuple of string literals.
These are matched against the name of the exception, with no subclass checking.
Python
>>> try:
... 1/0
... except Exception:
... print("I catch all exceptions!")
... except ZeroDivisionError:
... print("You divided by zero!")
I catch all exceptions!
Draconic
>>> try:
... 1/0
... except "Exception":
... print("I catch all exceptions!")
... except "ZeroDivisionError":
... print("You divided by zero!")
You divided by zero!
Starred Unpacking
Assigning to a starred variable outside of a tuple or list in Python throws a SyntaxError, but is valid in Draconic
Python
>>> *a = [1, 2, 3]
SyntaxError: starred assignment target must be in a list or tuple
Draconic
>>> *a = [1, 2, 3]
>>> a
[1, 2, 3]
This has syntactical equivalents in Python:
>>> *a, = [1, 2, 3]
>>> [*b] = [1, 2, 3]
>>> (*c,) = [1, 2, 3]
>>> assert a == b == c == [1, 2, 3]
Related Skills
node-connect
347.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
claude-opus-4-5-migration
108.0kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
108.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
model-usage
347.2kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
