Skip to main content
@cycls.app is a function that returns an ASGI application. Cycls serves it, gives it a URL, and wires in identity and storage.
notes.py

The decorator

The body runs inside the container at startup. Import heavy dependencies there, not at module level, so your local process stays light.

Identity

With auth= set, two dependencies become available on the decorated object.
user carries id, org_id, org_slug, org_role, org_permissions, plan and features. See Authentication for providers and claims.

Storage

notes.workspace resolves a per-user scope on the volume mounted at /workspace. Two things live there:
Atomic per key, prefix scans, JSON values. Backed by the volume, so it survives redeploys.
Both need a volume at /workspace. Without one the error arrives on first use, not at deploy, so declare it whenever the app touches storage.

Serving a front end

Bundle the HTML with the image and return it from a route.
The publishable key is resolved at request time, so the same file works locally and in production without a build step.

Running untrusted commands

cycls.Sandbox is a fluent wrapper around bubblewrap for executing commands with a read-only root, a cleared environment and no network unless you ask.
Every method returns a new sandbox, so a shared base is safe to extend per request. cycls.Sandbox() already mounts /tmp, /dev and /proc and dies with its parent. cycls.SandboxResult carries stdout and stderr as bytes, the exit code, timed_out, and .output, both streams decoded into one string. env= is the environment of bwrap itself, not of the command. Without it, bwrap runs with your app’s full environment, secrets included, so pass a minimal one as the example does.

Programmatic control

For python notes.py to serve, guard it the usual way:

Next

Agents

The chat layer on top of apps: a managed model loop, tools and a web UI.