Skip to content

Releases: ofthemachine/fraglet

fraglet-entrypoint v0.6.0

04 May 07:29

Choose a tag to compare

Release v0.6.0

Key Highlights

  • Per-mode essence — optional essence field in fraglet.yaml (same path resolution as guide), fraglet-entrypoint essence, and fragletc 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.0

This 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.0

Update the sha256 checksums to match the new release binaries.

fragletc v0.6.0

28 Mar 05:02

Choose a tag to compare

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.
  • --param support — pass parameters to fraglets via CLI, declared in code via fraglet-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.0

This 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/ replaces cli/ as the binary source
  • Build info now at cmd/fragletc/build-info.json
  • Test harness extracted to external github.com/ofthemachine/clitest package
  • go install path is now github.com/ofthemachine/fraglet/cmd/fragletc@latest

fraglet-entrypoint v0.5.0

28 Mar 05:13

Choose a tag to compare

Release v0.5.0

Key Highlights

  • Breaking: fraglet.yml mode management restructured — modes are now defined inline via a modes map, replacing the previous per-file approach. Designed for "fat" containers with many execution modes.
  • makeExecutable removed — 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.0 tags instead of bare v0.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.sh

Fields 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.0

This 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/clitest package
  • All entrypoint domain files (releases, tests, schema reference) now live under cmd/entrypoint/

Upgrading

ARG FRAGLET_VERSION=entrypoint-v0.5.0

Update 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

06 Mar 05:30

Choose a tag to compare

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/store

The 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=X only 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, sets FRAGLET_CONFIG=/fraglet-<mode>.yml in 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_64
  • fragletc-linux-arm64 — Linux ARM64
  • fragletc-windows-amd64.exe — Windows x86_64
  • fragletc-darwin-amd64 — macOS Intel
  • fragletc-darwin-arm64 — macOS Apple Silicon
  • build-info.json — embedded provenance (for reproducible build verification)
  • checksums.txt — SHA256 checksums for all binaries

fragletc v0.4.0

03 Mar 07:41

Choose a tag to compare

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.txt

Build 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_64
  • fragletc-linux-arm64 — Linux ARM64
  • fragletc-windows-amd64.exe — Windows x86_64
  • fragletc-darwin-amd64 — macOS Intel
  • fragletc-darwin-arm64 — macOS Apple Silicon
  • build-info.json — embedded provenance (for reproducible build verification)
  • checksums.txt — SHA256 checksums for all binaries

fragletc v0.3.0

27 Feb 17:28

Choose a tag to compare

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 lang parameter maps to --vein in 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_64
  • fragletc-linux-arm64 — Linux ARM64
  • fragletc-windows-amd64.exe — Windows x86_64
  • fragletc-darwin-amd64 — macOS Intel
  • fragletc-darwin-arm64 — macOS Apple Silicon

fragletc v0.2.0

27 Feb 08:28

Choose a tag to compare

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_64
  • fragletc-linux-arm64 — Linux ARM64
  • fragletc-windows-amd64.exe — Windows x86_64
  • fragletc-darwin-amd64 — macOS Intel
  • fragletc-darwin-arm64 — macOS Apple Silicon

fragletc v0.1.0

18 Feb 07:26

Choose a tag to compare

fragletc v0.1.0

Initial release of the fraglet CLI.

Artifacts

  • fragletc-linux-amd64 — Linux x86_64
  • fragletc-linux-arm64 — Linux ARM64
  • fragletc-windows-amd64.exe — Windows x86_64

Usage

See repo README and fragletc --help.

fraglet-entrypoint v0.4.0

12 Feb 06:53

Choose a tag to compare

Release v0.4.0

Key Highlights

  • Stdin passthrough: fraglet-entrypoint now forwards the container's stdin to the executed command, enabling echo "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 command

This 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 arg1

No 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:latest

fraglet-entrypoint v0.3.0

24 Nov 07:30

Choose a tag to compare

Release v0.3.0

Key Highlights

  • Direct file replacement: fraglet-entrypoint can now overwrite an entire target file when injection.codePath is 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 codePath without match / match_start / match_end and 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 / guide commands; usage now reports “entire file replacement” when no markers exist.

Injection Mode Helpers

  • Added isLineInjection, isRangeInjection, and isFileInjection helpers.
  • isEmptyInjection now 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: true

Line / Range Modes (unchanged)

  • Still specify match for single-line replacement or match_start + match_end for regions.
  • You can mix in a custom codePath with either mode.

🧪 Testing

  • entrypoint/tests/docker_integration now 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.go to enforce the injection helper behavior.
  • make test-entrypoint and go 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

  1. Copy the new fraglet-entrypoint binary into the image (e.g. /usr/local/bin/fraglet-entrypoint).
  2. Add a fraglet.yaml like the file replacement example above.
  3. 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"]
  4. Build the image (tag 100hellos/brainfuck:local) and test it via MCP:
    docker build -t 100hellos/brainfuck:local -f brainfuck/Dockerfile .
    mcp run brainfuck '++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>++.'