AetherScript
AetherScript is a small, interpreted programming language with its own Aether Studio IDE, available as both a standalone Windows app and a Visual Studio Code extension. Both versions include a syntax-highlighted editor, custom interpreter, run controls, output console, file actions, and language quick reference.
Try it
Windows installer
Run AetherScript Studio Setup 0.9.10.exe and choose a per-user installation folder. Setup creates Start Menu and desktop shortcuts, adds aetherpip to your user PATH, and launches AetherScript Studio when it finishes. On first launch, choose Standalone AetherScript libraries for the three starter libraries or Multiple AetherScript libraries for all 75 additional libraries. You can also install individual bundled libraries later with aetherpip install <library-name>. Reopening AetherScript Studio launches the IDE directly.
The installer adds aetherpip to your user PATH, so bundled-library commands such as aetherpip list and aetherpip install numpy work from any folder. Open a new terminal after installation so it receives the updated PATH. For commands that take a file, pass its path: aetherpip run "C:\Projects\hello.aether" works from anywhere. To install a local handmade library, use aetherpip install "C:\Projects\my-library.aether"; changing into its folder is only needed if you want to use a relative filename.
The installer does not install Python or modify another language's installation. The app is not code-signed, so Windows may display a SmartScreen warning.
VS Code extension
Install the aetherscript-0.9.10.vsix in VS Code, or open this project and press F5 to launch an Extension Development Host. Open the Command Palette and choose AetherScript: Open Aether Studio. You can also open a .aether file and use Ctrl+F5.
To run the tests, use npm test. To build both distributables, run npm install, npm run package, and npm run desktop:exe. The extension is output as a .vsix in the project directory; the Windows installer is output in release/.
- Aether Trace (
✦ Trace in Aether Studio or AetherScript: Trace File in VS Code) runs the program and shows statement-by-statement snapshots of visible variables. The trace is capped at 500 steps, includes steps reached before a runtime error, and does not change ordinary Run behavior. VS Code also binds it to Ctrl+Shift+F5 (Cmd+Shift+F5 on macOS).
- Spell Map in Aether Studio lists
spell, def, function, and procedure definitions as you type; select one to jump to its declaration. In VS Code, AetherScript: Navigate Spells opens a searchable spell picker, and the standard Outline view also lists spells.
- Format in either Aether Studio editor fixes indentation for AetherScript and Python-style blocks. VS Code also provides syntax diagnostics, keyword/library completions, AetherScript: Format Document, and the standard Shift+Alt+F formatting shortcut.
These features are built into AetherScript's interpreter and editors, including variable-snapshot tracing and spell navigation. They work without Python or external debugger extensions.
Publish to the Visual Studio Marketplace
- Create a publisher at Visual Studio Marketplace publisher management and choose an available publisher ID. The manifest currently uses
aetherscript; change the publisher value in package.json if your publisher ID differs.
- Create a Marketplace Personal Access Token with Marketplace > Manage scope. Keep it private; do not put it in this project.
- Install dependencies and run tests, then package with
npm run package.
- Sign in with
npx vsce login <your-publisher-id> and publish with npx vsce publish. You can also upload the generated .vsix from the publisher management page.
Language guide
# Variables and output
weave name = "traveler"
shine "Hello, " + name
# Change a variable and branch
weave score = 7
when score >= 10
shine "A bright star!"
otherwise
shine "Keep exploring"
end
# Repeat while a condition is true
weave count = 3
orbit count > 0
shine count
set count = count - 1
end
# Define and call a spell (function)
spell greet(person)
return "Welcome, " + person
endspell
shine greet("Aether")
You can also write programs with familiar beginner-friendly words:
let name = "traveler"
print "Hello, " + name
if name equals "traveler"
show "Welcome!"
else
output "Who are you?"
endif
function greet(person)
give "Hello, " + person
endfunction
print greet(name)
These features are built into the language; no summon statement is needed:
weave scores = [8, 10, 7]
weave total = 0
for score in scores
set total += score
endfor
shine "Average: " + (total / len(scores))
shine "Is 2 in range? " + (2 in range(5))
shine "3 squared: " + 3 ** 2
for name in list repeats once per list item; strings can be looped character by character. The loop variable exists only inside its loop. Use endfor to finish the loop, leave to exit early, and continue (or next/skip) to move to the next item. The in operator checks a list or string. ** raises a number to a power. set also supports +=, -=, *=, /=, and %=. range(stop), range(start, stop), or range(start, stop, step) creates a list of numbers (at most 10,000 items).
20 more built-in features
These are part of the language itself, not libraries:
otherwise when and else if add more choices to a when block; elseif is also accepted.
repeat 3 times runs a block a fixed number of times; endrepeat closes it.
repeat 3 times as turn also gives each iteration a local counter starting at zero.
for n from 1 to 5 counts through a number range, including both ends.
- Add
by 2 to a number range to choose its step; counting down works too.
choose value, case value, otherwise, and endchoose select a matching block.
constant name = value makes a variable you cannot later change.
check condition stops with a clear error if the condition is false.
check condition, "message" shows your own message when a check fails.
increment count adds one.
increment count by 3 adds a chosen amount.
decrement count subtracts one.
decrement count by 3 subtracts a chosen amount.
// divides and rounds down to the next whole number.
**= raises a variable or list item to a power and stores the result.
is compares two values for equality.
is not checks that two values are different.
not in checks that a value is absent from a list or string.
length, absolute, minimum, maximum, and round are available without summon math.
join(list, separator) combines list values into text; split(text, separator) turns text into a list.
AetherGame 2D, perspective 3D, and isometric 3.5D
The aethergame library draws bounded scenes in the GAME PREVIEW panel in Aether Studio. Install the multiple library pack in standalone Studio, then try examples/aethergame_2d.aether or examples/aethergame_3d.aether:
summon aethergame
aethergame.start(640, 360, "#17202f")
aethergame.rect(30, 70, 100, 80, "#b7a4ff")
aethergame.circle(220, 110, 30, "orange")
aethergame.line(20, 200, 300, 200, "white", 2)
aethergame.text("My first scene", 24, 32, "white", 20)
start(width, height[, background]) creates a scene up to 1024 by 768 pixels. 2D drawing includes rect, circle, line, text, polygon, triangle, ellipse, and grid. Use setCamera(x, y, z[, focalLength]), point3d, line3d, box3d, and sphere3d for perspective-projected wireframe 3D; tile3d draws isometric 3.5D diamond tiles. Scenes are limited to 1000 drawing items, and colors must be simple color names or hexadecimal values. AetherGame also supports a playable maze scene with arrow-key movement; animation/game loops, image assets, and solid lit meshes are future work.
Run examples/aethergame_maze.aether in Aether Studio or the VS Code Studio view to play the first AetherScript maze game. In standalone Studio, install the multiple library pack or run aetherpip install aethergame first. Click the preview to focus it, then use the arrow keys to reach the chest. aethergame.maze(rows, cellSize) takes an odd-sized ASCII map (5–31 rows and columns): # is a wall, . is a path, S is the player start, and C is the chest. Wall movement is blocked, and reaching the chest wins the game.
The 3D example combines these APIs:
summon aethergame
aethergame.start(640, 360, "#101826")
aethergame.setCamera(320, 180, -500, 500)
aethergame.tile3d(0, 0, -60, 110, "#395f59")
aethergame.box3d(280, 150, 100, 110, 110, 110, "#b7a4ff")
aethergame.sphere3d(390, 160, 80, 48, "#ffcf70")
aethergame.line3d(80, 240, 40, 520, 240, 40, "white")
Local machine learning
The aetherml library trains small models locally; it does not call cloud services or require Python, TensorFlow, or PyTorch:
summon aetherml
weave features = [[0], [1], [2], [3]]
weave targets = [1, 3, 5, 7]
weave model = aetherml.trainLinear(features, targets, 0.01, 500)
shine aetherml.predictLinear(model, [4])
trainLinear uses gradient descent for numeric regression. trainLogistic trains a binary classifier, and predictClass returns 0 or 1. normalize, split, accuracy, mse, precision, and recall help prepare and evaluate small datasets. Training is bounded to 1,000 epochs and 1,000,000 feature updates per call. This is a real, small educational training implementation, not a general-purpose deep-learning framework.
Project-scoped file management
In standalone Studio, choose Project Folder before using file calls. In VS Code, AetherScript uses the first open workspace folder. Paths must be relative to that root; path traversal and links escaping the root are rejected. Text operations are capped at 1 MiB per file, directory listing is one level deep, and remove only removes a file or an empty directory.
summon files
files.writeText("notes/hello.txt", "Hello from AetherScript")
files.appendText("notes/hello.txt", "!")
shine files.readText("notes/hello.txt")
shine files.list("notes")
Available calls are readText, writeText, appendText, list, exists, makeDirectory, remove, copy, move, and size. The folder must be selected first, and parent folders must exist except when created with makeDirectory.
data includes CSV/JSON conversion, flattening, chunking, frequencies, min-max normalization, seeded shuffling, and sampling. utils provides clamping, interpolation, range mapping, repeatable random numbers, 2D/3D vectors, distances, vector normalization, and 2D angles. For example:
summon data
summon utils
weave rows = data.parseCsv("name,score\nAether,9")
shine data.minmax([10, 20, 30])
shine utils.distance3([0, 0, 0], [2, 3, 6])
The 50 newly added APIs across AetherGame, aetherml, files, data, and utils are listed with examples and constraints in the included ROADMAP.md file.
Beginner-friendly words
These 25 words are aliases for AetherScript's existing commands and operators. You can mix them with the original words:
| Word |
Same as |
Purpose |
let, make |
weave |
Create a variable |
change, update |
set |
Change a variable |
print, show, output |
shine |
Display a value |
if |
when |
Start a condition |
else |
otherwise |
Choose the other branch |
endif |
end |
Finish a condition |
while, repeat |
orbit |
Repeat while a condition is true |
endwhile |
end |
Finish a loop |
function, procedure |
spell |
Define a function |
endfunction, endprocedure |
endspell |
Finish a function |
give |
return |
Send a value back from a function |
exit, break |
leave |
Exit the current loop |
import, use |
summon |
Load a library |
nil, null |
nothing |
Write an empty value |
equals |
== |
Compare two values for equality |
Standard libraries
Bring extra tools into a program with summon. Math, text, and list helpers are built into AetherScript:
summon math
summon strings
summon lists
shine math.sqrt(81)
shine strings.upper("hello, aether!")
weave planets = ["Ember", "Tide"]
lists.push(planets, "Gale")
set planets[0] = "Cloud"
shine lists.join(planets, ", ")
summon math as m also works if you prefer a shorter library name.
| Library |
Functions and values |
math |
pi, e, tau, abs, floor, ceil, round, sqrt, pow, min, max, clamp, sin, cos, tan, log, log10 |
strings |
upper, lower, trim, contains, startsWith, endsWith, replace, split, slice |
lists |
push, pop, insert, remove, contains, reverse, sort, join, slice |
Lists use square brackets, zero-based indexing (planets[0]), and mutable indexed assignment (set planets[0] = "Cloud"). lists.push, insert, pop, remove, sort, and reverse update the supplied list. math.min and math.max accept multiple numbers or a single list of numbers.
Additional library packs
The Multiple AetherScript libraries pack adds small, offline AetherScript-native demos inspired by these Python packages:
| Library |
Starter functions |
numpy |
array, zeros, ones, arange, sum, mean, dot, add, shape |
pandas |
frame, head, column, row, shape, unique |
matplotlib, plotly, bokeh |
bar, line (console charts) |
seaborn |
histogram, heatmap |
sklearn |
linearFit, predict, accuracy, nearest |
tensorflow, keras, torch |
tensor, relu, sigmoid, softmax, dot (small list-based demonstrations) |
scipy |
trapezoid, derivative, interpolate |
opencv |
dimensions, grayscale, invert |
pillow |
dimensions, grayscale, invert, crop |
requests |
parseUrl, isHttps, encode (URL helpers only; no HTTP requests) |
beautifulsoup |
text, title, links (parses an HTML string you provide) |
flask, django |
route, response; Django also has paginate (in-memory descriptions only) |
nltk |
words, sentences, frequency |
spacy |
words, sentences, capitalizedPhrases |
wifi |
profiles, connect, status (offline simulator only) |
These are learning-oriented language libraries, not Python package ports: they do not train neural networks, start web servers, access cameras or image files, send network requests, scan or connect to real Wi-Fi, or run Python code. Images and tables are represented using AetherScript lists.
Fifty more offline libraries are available as individual aetherpip installs. For example:
aetherpip install statistics
aetherpip install camera
aetherpip list
Installed modules can be imported with summon, for example summon statistics followed by shine statistics.median([2, 8, 4]). The new catalog includes calendar/date helpers, numeric and geometry tools, text encoding, matrix and vector math, game collision and camera calculations, data structures, color conversion, and offline URL/HTML text helpers. These modules perform local calculations only; they do not download package code or contact a package registry. The complete names and descriptions are in src/library-catalog.json.
Handmade libraries
A library is an .aether file containing one or more spell definitions and optional summon imports, for example examples/hello_tools.aether. Its lowercase filename becomes its library name:
aetherpip install .\hello_tools.aether
Open a new terminal after installation, then use the library in a program:
summon hello_tools
shine hello_tools.double(6)
You can also use Libraries → Import .aether library in Aether Studio, or run AetherScript: Install Library from the VS Code Command Palette. aetherpip, Aether Studio, and the VS Code extension share the per-user custom library folder. Custom libraries run in the AetherScript interpreter; they cannot execute JavaScript, access files, or make network requests. Online publishing is not configured because this project has no library registry or upload server; installs are local to your account.
aetherpip commands
Open CMD after installing AetherScript Studio. Install the direct executable-converter command once:
aetherpip install auto_aether_to_exe
Then run commands from CMD (a new terminal window may be needed after installing):
auto_aether_to_exe .\hello.aether .\hello-app
aetherpip run .\hello.aether
aetherpip check .\hello.aether
aetherpip install statistics
aetherpip install camera
aetherpip install .\hello_tools.aether
aetherpip list
aetherpip auto_aether_to_exe .\hello.aether
aetherpip install auto_aether_to_exe adds an auto_aether_to_exe.cmd command beside the installed aetherpip shim, in the folder the installer added to your user PATH. auto_aether_to_exe creates a folder containing hello.exe and its runtime files. Share the whole folder, not just the .exe. Opening the generated app runs the bundled program and shows its output. The package also includes the currently installed bundled-library selection and your custom .aether libraries. Commands that run/check programs display their output or errors in a Studio dialog.
Keywords and values
| Syntax |
Purpose |
weave name = value |
Declare a variable in the current scope |
name = value |
Python-style variable assignment; creates the name if needed |
set name = value |
Update an existing variable |
shine expression |
Print a value |
when condition / otherwise / end |
Conditional branch |
orbit condition / end |
Loop while the condition is true |
for item in items / endfor |
Loop over a list or string |
repeat count times / endrepeat |
Repeat a fixed number of times |
for item from start to stop / endfor |
Count through an inclusive number range |
choose value / case value / endchoose |
Run the matching case |
constant name = value |
Declare a value that cannot be changed |
check condition |
Stop with an error if the condition is false |
spell name(args) / endspell |
Define a function |
def name(args): / endspell |
Python-style function header |
if condition: / elif condition: / else: / end |
Python-style conditional headers |
while condition: / end |
Python-style while header |
for item in items: / endfor |
Python-style for header |
pass |
Do nothing on this line |
assert condition, "message" |
Stop with an error when the condition is false |
from math import sqrt as root |
Import one library member with an optional alias |
try: / except Error as problem: / finally: / endtry |
Catch runtime errors and optionally run cleanup code |
raise expression |
Stop with an error using the expression as its message |
del name |
Remove a variable from its scope |
return expression |
Return from a function |
leave, exit, break |
Exit the innermost loop |
continue, next, skip |
Skip to the next loop iteration |
summon math |
Import a standard library; optional as alias |
true, false, nothing (True, False, None) |
Boolean and empty values |
and, or, not |
Boolean operators |
Python-style headers accept a trailing colon, but blocks still close with AetherScript's explicit end, endfor, endspell, or endtry; indentation does not determine block boundaries. except currently catches runtime errors without filtering by exception class. Strings use double quotes and support \\n, \\r, \\t, \\", and \\\\. Comments start with #. Arithmetic supports +, -, *, /, %, and **; comparisons support ==, !=, <, <=, >, and >=. The in operator checks for a value in a list or string. Assignment supports =, +=, -=, *=, /=, and %=. Parentheses group expressions. + joins values when either side is a string.
Global built-in functions are len, text, number, kind, first, last, isEmpty, contains, sum, average, sorted, reverse, and range. For example, range(4) creates [0, 1, 2, 3], sum([2, 3]) returns 5, and first("Aether") returns "A". Ranges are capped at 10,000 items. The interpreter limits execution to 100,000 steps and spell calls to 100 nested calls.
Commands
- AetherScript: Run File — run the active
.aether document (Ctrl+F5).
- AetherScript: Run Selection — run the selected code, or the whole file if no selection is active.
- AetherScript: Open Aether Studio — open the full-size Studio editor.