Bramble
Purely functional build system and package manager
Install / Use
/learn @maxmcd/BrambleREADME
- Project Status
- Installation
- Hello World
- Spec
Bramble is a work-in-progress functional build system inspired by Nix.
Bramble is a functional build system that intends to be a user-friendly, robust, and reliable way to build software. Here are some if the ideas behind it:
- Project Based: Every project has a
bramble.tomlandbramble.lockfile that track dependencies and other metadata needed to build the project reliably. - Reproducible: All builds are assumed to be reproducible. Every build must consistently return the same output given the same input. You can write builds that aren't reproducible but they'll likely break things.
- Rootless First:: Where possible, no root permissions are required to run. For sandboxing, user namespaces are used on Linux and
sandbox-execis used on macOS. Unclear how this will work beyond Linux and macOS. - Daemonless: Builds are executed directly and not handed off to a daemon.
- Sandboxed: All builds are sandboxed, running software with Bramble will be sandboxed by default. Builds also take as little input as possible (no args, no environment variables, no network). Some of these might be relaxed as the project evolves, but things will hopefully stay locked down.
- Dependencies: Dependencies are stored in repositories. You might reference them with
load("github.com/maxmcd/busybox")in a build file orbramble build bitbucket.org/maxm/foo:foofrom the command line. Dependencies are project specific. - Content-Addressable Store: Build outputs and build inputs are stored in directories that are named with the hash of their contents. This ensured build output can be verified and
- Remote Build: Future support for remote build execution.
- Starlark: The configuration language starlark is used to define builds.
- Diverse Build Environment Support: Will have first class support for all major operating systems and potentially even support for the browser, webassembly, FAAS, and others. (Bramble is Linux-only at the moment).
Project Status
Many things are broken, would not expect this to work or be useful yet. The list of features seems to be solidifying so hopefully things will be more organized soon. If you have ideas or would like to contribute please open an issue.
Feature Status
- [x] Basic Build Functionality
- [x] Store Content Relocation
- [ ] Sandboxing
- [x] Linux
- [ ] OSX
- [x] "Fetch" Build Rules
- [x] Fetch URL
- [x] Fetch Git Repo
- [x] Remote Dependencies
- [ ] Remote Builds
- [ ] Recursive Builds
- [ ] Documentation Generation
- [ ] Docker/OCI Container Build Output
Installation
Install with go get github.com/maxmcd/bramble or download a recent binary release. Linux is the only supported OS at the moment. macOS support should be coming soon, others much later.
Linux
In order for rootless/userspace sandboxing to work "User Namespaces" must be compiled and enabled in your kernel:
- Confirm
CONFIG_USER_NS=yis set in your kernel configuration (normally found in/proc/config.gz)$ cat /proc/config.gz | gzip -d | grep CONFIG_USER_NS CONFIG_USER_NS=y - Arch/Debian:
echo 1 > /proc/sys/kernel/unprivileged_userns_clone - RHEL/CentOS 7:
echo 28633 > /proc/sys/user/max_user_namespaces
Hello World
Here's an example project that downloads busybox and uses it to create a script that says "Hello world!".
./bramble.toml
[package]
name = "github.com/maxmcd/hello-example"
version = "0.0.1"
./default.bramble
def fetch_url(url):
"""
fetch_url is a handy wrapper around the built-in fetch_url builder. It just
takes the url you want to fetch.
"""
return derivation(name="fetch-url", builder="fetch_url", env={"url": url})
def fetch_busybox():
return fetch_url("https://brmbl.s3.amazonaws.com/busybox-x86_64.tar.gz")
def busybox():
"""
busybox downloads the busybox binary and copies it to an output directory.
Symlinks are then created for every command busybox supports.
"""
return derivation(
name="busybox",
builder=fetch_busybox().out + "/busybox-x86_64",
args=["sh", "./script.sh"],
sources=files(["./script.sh"]),
env={"busybox_download": fetch_busybox()},
)
def hello_world():
bb = busybox()
PATH = "{}/bin".format(bb.out)
return derivation(
"say_hello_world",
builder=bb.out + "/bin/sh",
env=dict(PATH=PATH, busybox=bb.out),
args=[
"-c",
"""set -e
mkdir -p $out/bin
touch $out/bin/say-hello-world
chmod +x $out/bin/say-hello-world
echo "#!$busybox/bin/sh" > $out/bin/say-hello-world
echo "$busybox/bin/echo Hello World!" >> $out/bin/say-hello-world
# try it out
$out/bin/say-hello-world
""",
],
)
./script.sh
set -e
$busybox_download/busybox-x86_64 mkdir $out/bin
$busybox_download/busybox-x86_64 cp $busybox_download/busybox-x86_64 $out/bin/busybox
cd $out/bin
for command in $(./busybox --list); do
./busybox ln -s busybox $command
done
If you copy these files into a directory you can build it like so:
$ bramble build ./:hello_world
bramble path directory doesn't exist, creating
✔ busybox-x86_64.tar.gz - 332.830943ms
✔ busybox - 88.136237ms
✔ url_fetcher.tar.gz - 424.225793ms
✔ url_fetcher - 46.129651ms
✔ fetch-url - 313.461369ms
✔ busybox - 152.799168ms
✔ say_hello_world - 29.742436ms
Huh, what's confusing. What are all these builds in our output? Bramble needs to pull some dependencies itself in order to fetch and unpack the url provided. This is so that you can pin the internal functionality of bramble to a specific version. This isn't all hooked up yet, but for the moment you can see the internals being built in the build output.
Now that the build is complete you'll see that a bramble.toml file has been written to the project directory.
./bramble.lock
[URLHashes]
"basic_fetch_url https://brmbl.s3.amazonaws.com/busybox-x86_64.tar.gz" = "uw5ichj6dhcccmcts6p7jq6etzlh5baf"
"basic_fetch_url https://brmbl.s3.amazonaws.com/url_fetcher.tar.gz" = "p2vbvabkdqckjlm43rf7bfccdseizych"
"fetch_url https://brmbl.s3.amazonaws.com/busybox-x86_64.tar.gz" = "uw5ichj6dhcccmcts6p7jq6etzlh5baf"
These are the three archives we had to download in order for the build to run. This will ensure that if we ever download these files again, the contents will match what we expect them to.
We can use bramble run to run the resulting script.
$ bramble run ./:hello_world say-hello-world
Hello World!
That's it! Your first build and run of a Bramble derivation.
Spec
This is a reference manual for Bramble. Bramble is a work-in-progress. I started writing this spec to solidify the major design decisions, but everything is still very much in flux. There are scattered notes in the notes folder as well.
Introduction
Bramble is a functional build system and package manager. Bramble is project-based, when you run a build or run a build output it must always be done in the context of a project.
Here are three example use-cases that Bramble hopes to support and support well.
- Running a build or a command related to a project. Often, code repositories want to explain how to build or run their software. Bramble aims to be one of the safest and most reliable ways to do that. A
bramble buildorbramble runwithin a project will use thebramble.toml,bramble.lockand source files to fetch dependencies from a cache or build them from source. Additionallybramble runcommands are sandboxed by default, so Bramble should be a good choice to run unfamiliar software. - Running arbitrary software from the internet. Running
bramble run github.com/username/project:function binarywill pull down software from that repo, build it, and run it within a sandbox on a local system.bramble runis sandboxed by default and aims to provide a safe and reproducible way to run arbitrary software on your system. - Build a Docker/OCI container. Any
bramble runcall can be packaged up into a container containing only the bare-minimum dependencies for that program to run. - Future use-cases. Support for WASM build environments, support for running builds in a browser. Tight integration with IDEs.
Project configuration
Every Project has a bramble.toml file that includes configuration information and a bramble.lock file that includes hashes and other metadata that are used to ensure that the project can be built reproducibly.
Package metadata
[package]
name =
Related Skills
node-connect
344.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
344.1kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
frontend-design
96.8kCreate 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.
openai-whisper-api
344.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
