Skip to main content

hedgebuddy

The Python side of HedgeBuddy. Hedge apps (OffShoot, FoolCat, EditReady, Canister) run a Python script when something happens, such as a copy finishing. This package gives that script:

  • its typed variables from the active HedgeBuddy profile;
  • the event payload;
  • a run record, so HedgeBuddy can show what happened.

Pure Python, no dependencies, Python 3.9+.

Install

Install it for the Python the Hedge apps use:

py -3 -m pip install hedgebuddy        # Windows
python3 -m pip install hedgebuddy      # macOS

Until 0.11.0 is on PyPI, install it from a checkout of this repository with py -3 -m pip install ./python.

HedgeBuddy's check_script tool tells you when it is missing.

A script

"""
{"hedgebuddy": 1,
 "app": "offshoot",
 "event": "FileCopyCompleted",
 "requires": {
   "SLACK_WEBHOOK": {"type": "secret", "description": "Incoming webhook URL"},
   "PROJECT_NAME":  {"type": "string", "default": "Untitled"}
 }}
---
Posts a summary to Slack after each card finishes.
"""
import json
import urllib.request

import hedgebuddy as hb


@hb.script
def main(event, vars):
    if event.state != "Success":
        hb.log(f"copy failed: {event.state}")
        return 1
    text = f"{vars.PROJECT_NAME}: {event.destinationPath} is done"
    body = json.dumps({"text": text}).encode()
    request = urllib.request.Request(vars.SLACK_WEBHOOK, body, {"Content-Type": "application/json"})
    urllib.request.urlopen(request, timeout=10)
    hb.log("posted to slack")

The manifest

The JSON at the top of the docstring, ended by a --- line, tells HedgeBuddy three things:

  • which app and event the script handles;
  • which variables it needs;
  • the type of each variable.

A variable with a default is optional. HedgeBuddy uses the manifest to attach the script to the right event and to check the profile before it runs. The types are string, secret, int, float, bool, path, url, string[] and path[].

@hb.script

When Hedge runs the file, the decorator does the following, in order:

  1. Finds the active profile.
  2. Starts a run record.
  3. Checks every required variable. If one is missing or has the wrong type, it stops and names it.
  4. Parses the event.
  5. Calls main(event, vars).
  6. Records the result and exits with main's return value.

None means success. A non-zero number means the run failed. Any other return value, or a number outside 0 to 255, is recorded as an error with exit code 1. An uncaught exception is recorded with its traceback. When the file is imported rather than run, for example by a test, the decorator returns main unchanged.

The profile's secret values are replaced with ******** in hb.log lines and tracebacks, both in the run record and on stderr. A secret shorter than four characters is not masked, so it does not mangle other text.

Put imports and helper functions above the decorated main, and keep main last in the file: the decorator runs it as soon as it is defined, so code below it has not run yet.

vars

vars.NAME or vars["NAME"] returns the value in its Python type:

Type Python value
path pathlib.Path
path[] list of Path
int int
float float
bool bool
string[] list of str
string, secret, url str

Secrets come from the profile's secrets file. vars.get("NAME", default) and "NAME" in vars work too.

Inside a script, vars.NAME falls back to the manifest default, while hb.var("NAME") reads only the profile.

event

The payload's keys, without the <EventName>_ prefix: event.state, event.destinationPath. A value that holds a JSON object or array is decoded for you. Other attributes:

  • event.raw is the original payload.
  • event.app and event.name identify the event.

A field that shares a name with one of these attributes is read with event["name"].

Other helpers

Call What it does
hb.var("NAME", default=...) One variable of the active profile. The default applies only when the variable is missing.
hb.exists("NAME") Whether the variable has a value.
hb.all_vars() Every variable with a value, typed.
hb.inject_env(overwrite=False) Copies every variable into os.environ as text. Bools become 1 or 0, and lists are joined with os.pathsep. Useful when you bring a script that already reads environment variables.
hb.log(message) Adds a line to the run record, or prints it outside a run.
hb.event() Parses the payload in scripts that do not use @hb.script.

Errors: VariableNotFoundError, VariableTypeError, StorageNotFoundError, StorageCorruptedError and ManifestError. They all derive from HedgeBuddyError.

Trying a script by hand

Pass the payload as the first argument. Point HEDGEBUDDY_DATA_DIR at a test data folder if you do not want the run recorded in your real one.

On Windows, in cmd:

py -3 on_copy_complete.py "{\"FileCopyCompleted_state\": \"Success\"}"

On macOS:

python3 on_copy_complete.py '{"FileCopyCompleted_state": "Success"}'

Metadata

Release files for hedgebuddy 0.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hedgebuddy 0.11.0
File Size Uploaded
hedgebuddy-0.11.0.tar.gz 76.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hedgebuddy 0.11.0
File Interpreter ABI Platform
hedgebuddy-0.11.0-py3-none-any.whl Python 3 none any Details

Total release size: 96.7 kB

Release files / hedgebuddy-0.11.0.tar.gz

Download URL hedgebuddy-0.11.0.tar.gz
Size 76.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ab357348d7b3d46f1e1d764bc5478322f9eaae153a6ae685b2b3e7898d3df558
BLAKE2b-256 checksum
How to use checksums
210b1d05e8ceb01228e19bcc77d350d911dcb8f9c5ab85f68b56ba1b6f91c7cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / hedgebuddy-0.11.0-py3-none-any.whl

Download URL hedgebuddy-0.11.0-py3-none-any.whl
Size 20.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
60f2870d068da6e5f0efa25e28ace9f91b4f575d71306c35805c6d50382ffe7b
BLAKE2b-256 checksum
How to use checksums
9b3c58193fcaf5e73666eaac88232b7a2020963626e8c6ce16f52df332f25734
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.11.0 This release

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.7

2 release files

0.8.5

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page