Releases: ofthemachine/fraglet
fraglet-entrypoint v0.6.0
Release v0.6.0
Key Highlights
- Per-mode essence — optional
essencefield infraglet.yaml(same path resolution asguide),fraglet-entrypoint essence, andfragletc essence <vein>.
New Features
Per-mode essence
Optional essence field (file path, same resolution as guide) supplies a token-dense capability summary for the active mode. Invoked as fraglet-entrypoint essence inside the image or fragletc essence <vein> from the host. If no essence is configured or the file is missing, behavior matches guide for a missing guide: no stdout or stderr from the entrypoint for that subcommand, exit 0 (no fallback to the guide file).
Reproducible Builds
To verify a release binary was built from the claimed source:
./verify-release.sh entrypoint-v0.6.0This runs the build inside a golang:<version>-bookworm container pinned to the exact Go version from go.mod at the tag, builds both linux/amd64 and linux/arm64 binaries, and outputs sha256 checksums. Compare against checksums.txt from the release.
Upgrading
ARG FRAGLET_VERSION=entrypoint-v0.6.0Update the sha256 checksums to match the new release binaries.
fragletc v0.6.0
fragletc v0.6.0
Key Highlights
- MCP language modes — the MCP server now supports language modes, letting AI tools request mode-specific guides and execution contexts.
- MCP fraglet saving — the MCP server can save fraglets to disk for reproducibility.
--paramsupport — pass parameters to fraglets via CLI, declared in code viafraglet-meta:sentinels.- Breaking: fraglet.yaml mode format — reads the new inline modes schema (matches entrypoint v0.5.0).
What's New
MCP Server: Language Modes
The language_help MCP tool now accepts an optional mode parameter:
{
"tool": "language_help",
"arguments": {
"language": "java",
"mode": "main"
}
}This returns mode-specific authoring guides when containers define multiple execution modes.
MCP Server: Fraglet Saving
The run MCP tool can now save fraglets to a local path before execution, enabling workflows where AI tools persist code snippets for reproducibility.
Fraglet Parameters
Parameters are declared in fraglet code via fraglet-meta: comment sentinels:
# fraglet-meta: param=city:default=london param=port:default=8080
import os
print(f"City: {os.environ['CITY']}, Port: {os.environ['PORT']}")And passed via fragletc:
fragletc --vein=python --param CITY=tokyo -c '...'fragletc decodes the params and passes them as FRAGLET_PARAM_* transport env vars to the container. The entrypoint coerces them into bare env vars for the executed code.
Reproducible Builds
To verify a release binary was built from the claimed source:
./verify-release.sh fragletc-v0.6.0This runs the build inside a golang:<version>-bookworm container pinned to the exact Go version from go.mod, downloads the release's build-info.json, builds all platform binaries, and outputs sha256 checksums. Compare against checksums.txt from the release.
Infrastructure
- Restructured build:
cmd/fragletc/replacescli/as the binary source - Build info now at
cmd/fragletc/build-info.json - Test harness extracted to external
github.com/ofthemachine/clitestpackage go installpath is nowgithub.com/ofthemachine/fraglet/cmd/fragletc@latest
fraglet-entrypoint v0.5.0
Release v0.5.0
Key Highlights
- Breaking: fraglet.yml mode management restructured — modes are now defined inline via a
modesmap, replacing the previous per-file approach. Designed for "fat" containers with many execution modes. makeExecutableremoved — execution paths are always made executable. The option was a foot-gun that only mattered when omitting an interpreter prefix.- Parameter coercion — the entrypoint now coerces
FRAGLET_PARAM_*transport env vars into bare env vars for the executed command. The entrypoint is intentionally dumb: no schema, no decoding, just prefix stripping and a no-shadow rule. Decoding is fragletc's responsibility. - Independent release tagging — entrypoint releases now use
entrypoint-v0.X.0tags instead of barev0.X.0, decoupling binary releases from Go module versioning.
Breaking Changes
fraglet.yml Modes
The mode management was restructured to support containers with many modes. Modes are now defined inline in the config:
fragletTempPath: /FRAGLET
# Default mode (used when FRAGLET_MODE is unset)
injection:
codePath: /hello-world/hello-world.sh
match: FRAGLET
guide: /guide.md
execution:
path: /hello-world/hello-world.sh
# Named modes override specific fields
modes:
main:
injection:
codePath: /hello-world/Main.java
match_start: "// BEGIN_FRAGLET"
match_end: "// END_FRAGLET"
guide: /guide-main.md
execution:
path: /hello-world/run-main.shFields not specified in a mode inherit from the root config. All existing 100hellos containers need their fraglet.yml updated to the new schema.
makeExecutable Removed
The execution.makeExecutable field has been removed. The entrypoint always makes the execution path executable. This was the correct behavior in all real-world cases — the only scenario where false was needed was interpreter-based execution (python /path/to/script.py), which doesn't need the file to be executable anyway.
New Features
Parameter Coercion
The entrypoint scans the process environment for FRAGLET_PARAM_* variables, strips the prefix, and sets them as bare env vars:
FRAGLET_PARAM_CITY=london → CITY=london
The no-shadow rule prevents overwriting existing env vars (e.g., FRAGLET_PARAM_HOME is ignored if HOME already exists). Transport vars are cleaned up after coercion.
Parameters are declared in fraglet code via fraglet-meta: comment sentinels and passed by fragletc via --param. The entrypoint doesn't know about fraglet-meta — it only does the transport layer.
Reproducible Builds
To verify a release binary was built from the claimed source:
./verify-release.sh entrypoint-v0.5.0This runs the build inside a golang:<version>-bookworm container pinned to the exact Go version from go.mod, builds both linux/amd64 and linux/arm64 binaries, and outputs sha256 checksums. Compare against checksums.txt from the release.
Infrastructure
- Consolidated to single Go module (no more separate
entrypoint/go.mod) - Test harness extracted to external
github.com/ofthemachine/clitestpackage - All entrypoint domain files (releases, tests, schema reference) now live under
cmd/entrypoint/
Upgrading
ARG FRAGLET_VERSION=entrypoint-v0.5.0Update the sha256 checksums to match the new release binaries. The tag format change from v0.X.0 to entrypoint-v0.X.0 is a one-time migration.
Every language container's fraglet.yml must be updated to the new mode schema.
fragletc v0.5.0
fragletc v0.5.0
What's New
Optional persistence for successful MCP runs (fragletc mcp --save)
When the MCP server is started with a save directory, successful runs from the run tool are persisted as content-addressed, shebangable fraglet files. Persistence is invisible to the agent (no path or hash in the response).
fragletc mcp --save=$HOME/.fraglet/store
fragletc mcp --save=~/.fraglet/storeThe save path supports environment variable expansion ($HOME, ${HOME}) and tilde expansion (~, ~/path). Artifacts are stored under <save-root>/<lang>/[tagPrefix/]<h[:2]>/<h[2:]> (hash-sharded). If the run includes annotations, the lexically first annotation's tag-prefix (the part before :) is used as a subfolder under the language name; otherwise no subfolder is used.
Artifact shape: Each saved file is a shebangable script:
- Shebang:
#!/usr/bin/env -S fragletc --image=<image@sha256:...>and--mode=Xonly when the run had an explicit mode. - Optional comment line:
# fraglet-meta: <annotations in lexically sorted order>(key:value tokens). - Then the fraglet body.
Re-running the same file (e.g. ./saved-fraglet) uses the pinned image digest and mode, giving a clear reproducibility boundary for cacheable runs.
MCP run tool: optional mode and annotations
The run tool now accepts:
mode— Optional fraglet mode (e.g.main). When provided, setsFRAGLET_CONFIG=/fraglet-<mode>.ymlin the container and is included in persisted artifacts when save is enabled.annotations— Optional list of key:value tokens (e.g.determinism:deterministic,math:number-theory) for discovery and cache semantics. Rendered in sorted order in saved artifacts; the first annotation's tag-prefix can be used as a save subfolder.
Tool descriptions and input schemas are phrased in terms of tool parameters only (e.g. lang, mode, code). CLI flags like --vein and --save apply to starting the server (fragletc mcp [--save=...]), not to individual tool calls, so agents are not directed to pass CLI-style arguments to the tools.
Save interface for future backends
Persistence is gated behind an ArtifactSaver interface. The current implementation is a synchronous local filesystem writer. The interface does not assume sync durability, so a future implementation (e.g. HTTP endpoint, async/best-effort) can be plugged in without changing callers.
Artifacts
fragletc-linux-amd64— Linux x86_64fragletc-linux-arm64— Linux ARM64fragletc-windows-amd64.exe— Windows x86_64fragletc-darwin-amd64— macOS Intelfragletc-darwin-arm64— macOS Apple Siliconbuild-info.json— embedded provenance (for reproducible build verification)checksums.txt— SHA256 checksums for all binaries
fragletc v0.4.0
fragletc v0.4.0
What's New
fragletc version — provable build lineage
Every fragletc binary now embeds its own provenance via go:embed. fragletc version shows the release version, git commit SHA, and build timestamp baked into the binary at build time.
$ fragletc version
fragletc v0.4.0
commit: abc1234def56
built: 2026-03-03T04:00:00Z
The build-info.json is generated during make build and CI, capturing the exact commit and version from cli/releases/. Local development builds show version: dev as a clear signal they aren't release artifacts.
Reproducible builds
Builds are now byte-for-byte reproducible. Given the same source, the same Go version, and the same build-info.json, you get an identical binary regardless of when or where you build it.
The build-info.json used for each release is published alongside the binaries. To verify a release:
git checkout fragletc-v0.4.0
cp /path/to/downloaded/build-info.json cli/build-info.json
CGO_ENABLED=0 go build -trimpath -buildvcs=false -ldflags="-s -w" -o fragletc ./cli
shasum -a 256 fragletc # compare against checksums.txtBuild flags that enable this: -trimpath (strips host paths), -buildvcs=false (we embed our own provenance), CGO_ENABLED=0 (no system library variance), -ldflags="-s -w" (consistent stripping).
Bug fix: fragletc guide now parses --mode in any position
Previously, fragletc guide java --mode=wordalytica silently ignored the --mode flag because Go's standard flag package stops parsing at the first non-flag argument. The flag only worked when placed before the vein name (fragletc guide --mode=wordalytica java).
All of these now work correctly:
fragletc guide java --mode=wordalytica
fragletc guide java --mode wordalytica
fragletc guide java -m wordalytica
fragletc guide --mode=wordalytica java
fragletc guide -m wordalytica java
Artifacts
fragletc-linux-amd64— Linux x86_64fragletc-linux-arm64— Linux ARM64fragletc-windows-amd64.exe— Windows x86_64fragletc-darwin-amd64— macOS Intelfragletc-darwin-arm64— macOS Apple Siliconbuild-info.json— embedded provenance (for reproducible build verification)checksums.txt— SHA256 checksums for all binaries
fragletc v0.3.0
fragletc v0.3.0
What's New
MCP tool definitions now teach AIs about fraglet files
The run and language_help MCP tool descriptions now document:
- Fraglet as a concept — an executable code file that runs in a containerized sandbox
- The fragletc shebang —
#!/usr/bin/env -S fragletc --vein=<lang> - Vein terminology — the
langparameter maps to--veinin the CLI
AIs using the MCP server will now correctly produce fragletc shebangs when asked to write executable fraglets, instead of defaulting to native language interpreters.
Automated releases
Pushing a new cli/releases/vX.Y.Z.md file now automatically triggers the release build and GitHub Release creation.
Artifacts
fragletc-linux-amd64— Linux x86_64fragletc-linux-arm64— Linux ARM64fragletc-windows-amd64.exe— Windows x86_64fragletc-darwin-amd64— macOS Intelfragletc-darwin-arm64— macOS Apple Silicon
fragletc v0.2.0
fragletc v0.2.0
What's New
Built-in MCP server (fragletc mcp)
fragletc now ships with the MCP (Model Context Protocol) server built in. No more separate fraglet-mcp binary — a single fragletc handles both CLI execution and AI tool integration.
Start the MCP server:
fragletc mcp
Configure in Claude Desktop or Cursor:
{
"mcpServers": {
"fraglet": {
"command": "fragletc",
"args": ["mcp"]
}
}
}One-line installer
curl -fsSL https://raw.githubusercontent.com/ofthemachine/fraglet/main/install.sh | sh
Platform detection, checksum verification, Docker check, and PATH setup — all handled.
See INSTALL.md for full setup guide including Claude Desktop and Cursor configuration.
Artifacts
fragletc-linux-amd64— Linux x86_64fragletc-linux-arm64— Linux ARM64fragletc-windows-amd64.exe— Windows x86_64fragletc-darwin-amd64— macOS Intelfragletc-darwin-arm64— macOS Apple Silicon
fragletc v0.1.0
fragletc v0.1.0
Initial release of the fraglet CLI.
Artifacts
fragletc-linux-amd64— Linux x86_64fragletc-linux-arm64— Linux ARM64fragletc-windows-amd64.exe— Windows x86_64
Usage
See repo README and fragletc --help.
fraglet-entrypoint v0.4.0
Release v0.4.0
Key Highlights
- Stdin passthrough:
fraglet-entrypointnow forwards the container's stdin to the executed command, enablingecho "data" | docker run --rm -i ... <container>workflows. - Full data pipeline support: Fraglets can read from stdin using their language's native I/O primitives — pipes, multi-line streams, and binary data all work.
- Verified across 14 languages: Python, Ruby, C, C++, Java, C#, Bash, Go, Rust, Haskell, Perl, Lua, Kotlin, and Scala.
✨ New Features
Stdin Forwarding to Executed Commands
Previously, cmd.Stdin was not wired up in the executor — any data piped into a container was silently dropped. The fix is one line, but the capability it unlocks is significant:
cmd := exec.Command(cmdPath, cmdArgs...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin // NEW — forwards container stdin to the commandThis means fraglets can now behave like real command-line tools that accept piped input:
# Single-line pipe
echo "hello world" | docker run --rm -i -v ./my-script.py:/FRAGLET:ro 100hellos/python:latest
# Multi-line stream
cat data.csv | docker run --rm -i -v ./process.rb:/FRAGLET:ro 100hellos/ruby:latest
# Binary data
cat image.png | docker run --rm -i -v ./analyze.py:/FRAGLET:ro 100hellos/python:latest
# Stdin + positional args
echo "input" | docker run --rm -i -v ./tool.sh:/FRAGLET:ro 100hellos/bash:latest --verbose arg1No configuration changes required — every existing container image benefits from a binary upgrade.
🧪 Testing
Three new integration test suites exercise the feature end-to-end:
stdin_passthrough
Builds an isolated test container and validates the core mechanics:
- Basic single-line pipe
- Multi-line stdin
- Stdin combined with positional arguments
- Graceful behavior when no stdin is provided
- Binary byte-count verification
stdin_languages
Mounts the locally-built entrypoint binary into real 100hellos containers and pipes data through fraglets written in Python, Ruby, C, C++, Java, and C#. Also tests stdin + args together (Python).
stdin_languages_extended
Same approach, covering Bash, Go, Rust, Haskell, Perl, Lua, Kotlin, and Scala. All 14 languages read stdin with their native idioms and produce expected output.
Running the tests
make test-entrypoint🚀 Upgrading
The change is fully backward-compatible. Containers that don't use stdin are unaffected — os.Stdin simply has no data to deliver.
For 100hellos containers: update the fraglet-entrypoint version and sha256 in the base Dockerfile (001-base) to point at the v0.4.0 release. No other changes needed — every language container that inherits from the base picks up stdin support automatically.
Usage note
Remember -i on docker run when piping data — without it, Docker closes stdin before the container can read it:
echo "hello" | docker run --rm -i -v ./my-fraglet.py:/FRAGLET:ro 100hellos/python:latestfraglet-entrypoint v0.3.0
Release v0.3.0
Key Highlights
- Direct file replacement: fraglet-entrypoint can now overwrite an entire target file when
injection.codePathis provided without match markers. Enables Brainfuck-style workflows where the program is the whole file. - Smarter config parsing: loader now distinguishes between line, range, and file injections instead of silently resetting
codePath-only configs. - Expanded test coverage: integration suite exercises the file replacement path and new unit tests lock the injection-mode helpers.
✨ New Features
Direct File Replacement (Brainfuck-ready)
- Detects
codePathwithoutmatch/match_start/match_endand copies the fraglet payload directly over the destination file. - Runs as the container user, preserving permissions and honoring
execution.makeExecutable. - Works seamlessly with existing
usage/guidecommands; usage now reports “entire file replacement” when no markers exist.
Injection Mode Helpers
- Added
isLineInjection,isRangeInjection, andisFileInjectionhelpers. isEmptyInjectionnow only fires when no injection mode is configured, preventing accidental fallbacks to defaults.
🔧 Configuration
File Replacement Example (fraglet.yaml)
fragletTempPath: /FRAGLET
injection:
codePath: /code/hello-world.bf # no markers → entire file is replaced
guide: /guide.md
execution:
path: /code/hello-world.bf
makeExecutable: trueLine / Range Modes (unchanged)
- Still specify
matchfor single-line replacement ormatch_start+match_endfor regions. - You can mix in a custom
codePathwith either mode.
🧪 Testing
entrypoint/tests/docker_integrationnow includes Test 3 which mounts a shebang’d fraglet, replaces/code/hello-world-replace.sh, and proves execution works end-to-end.- Added
pkg/fraglet/config_test.goto enforce the injection helper behavior. make test-entrypointandgo test ./pkg/fraglet/...must be green before tagging.
🚀 Building the Binary
cd entrypoint
GOOS=linux GOARCH=amd64 go build -o dist/linux_amd64/fraglet-entrypoint ./cmd
# Repeat for other arches as needed🧩 Integrating with 100hellos/brainfuck
- Copy the new
fraglet-entrypointbinary into the image (e.g./usr/local/bin/fraglet-entrypoint). - Add a
fraglet.yamllike the file replacement example above. - Set the container entrypoint to the binary:
COPY fraglet-entrypoint /usr/local/bin/fraglet-entrypoint COPY fraglet-brainfuck.yaml /fraglet.yaml ENTRYPOINT ["/usr/local/bin/fraglet-entrypoint"]
- Build the image (tag
100hellos/brainfuck:local) and test it via MCP:docker build -t 100hellos/brainfuck:local -f brainfuck/Dockerfile . mcp run brainfuck '++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>++.'