magmascript
Scripting toolkit with domain-first subcommands for managing magmacrunch.com infrastructure.
Install
git clone https://github.com/magmacrunchmedia/magmascript.git
cd magmascript
python3 -m venv .venv
.venv/bin/pip install -e ".[all]"
Configure
# Auto-configure from MCP server
magmascript configure
# Or manually set environment variables
export MAGMA_API_KEY="your-mcp-key"
export GITHUB_TOKEN=$(gh auth token)
export MAGMACRUNCH_ROOT="/path/to/magmacrunch.com"
Or use ~/.config/magmascript/config.toml:
[mcp]
url = "https://magmacrunch.duckdns.org/mcp"
api_key = "your-key"
[pi]
host = "your-pi-host"
user = "jake"
[gh]
token = "ghp_..."
owner = "magmacrunchmedia"
repo = "magmacrunch.com"
[project]
root = "/path/to/magmacrunch.com"
MagmaScript Language
Write .mgs scripts using a Python-inspired mini language with direct access to all domains.
Quick Start
# Run a script
magmascript run scripts/examples/hello.mgs
# Run with arguments
magmascript run scripts/examples/top-scores.mgs tetris
# Start interactive REPL
magmascript repl
Syntax Overview
// Variables
name = "MagmaCrunch"
version = 2
// String interpolation
print(f"Hello, {name} v{version}!")
// Functions
double = fn(x) { x * 2 }
result = double(21)
// Arrow functions
triple = x -> x * 3
// Script arguments
args_list = args()
if len(args_list) > 0 {
print(f"First arg: {args_list[0]}")
}
// Control flow
if x > 10 {
print("big")
} else {
print("small")
}
// Loops
for i in range(5) {
print(i)
}
while x > 0 {
x = x - 1
}
// Dict literals
scores = {"Pong": 12, "Tetris": 45}
print(scores["Tetris"])
// List comprehensions
numbers = [1, 2, 3, 4, 5]
evens = [x for x in numbers if x % 2 == 0]
doubled = [x * 2 for x in numbers]
// String methods
csv = "apple,banana,cherry"
fruits = csv.split(",")
upper = [f.upper() for f in fruits]
print("-".join(upper))
// Domain calls work directly
boards = mcp.scoreboards()
for board in boards {
print(f"{board.game}: {board.entries} entries")
}
Language Features
Import System
// Import a module (access as namespace)
intent "utils.mgs"
result = utils.greet("World")
// Import with alias
intent "utils.mgs" as u
result = u.greet("World")
// Import specific names
intent { greet, farewell } from "utils.mgs"
result = greet("World")
Error Handling
try {
result = risky_operation()
} haunter (e) {
print(f"Error: {e.message}")
}
// Throw custom errors
throw fire toad("something went wrong")
MagmaCrunch error vocabulary:
haunter— syntax/parse errorsfire toad— runtime errorsdevastate— undefined variable errorscontemplate— type errorsspooked— warnings (non-fatal, prints to stderr)
spooked("this is a warning")
File I/O
content = quarry("data.txt") // read file
litho("output.txt", "hello world") // write file
HTTP Requests
response = http.get("https://api.example.com/data")
print(response.status)
print(response.json)
http.post("https://api.example.com/data", body={"key": "value"})
Shell Commands
result = exec("ls -la")
print(result.stdout)
print(result.exit_code)
Classes
class Dog {
fn init(name) {
self.name = name
}
fn bark(self) {
return self.name + " says woof!"
}
}
rex = Dog("Rex")
print(rex.bark()) // "Rex says woof!"
Default Parameters
fn greet(name, greeting="hello") {
return greeting + ", " + name + "!"
}
greet("Jake") // "hello, Jake!"
greet("Jake", "hey") // "hey, Jake!"
Multi-Assignment
a, b = 1, 2
x, y, z = 10, 20, 30
a, b = [1, 2] // list unpacking
in / not in Operators
if "key" in {"name": "Jake"} { ... }
if 5 not in [1, 2, 3] { ... }
if "xyz" not in "hello" { ... }
List/String Slicing
[1, 2, 3, 4, 5][0:3] // [1, 2, 3]
[1, 2, 3][::-1] // [3, 2, 1]
[0, 1, 2, 3, 4][::2] // [0, 2, 4]
"hello world"[0:5] // "hello"
"abcdef"[::-1] // "fedcba"
Regex
"123abc".match("\\d+") // ["123"] (match at start)
"abc123def456".findall("\\d+") // ["123", "456"]
Built-in Functions
| Function | Description |
|---|---|
print(...) |
Print to stdout |
len(x) |
Length of string, list, or dict |
type(x) |
Type name as string |
range(n), range(start, stop), range(start, stop, step) |
Generate integer ranges |
str(x), int(x), float(x) |
Type conversions |
abs(x), min(...), max(...), sum(...) |
Math utilities |
keys(d), values(d) |
Dict operations |
args() |
Get script arguments from CLI |
quarry(path) |
Read file contents |
litho(path, content) |
Write content to file |
exec(command) |
Execute shell command, returns {stdout, stderr, exit_code} |
String Methods
| Method | Description |
|---|---|
s.split(sep) |
Split string by separator |
s.join(list) |
Join list with string separator |
s.upper() |
Convert to uppercase |
s.lower() |
Convert to lowercase |
s.contains(sub) |
Check if substring exists |
s.replace(old, new) |
Replace substring |
s.length() |
Get string length |
s.startswith(prefix) |
Check if starts with prefix |
s.endswith(suffix) |
Check if ends with suffix |
s.strip() |
Remove leading/trailing whitespace |
s.match(pattern) |
Match regex at start, return groups or none |
s.findall(pattern) |
Find all non-overlapping regex matches |
Example Scripts
See scripts/examples/ for working examples:
| Script | Description |
|---|---|
hello.mgs |
Hello World and basic features |
fibonacci.mgs |
Recursive functions and loops |
top-scores.mgs |
Arcade leaderboards (all games or single game) |
album-isrcs.mgs |
Get ISRCs/ISWCs for every song on an album |
album-lookup.mgs |
Album research: MusicBrainz + ISRC/ISWC + rights |
artist-rights.mgs |
Full artist rights catalog |
pi-health.mgs |
Pi system health check |
pi-traffic-report.mgs |
Nginx traffic analysis |
deploy-and-verify.mgs |
Deploy to Pi with service verification |
full-backup.mgs |
MusicBrainz backup pipeline |
weekly-scores.mgs |
Weekly scores report in markdown |
maintenance.mgs |
Weekly maintenance pipeline |
real-domains.mgs |
Test real domain connections (MCP search, scoreboards, games) |
domain-example.mgs |
Domain object overview and usage patterns |
Domains
MCP Domain — MusicBrainz, scores, Discogs, write operations
magmascript mcp scoreboards # game leaderboards
magmascript mcp scores tetris # tetris scores
magmascript mcp search "radiohead" # search MusicBrainz
magmascript mcp entities # all cached entities
magmascript mcp games # arcade games
magmascript mcp mb-search "album name" # search MusicBrainz releases
magmascript mcp mb-release <mbid> # get release details
magmascript mcp mb-recording <mbid> # get recording details
Pi Domain — Direct SSH to Raspberry Pi
magmascript pi status # all service statuses
magmascript pi logs arcade-chat # service logs
magmascript pi restart arcade-chat # restart service
magmascript pi info # uptime, memory, temp
magmascript pi deploy arcade/chat-server.py # deploy files
magmascript pi backup musicbrainz # backup + commit to GitHub
magmascript pi traffic # nginx traffic analysis
GitHub Domain — Direct API access
magmascript gh workflows # all workflow statuses
magmascript gh trigger "Deploy to Pi" # trigger workflow
magmascript gh issues # list issues
magmascript gh file path/to/file.txt # read file
magmascript gh sync # diff + commit all data files
Scores Domain — Game high scores
magmascript scores list # all game leaderboards
magmascript scores get tetris # tetris scores
magmascript scores report # markdown report
magmascript scores report --discord # Discord JSON payload
magmascript scores reset tetris # reset one game (backup created)
Archive Domain — Archive page operations
magmascript archive check-format # validate HTML formatting
magmascript archive bake-cache # inline MusicBrainz cache into pages
MusicBrainz Domain — MusicBrainz API client
magmascript mb backup # full MusicBrainz backup
magmascript mb backup --dry-run # preview backup
magmascript mb backup --stale-only # only refresh stale caches
Last.fm Domain — Last.fm API client
magmascript lastfm fetch # fetch play counts
magmascript lastfm fetch --skip-existing # skip cached artists
Search Domain — Site search index builder
magmascript search build-index # build search-index.json
magmascript search preview 10 # preview first 10 entries
Rights Domain — Music rights metadata (ISRC, ISWC, ASCAP)
magmascript rights search "Farewell" # search by title, ISRC, ISWC, or ASCAP ID
magmascript rights catalog "C.P. Rutledge" # full rights catalog for an artist
magmascript rights export # TSV export for ASCAP forms
Media Domain — Multi-provider media search
magmascript media search "sunset" # search all providers
magmascript media providers # list available providers
Cache Domain — Cache management
magmascript cache stats # show cache statistics
magmascript cache clear # clear all cache
Magma — System status dashboard
magmascript magma # version, domains, cache stats
Crunch — Batch pipeline
magmascript crunch mb # MusicBrainz backup
magmascript crunch lastfm # Last.fm fetch
magmascript crunch search # Build search index
magmascript crunch archive # Archive pages
magmascript crunch scores # Scores update
magmascript crunch gh # GitHub sync
magmascript crunch all # Run all targets
Texas — Full/heavy operation (same targets, no shortcuts)
magmascript texas mb # Full MusicBrainz backup
magmascript texas lastfm # Full Last.fm fetch
magmascript texas search # Full search index rebuild
magmascript texas archive # Full archive processing
magmascript texas scores # Full scores update
magmascript texas gh # Full GitHub sync
magmascript texas all # Full heavy run
Toast — Burn/clear caches
magmascript toast cache # Clear general cache
magmascript toast mb-cache # Clear MusicBrainz cache
magmascript toast lastfm-cache # Clear Last.fm cache
magmascript toast scores-cache # Clear scores cache
magmascript toast gh-cache # Clear GitHub cache
magmascript toast search-index # Remove search index
magmascript toast all # Clear everything
Python Library
from magmascript import MCPClient, PIClient, GHClient, RightsClient
# MCP
with MCPClient() as mcp:
boards = mcp.scoreboards()
releases = mcp.mb_search_releases("album name")
# Pi (direct SSH)
with PIClient() as pi:
status = pi.services()
info = pi.info()
# GitHub (direct API)
with GHClient() as gh:
workflows = gh.workflows()
# Music rights metadata
with RightsClient() as rights:
catalog = rights.catalog("C.P. Rutledge")
Shell Helpers
source lib/magmascript.sh
mcp_scoreboards # MCP commands
pi_status # Pi commands
gh_workflows # GitHub commands
Documentation
Full documentation on the Wiki:
- Configuration
- MagmaScript Language
- MCP Domain
- Pi Domain
- GitHub Domain
- Scores Domain
- Rights Domain
- Example Scripts
- Architecture
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
magmascript-2.0.1.tar.gz
(121.1 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
magmascript-2.0.1-py3-none-any.whl
(122.3 kB
view details)
File details
Details for the file magmascript-2.0.1.tar.gz.
File metadata
- Download URL: magmascript-2.0.1.tar.gz
- Upload date:
- Size: 121.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
968417801a2676786d52a19040f50821ab4936de20090b7c28289389ec234b79
|
|
| MD5 |
0dbde5d8bbc6bdaab159fe182936eeb1
|
|
| BLAKE2b-256 |
29aa42d65f4045c4e44e3a6cd492e6cb2deedbc7bc9534c65d4103b0d179b252
|
File details
Details for the file magmascript-2.0.1-py3-none-any.whl.
File metadata
- Download URL: magmascript-2.0.1-py3-none-any.whl
- Upload date:
- Size: 122.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06ca3b7d79627cb0d8e53823a0da3488a550ea933dceae56623d2d0a72f15225
|
|
| MD5 |
6f61895452c882303ce9188160e1f9ec
|
|
| BLAKE2b-256 |
d9cc89f9bfdad25608e7e0ecadad2f55b2de65b9f54939ede041f86ff481b705
|