This release is a pre-release and may not be stable for production use.
buddelkiste
Run a command in a rootless sandbox (bk): filesystem and process isolation
via bubblewrap, plus optional
network controls — share the host stack, cut connectivity entirely, or filter
egress with pasta/slirp4netns and in-namespace nftables (IP/CIDR and hostname
rules, no root required).
Usage
# Run a command in the sandbox
bk run /path/to/executable [args...]
# Inspect the sandbox (login shell)
bk run
# Catalog helpers
bk list-features
bk list-net-presets
bk info # merged config for cwd
bk info cursor-agent # plus that executable's overlays
# PATH shims for configured [executables.*]
bk shims install
bk shims check
bk shims list
# Topic features (only ``user`` on by default)
bk run --feature python --feature ssh python myscript.py
bk run --feature cursor --feature gui cursor-agent
# Network modes (filter is the default; policy allow, denies private + localhost)
bk run --network host … # share host network
bk run --network none … # no connectivity
bk run --network filter \
--net-policy deny \
--net-allow 1.1.1.1/32 \
--net-allow api.github.com \
--net-allow '*.pypi.org' \
--net-deny-preset metadata …
bk run wrapper options: --debug, --feature / --no-feature,
--network, --net-policy, --net-allow, --net-allow-preset,
--net-deny, --net-deny-preset,
--dbus-see, --dbus-talk, --dbus-own, --dbus-call, --dbus-broadcast.
Everything else is the sandboxed command.
Features
Optional permission sets are grouped by topic. Only user is enabled by
default; every other built-in is opt-in. Toggle with CLI flags or config; see
bk list-features for the live catalog (including each feature's module path).
| Feature | What it grants |
|---|---|
asdf |
~/.asdf, ~/.tool-versions, ASDF_DIR |
cursor |
Cursor IDE/CLI install and state dirs |
dbus |
session/system bus sockets, DBUS_SESSION_BUS_ADDRESS |
dbus-proxy |
session bus via xdg-dbus-proxy; optional see/talk/own/call/broadcast filter (conflicts with dbus) |
docker |
~/.docker, Docker socket / DOCKER_HOST (conflicts with docker-proxy / docker-instance) |
docker-proxy |
Filtered Docker API proxy + image allowlist (conflicts with docker / docker-instance) |
docker-instance |
Project-local rootless dockerd + FS/net isolation (conflicts with docker / docker-proxy) |
git |
~/.gitconfig, ~/.config/git |
google |
/opt/google |
gui |
display, GPU, audio, fonts, related env |
java |
OpenJDK /etc/java-*-openjdk configs |
node |
npm/nvm/bun paths, BUN_INSTALL |
nvim |
~/nvim |
python |
pip/virtualenv paths and env |
rust |
shared ~/.cargo / ~/.rustup (or CARGO_HOME / RUSTUP_HOME) |
ssh |
~/.ssh/config plus a dedicated agent with ~/.ssh/sandbox_* keys |
user |
~/.local (ro), ~/.cache (rw), locale and terminal env (LANG, LC_*, TERM, EDITOR, …) — default on |
xdg-open |
host xdg-open via flatpak-xdg-utils |
CLI
bk list-features
# Tighten a desktop-ish run
bk run --no-feature gui --no-feature dbus --no-feature xdg-open curl https://example.com
# Minimal toolchains for a script
bk run --no-feature cursor --no-feature google --feature python --feature git python app.py
# Allowlist-style: disable broadly in config, then enable what you need
bk run --feature ssh --feature git git fetch
Precedence (later wins for CLI flags): feature defaults → global config
features → per-executable executables.<name>.features →
active [[projects]] features → --feature / --no-feature.
bk info (optional executable name) prints that merged view as TOML.
D-Bus proxy
dbus-proxy publishes a private session-bus socket from xdg-dbus-proxy and
sets DBUS_SESSION_BUS_ADDRESS to it. It conflicts with dbus.
With no rules the proxy is unfiltered (full session bus). xdg-dbus-proxy
rejects a bare * name, so filtering is opt-in: set any of see, talk,
own, call, or broadcast and the proxy is started with --filter and
only those rules. An explicit empty list turns filtering on without rules of
that kind.
| Key | Flag | Value |
|---|---|---|
see |
--see / --dbus-see |
well-known name the sandbox may see |
talk |
--talk / --dbus-talk |
name the sandbox may call (implies see) |
own |
--own / --dbus-own |
name the sandbox may own (implies talk and see) |
call |
--call / --dbus-call |
NAME=RULE for method calls |
broadcast |
--broadcast / --dbus-broadcast |
NAME=RULE for broadcast signals |
Names may end in .* (org.freedesktop.portal.* matches
org.freedesktop.portal and org.freedesktop.portal.Desktop, not
org.freedesktop.portalextra). RULE is [METHOD][@PATH]: METHOD is *,
an interface, interface.*, or interface.member; PATH is an object path
with an optional /* suffix.
Precedence for each key: global [dbus_proxy], then the same key under
executables.<name>.dbus_proxy (replaces that key), then repeatable CLI flags
(appended).
bk run --feature dbus-proxy \
--dbus-talk org.freedesktop.Notifications \
--dbus-talk 'org.freedesktop.portal.*' \
--dbus-call 'org.freedesktop.portal.*=*' \
--dbus-broadcast 'org.freedesktop.portal.*=@/org/freedesktop/portal/*' \
cursor-agent
Config
Configuration is read from ~/.config/buddelkiste/config.toml.
# Global allowlist (exactly these features), or use a table of overrides:
# features = { gui = false, google = false }
features = ["user", "git", "ssh", "python", "rust"]
[feature.zig]
description = "Zig toolchain cache"
default = false
env = ["ZIG_GLOBAL_CACHE_DIR"]
[[feature.zig.binds]]
source = "$ZIG_GLOBAL_CACHE_DIR"
mode = "rw"
[[feature.zig.binds]]
source = "${HOME}/.zig"
mode = "ro"
[[feature.zig.binds]]
source = "${HOME}/.cache/zig"
mode = "overlay" # persistent upper under $XDG_CACHE_HOME/buddelkiste/overlays/<hash>
[executables.cursor-agent]
features = ["user", "cursor", "git", "ssh", "gui", "dbus", "xdg-open"]
args = ["--force"]
[[projects]]
path = "/home/me/src/myapp"
features = { python = true, rust = true }
network.mode = "filter"
[executables.cursor-agent.network]
mode = "filter"
policy = "deny"
allow = ["1.1.1.1/32", "api.github.com"]
# Session-bus filter for the dbus-proxy feature (omit for an unfiltered proxy).
[dbus_proxy]
talk = ["org.freedesktop.Notifications", "org.freedesktop.portal.*"]
call = ["org.freedesktop.portal.*=*"]
broadcast = ["org.freedesktop.portal.*=@/org/freedesktop/portal/*"]
[executables.cursor-agent.dbus_proxy]
own = ["org.example.MyApp"]
[executables.python]
features = { python = true, git = true, gui = false }
shim = false
# Docker proxy: declare images in config, then `bk docker-policy apply`
# (enforcement files live under ~/.config/buddelkiste/docker-proxy/).
[docker_proxy]
images = ["alpine:3.20", "postgres:16-alpine", "ghcr.io/example/*"]
# on_unknown_image = "session" # default: hold until approve/deny
# on_unknown_image = "deny" # immediate 403 (good for CI)
# Project-local rootless daemon (docker-instance feature; default off)
# [docker_instance]
# fs = "project" # host | project | data
# net = "userspace" # host | userspace | none
# # data_root = "$XDG_DATA_HOME/buddelkiste/docker-instance/myproj"
# # fs_allow = ["$HOME/.cache/go-build"]
# # [docker_instance.policy]
# # images = ["*"]
# shims = false # disable PATH shims globally (per-entry shim = true still wins)
[[binds]]
source = "/path/to/directory"
mode = "ro" # or "rw", "tmp-overlay", "overlay", "overlay:$XDG_CACHE_HOME/bk-upper"
[[binds]]
source = "${HOME}/scratch"
target = "/mnt/scratch"
mode = "tmp-overlay" # writable in the sandbox; host tree unchanged
[[binds]]
glob = "${HOME}/.config/git*"
mode = "ro"
[[binds]]
glob = "${HOME}/.ssh/id_*"
nullglob = true
mode = "ro"
[[envvars]]
name = "MYENVVAR"
value = "example value" # omit value= to take it from the process environment
[network]
# Defaults: mode = "filter", policy = "allow",
# deny_presets = ["internal", "localhost"] (RFC1918/ULA + loopback).
mode = "filter"
policy = "allow"
allow = ["1.1.1.1/32", "api.github.com", "*.pypi.org"]
deny = ["203.0.113.0/24"]
deny_presets = ["internal", "localhost", "metadata", "linklocal", "corp"]
# allow_presets = ["metadata"] # same preset names, added to allow
[network.presets]
corp = ["10.50.0.0/16", "*.internal.example.com"]
Bind mode values:
| Mode | Meaning |
|---|---|
ro |
read-only bind (default) |
rw |
read-write bind |
tmp-overlay |
overlayfs; writes are ephemeral |
overlay |
overlayfs; upper under $XDG_CACHE_HOME/buddelkiste/overlays/<sha256(source)> |
overlay:<path> |
overlayfs with an explicit upper path ($VAR / ${VAR} / ~ ok) |
Paths in source, glob, target, and overlay:<path> may use $VAR / ${VAR}.
A glob table binds every matching file or directory with the same mode.
nullglob = true allows the pattern to match nothing; the default is to error.
With glob, an optional target is a directory and each match is mounted at
target/<basename>.
The current working directory must be visible inside the sandbox. If it is not
covered by any bind, bk asks yes (this run), always (persist a
[[projects]] entry), or no (abort), then which features to enable. A
project is always bound read-write. Non-interactively it errors instead.
[[projects]]
path = "/home/me/src/myapp"
features = { python = true, rust = true }
network.mode = "filter"
PATH shims
For each [executables.<name>] entry with shimming enabled, bk shims install
writes a small sh wrapper into $XDG_DATA_HOME/buddelkiste/shims (default
~/.local/share/buddelkiste/shims). The shim resolves the real binary
(skipping its own directory) and runs bk run <real> "$@". Shims include a
# buddelkiste-shim: marker so later installs can refresh our own files
without overwriting unrelated binaries.
Install also writes $XDG_DATA_HOME/buddelkiste/shims.sh and, if they
already exist, appends a marked include to ~/.bashrc and ~/.zshrc. Paths
in those snippets use $HOME so the same rc file works for different users.
Interactive shells source the snippet, prepend the shim directory to PATH,
and run bk shims check --quiet.
Toggle with a global shims boolean (default true) and optional per-entry
shim = true/false overrides. Disabled entries remove a managed shim on the
next install.
shims = true
[executables.cursor-agent]
features = ["cursor"]
[executables.python]
shim = false
bk shims install # create/update/remove shims and the shell hook
bk shims check # warn if an original binary appears earlier on PATH
bk shims check -q # warnings only (used by the startup snippet)
bk shims list # configured/installed shims and the binaries they wrap
bk shims check exits non-zero when something would bypass the sandbox.
Python features (entry points)
Built-ins and third-party packages register features under the
buddelkiste.features entry-point group. The entry point value must be a
Feature instance, or a zero-argument callable that returns one. When loaded,
name and origin are set from the entry-point name and value
(e.g. labs / mypkg.features:LABS).
Feature fields:
| Field | Type | Default | Meaning |
|---|---|---|---|
name |
str |
(required) | Feature id used in CLI/config (--feature, features = [...]). Overwritten by the entry-point name at load time. |
description |
str |
(required) | One-line summary shown by bk list-features. |
default |
bool |
False |
Whether the feature is enabled before config/CLI overrides. |
env_vars |
tuple[str, ...] |
() |
Host env var names to forward into the sandbox when the feature is on. |
binds |
Callable[[], list] |
lambda: [] |
Zero-arg callable returning bind objects (ROBindConfig, RWBindConfig, DevBindConfig, overlay configs, Tmpfs, or raw bwrap arg tuples). Called each run. |
setup |
Callable[[], AbstractContextManager[Sequence[str]]] | None |
None |
Optional factory returning a context manager. Entered while the sandbox runs; its yielded sequence is appended as extra bwrap args (binds, --setenv, …). Use for sockets/agents that need lifecycle. |
required_commands |
tuple[str, ...] |
() |
Host executables required when the feature is enabled. bk run fails early with a descriptive error if any are missing. |
conflicts_with |
tuple[str, ...] |
() |
Feature names that must not be enabled together (checked before launch). |
origin |
str |
"" |
Shown in bk list-features. Overwritten by the entry-point value at load time (e.g. mypkg.features:LABS). |
# mypkg/features.py
from collections.abc import Iterator, Sequence
from contextlib import contextmanager
from pathlib import Path
from buddelkiste.binds import ROBindConfig, RWBindConfig
from buddelkiste.features import Feature
def labs_binds() -> list:
home = Path.home()
return [
RWBindConfig(home / ".labs"),
ROBindConfig(home / ".config/labs"),
]
@contextmanager
def labs_setup() -> Iterator[Sequence[str]]:
# Optional: start helpers, yield extra bwrap args, clean up on exit.
# Built-in ssh uses this pattern for a dedicated ssh-agent.
yield []
LABS = Feature(
name="labs", # replaced by entry-point name "labs" when loaded
description="Lab tooling directories",
default=False,
env_vars=("LABS_HOME",),
binds=labs_binds,
setup=labs_setup, # or omit / None
origin="mypkg.features:LABS", # replaced by entry-point value when loaded
)
# pyproject.toml
[project.entry-points."buddelkiste.features"]
labs = "mypkg.features:LABS"
After install, bk list-features shows the entry and its origin. Pure-TOML
[feature.<name>] covers env/bind cases without a package; use Python entry
points for custom bind logic or setup hooks. Config feature names must not
collide with an existing entry point.
Docker proxy
The raw docker feature exposes the host Docker socket. Prefer docker-proxy
when a sandboxed tool (agent, CI helper, …) should talk to Docker without a full
socket: the host bk process runs a filtered API proxy, binds only that socket
into the sandbox, and sets DOCKER_HOST to it.
docker, docker-proxy, and docker-instance conflict; enable only one.
Enable
# One-off
bk run --no-feature docker --feature docker-proxy docker version
# Or in config (docker-proxy defaults to off)
features = { docker = false, docker-proxy = true }
[executables.cursor-agent]
features = { docker = false, docker-proxy = true }
Policy layers
Effective policy is the merge of, in order:
- Host store —
~/.config/buddelkiste/docker-proxy/<project-key>.toml(per active[[projects]]path, or cwd) - Session grants — same dir,
<project-key>.session.toml(written bybk docker-policy approve) - Config declaration — optional
[docker_proxy]in user config (used byapply; also merged when present)
bk docker-policy path # host store path for this project
bk docker-policy show # effective images + on_unknown_image
bk docker-policy apply # copy [docker_proxy] from config → host store
bk docker-policy apply --dry-run
Declare images in config, then apply once (or edit the host file from path):
[docker_proxy]
images = [
"alpine:3.20",
"postgres:16-*",
"ghcr.io/myorg/*",
]
# Optional; default is "session"
# [docker_proxy.approval]
# on_unknown_image = "deny"
Image patterns use shell-style globs (fnmatch). A pattern ending in :* also
matches the untagged name (Docker’s implied :latest). Digests are stripped
before matching (repo:tag@sha256:… → repo:tag).
What the proxy allows and denies
Forwarded by default: ordinary Engine API traffic for allowlisted images
(create/start/attach/pull of listed refs, version, info, …).
Denied by default (403), even for allowlisted images:
- Dangerous
HostConfig— privileged, host network/PID/IPC/UTS/userns,CapAdd, device mounts, … - Host bind mounts unless the source matches
allow_bindsglobs in the policy - API categories: build, commit, swarm, plugins, session
Unknown images (not on the allowlist):
on_unknown_image |
Behaviour |
|---|---|
session (default) |
Hold the HTTP request until you approve or deny on the host |
deny |
Immediate 403 (suitable for CI) |
Interactive approval (host only)
With on_unknown_image = "session" (the default), unknown images are not
prompted on the sandboxed client’s TTY. Approval is an out-of-band host
workflow so agent/CI sessions keep a clean shared terminal.
Flow
- Inside the sandbox, a client does something that needs an unknown image
(e.g.
docker pull alpine:3.21ordocker run …). - The proxy holds the HTTP request (the client blocks / waits). Concurrent waits for the same image share one pending entry.
- On the host, the proxy logs the hold and (best-effort) shows a desktop
notification via
notify-send, including the pending id and a ready-to-runbk docker-policy approve <id>hint. - On the host (another terminal, outside the sandbox), decide:
bk docker-policy pending # id<TAB>image
bk docker-policy approve # if exactly one pending
bk docker-policy approve alpine:3.21 # by image or pending id
bk docker-policy deny deadbeef
- Approve appends the image to the session policy file
(
…/<project-key>.session.toml), unblocks waiters, and lets the original create/pull continue (HostConfig / API denials still apply). - Deny (or proxy teardown) unblocks with 403.
The control socket is not mounted into the sandbox — pending /
approve / deny only work on the host while that project’s proxy is live
(see …/<key>.runtime.json).
If you miss the notification
notify-sendmissing or failing → proxy logs a warning with the sameapprovecommand; usebk docker-policy pendingor the proxy logs.- Session grants last for that project’s proxy lifetime / session file;
promote durable allowlists with
[docker_proxy]+bk docker-policy apply(or edit the host store frombk docker-policy path).
Operational notes
- Live proxy metadata:
~/.config/buddelkiste/docker-proxy/<key>.runtime.json(pid, control socket path). Cleared when the sandbox exits. - The proxy only supports
unix://Docker sockets (DOCKER_HOSTon the host). - Socket paths are kept short enough for
AF_UNIX(including a sibling.ctlcontrol socket).
Docker instance
docker-instance starts a temporary rootless dockerd with a dedicated
store for this project, then (by default) puts the filtered API proxy in front
and binds only that socket into the sandbox. Images and volumes live under
$XDG_DATA_HOME/buddelkiste/docker-instance/<project-key>/ (override with
data_root) and do not touch the user-global Docker engine. The store is kept
when the sandbox exits unless remove_data_on_teardown = true (or
bk run --docker-instance-remove-data). Overlay snapshot work dirs are left
mode 000; bk docker-instance prune (and teardown wipe) chmod them so they
can be deleted.
Requires: dockerd, rootlesskit, newuidmap/newgidmap, /etc/subuid and
/etc/subgid entries for your user; for net = "userspace" also pasta
(passt) or slirp4netns. Storage defaults to whatever dockerd picks (auto);
set storage_driver (or --docker-instance-storage-driver) to overlay2,
fuse-overlayfs, or vfs. Do not switch drivers on a non-empty data_root
without pruning first.
bk run --no-feature docker --feature docker-instance docker version
bk docker-instance list
bk docker-instance prune # current project (prompts)
bk docker-instance prune --all -y # every default-home store
bk docker-instance prune proj-abc123 -y # by directory name
features = { docker = false, docker-instance = true }
[docker_instance]
fs = "project" # host | project | data — daemon mount namespace
net = "userspace" # host | userspace | none
# data_root = "/path/to/store"
# fs_allow = ["$HOME/.cache/go-build"]
proxy = true # agent sees only the filtered proxy socket
# remove_data_on_teardown = true # wipe data_root when bk run exits
# storage_driver = "fuse-overlayfs" # auto | overlay2 | fuse-overlayfs | vfs
# Optional; defaults allow build + /session and images=["*"] on this private daemon
# [docker_instance.policy]
# images = ["*"]
# [docker_instance.policy.api]
# deny = ["commit", "swarm", "plugins"]
fs |
Daemon can see |
|---|---|
host |
Full host filesystem (store still isolated) |
project (default) |
Project root, data_root, fs_allow, minimal system paths |
data |
data_root + fs_allow + minimal system only |
net |
Behaviour |
|---|---|
userspace (default) |
rootlesskit pasta/slirp4netns; dockerd iptables+forward on so bridge containers can use DNS/egress |
host |
Share host network with the daemon helper |
none |
No network for the daemon helper |
HostConfig denials (privileged, host net, CapAdd, arbitrary binds, …) still
apply when proxy = true. Unlike host docker-proxy, instance policy defaults
allow docker build and BuildKit /session, and use images = ["*"] on
this private store. BuildKit via the Docker CLI also needs a working
docker-buildx plugin on the host; without it, install buildx or use
DOCKER_BUILDKIT=0 for the legacy builder.
Network filter dependencies
network.mode = "filter" needs pasta (from passt) or slirp4netns, plus
nft and setpriv. No root and no reserved host subnets are required.
Hostname rules start a DNS proxy that redirects UDP/53 and updates dynamic
nftables allow sets from resolved A/AAAA records. Default policy is allow:
public egress is accepted, and the internal and localhost deny presets
reject private ranges (RFC1918/ULA) and loopback. policy = "deny" rejects
every destination that is not listed in allow. The chain policy stays drop
because a base chain cannot use reject as its policy. When resolv.conf is
only a loopback stub, sandbox DNS is relayed to that stub from the host netns
and systemd-resolved chooses the uplinks. Other nameserver IPs from
/etc/resolv.conf are auto-allowed so DNS still works under that deny policy.
Development
uv sync --group dev
uv run bk --help
uv run pytest # unit + integ + host e2e + coverage
uv run pytest -m integration # nested-safe real bwrap (host/none)
uv run pytest -m e2e # host e2e: filter/tun, nested ns, docker
uv run pytest -m "not e2e" # exclude host e2e (use inside a bwrap sandbox)
Integration layout:
tests/— unit/contract tests (mocked subprocess where needed)tests/integ/— nested-safe realbwrap(host/none), binds/env isolation; nestednft/netns cases are markede2etests/integ_net/— filter-mode e2e via pasta/slirp (allow/deny IP & host, guest caps); markede2etests/integ_docker/— docker-proxy / docker-instance e2e; markede2e
Release
scripts/release sets the project version in pyproject.toml, refreshes
uv.lock, commits that bump on the current branch, and tags
v<version>. It then builds an sdist and a universal wheel into
dist/<version>/. Older version directories are left in place. dist/latest
points at the version just built, and dist/stable points at the newest
tagged final release. A release or release candidate is created only from
main or master. After the build succeeds, a final release pushes that
branch and the tag to the branch's upstream. A release candidate is not
pushed. Unless --dry-run is set, the artifacts are published with
uv publish (uv's configured index and credentials) after that push.
just release 0.2.0
just release calls scripts/release. When the version is omitted on a TTY,
the script prints commit summaries since the last release and prompts for
one. Hitting return accepts the guessed next release.
just release
just release 0.2.0 --dry-run
just rc tags a release candidate of a future version. Pass the upcoming
release and the next free rcN is chosen from the local tags, or pass the
candidate itself:
just rc 0.3.0
# pyproject.toml 0.3.0rc1
just rc 0.3.0rc2 --dry-run
just rc
A version with an rcN suffix is a pre-release, so pip and uv keep
installing the current final release until someone asks for the candidate
(buddelkiste==0.3.0rc1) or passes --pre. The candidate is committed on
the release branch and tagged (v0.3.0rc1) before the build. dist/latest
and dist/rc point at it; dist/stable stays on the last final release.
Publish the local tag with git push --follow-tags.
just pre builds a developmental pre-release from any branch. The version
carries the short commit hash, a UTC timestamp, and the login name:
just pre
# pyproject.toml 0.3.0.dev0+abcdef1.20261008120000.mvb
just pre 0.3.0 --dry-run
It is committed on the current branch and tagged before the build, and it
is not pushed. dist/latest points at it; dist/stable and dist/rc stay
where they are. pip and uv treat it as a pre-release, so it is installed
only for that exact version or with --pre.
Metadata
Release files for buddelkiste 0.4.3rc1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| buddelkiste-0.4.3rc1.tar.gz | 185.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| buddelkiste-0.4.3rc1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 278.7 kB
Release files / buddelkiste-0.4.3rc1.tar.gz
| Download URL | buddelkiste-0.4.3rc1.tar.gz |
|---|---|
| Size | 185.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1e5d1091ddeb3de1ae5cad15a3409d8bf019cc4577bb896724c38bf68699a229
|
|
BLAKE2b-256 checksum How to use checksums |
07099011a843603b0b8f38fc02b286e7ece6eb35eeda6e57bf2bed9a94c163eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / buddelkiste-0.4.3rc1-py3-none-any.whl
| Download URL | buddelkiste-0.4.3rc1-py3-none-any.whl |
|---|---|
| Size | 93.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
56e27eb279e6fa99d22200faaad93a763f53e546cff0eccf135b276a33d6d39d
|
|
BLAKE2b-256 checksum How to use checksums |
dc8c8135e5b2d8c42153fc5ae4d5dc42c65fb76159ab6a224d70f7459cd205df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for buddelkiste 0.4.3rc1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.