🗂️ LiveFolders v0.22.0 — Now with concurrent shell session isolation — per-session invocation slots, async dispatch, SIGKILL escalation — Landlock (Linux) + sandbox-exec (macOS) — Apache 2.0 — Star us on GitHub! ★

What Is the Registry?

The LiveFolders Registry is a public index of community-built tools. Each entry points to a GitHub repository containing a folder.yaml manifest — the single file that defines how a LiveFolders tool behaves. The registry tracks the tool name, description, download count, and source URL. Nothing is hosted centrally; tools live in their authors’ GitHub repos.

🔍 Browse the Registry ► Publish a Tool

Installing Tools

Once you have LiveFolders installed, any registry tool is one command away:

# Install by owner/name slug livefolders install owner/toolname # Install a specific version (git tag) livefolders install owner/toolname@v1.2.0 # Install, then mount to make it available immediately livefolders install owner/toolname && livefolders mount

The CLI resolves the slug through the registry API, clones or downloads the folder.yaml from the source repository, and adds the tool to your local config. Re-running livefolders mount (or if it’s already running, the hot-reload picks it up within ~1 second) makes the tool’s files appear under .livefolders/tools/<name>/.

You can also search the registry from the command line or browse it on the web:

ActionCommand / URL
Installlivefolders install owner/name
Search (web)registry.livefoldersfs.org
Tool detail pageregistry.livefoldersfs.org/owner/name
Resolve APIGET /api/resolve/owner/name

Publishing a Tool

Publishing is free and open to anyone. You need a public GitHub repository with a folder.yaml in the root. The registry verifies ownership via a GitHub personal access token — the token is used in-flight and never stored.

Step 1 — Create your folder.yaml

Place a folder.yaml in the root of your GitHub repository. Here is a minimal example:

name: myweather description: Get current weather for any city. files: - name: forecast type: write_invoke description: Write a city name, read back the forecast. input: type: string min_length: 1 max_length: 100 handler: >- curl -s "https://wttr.in/${LIVEFOLDERS_INPUT}?format=3" - name: how_to.md type: readonly

See the full folder.yaml reference below for all supported fields.

Step 2 — Create a GitHub personal access token

Go to GitHub → Settings → Developer settings → Personal access tokens and create a fine-grained token (or classic token) with at least read access to repository contents for the repo you want to publish. The token is only used to confirm you own the repo; it is discarded after the request.

Step 3 — Publish

Post to the registry API:

curl -s -X POST https://registry.livefoldersfs.org/api/publish \ -H "Content-Type: application/json" \ -d '{"token": "ghp_YOUR_TOKEN", "repo": "your-github-username/your-repo"}'

On success:

{"ok":true,"url":"https://registry.livefoldersfs.org/your-github-username/your-repo"}
⚠ Rate limit: 10 publishes per hour per IP. Re-publishing the same repo updates the existing listing (description, timestamps). Download counts are preserved.

What gets listed

FieldSource
NameGitHub repo slug (owner/name)
DescriptionGitHub repository description
Repository URLGitHub repo HTML URL
Download countIncremented on each livefolders install
VersionsGit tags on the repository
Published / UpdatedTimestamps set by the registry

Set a clear GitHub repo description before publishing — it becomes your tool’s tagline in the index.


folder.yaml Reference

A folder.yaml is 6–50 lines of YAML. No server process, no imports, no build step. The LiveFolders runtime reads it at mount time and hot-reloads it within ~1 second whenever you save a change.

Top-level fields

FieldRequiredDescription
nameYesTool name — becomes the directory under .livefolders/tools/
descriptionYesOne-line summary shown in index.md and the registry
filesYesList of virtual file definitions (see below)
secretsNoList of required env var names; users prompted at install
state_fileNoPath to a persistent state file; injected as LIVEFOLDERS_STATE_FILE

File types

TypeTriggerUse when…
read_invokeLLM reads the fileNo input needed — e.g. fetch a list, get current status
write_invokeLLM writes the fileInput required — e.g. query, transform, command
readonlyStatic content; no handler runs — good for how_to.md

Per-file fields

FieldApplies toDescription
nameAllFilename in the virtual directory
typeAllread_invoke, write_invoke, or readonly
descriptionAllShown in how_to.md and schema.json
handlerInvoke typesShell command or script path to execute
input.typewrite_invokestring or json
input.min_lengthwrite_invokeMinimum input byte length
input.max_lengthwrite_invokeMaximum input byte length
input.patternwrite_invokeRegex the input must match
input.schemawrite_invokeJSON Schema block for structured input
timeoutInvoke typesSeconds before the handler is killed (default: 30)
networkInvoke typestrue to allow outbound network (sandbox default: blocked)
pipeInvoke typesList of endpoint names to chain — stdout of one feeds stdin of next

Full example

name: devtools description: A set of developer utilities — base64, JSON format, and UUID generation. secrets: - OPENAI_API_KEY # prompted at install, stored in secrets.env files: - name: how_to.md type: readonly - name: b64encode type: write_invoke description: Base64-encode any string. input: type: string min_length: 1 max_length: 4096 handler: echo -n "${LIVEFOLDERS_INPUT}" | base64 - name: jsonformat type: write_invoke description: Pretty-print JSON. input: type: json handler: echo "${LIVEFOLDERS_INPUT}" | jq . - name: uuid type: read_invoke description: Generate a random UUID v4. handler: python3 -c "import uuid; print(uuid.uuid4())" - name: summarise type: write_invoke description: Summarise any text with GPT-4o-mini. network: true input: type: string min_length: 10 handler: >- curl -s https://api.openai.com/v1/chat/completions \ -H "Authorization: Bearer ${OPENAI_API_KEY}" \ -H "Content-Type: application/json" \ -d "{\"model\":\"gpt-4o-mini\",\"messages\":[{\"role\":\"user\",\"content\":\"Summarise: ${LIVEFOLDERS_INPUT}\"}]}" \ | jq -r '.choices[0].message.content'

Tips for a Good Listing

✓ Write a clear repo description

The GitHub repository description becomes your tool’s one-liner in search results. Keep it under 80 characters and lead with what the tool does, not what it is.

✓ Add a how_to.md file

A readonly file named how_to.md is the first thing an LLM reads. Describe each endpoint, expected inputs, and example outputs. The runtime auto-generates a basic version if you omit it, but a hand-crafted one is better.

✓ Validate all inputs

Use min_length, max_length, pattern, and schema to reject bad input before the handler runs. The runtime returns a structured [ERROR:INVALID_INPUT] message — LLMs handle these cleanly.

✓ Tag your releases

Git tags become installable versions: livefolders install owner/name@v1.0.0. Push a tag before publishing so users can pin to a stable release.

✓ Declare secrets up front

If your tool needs an API key, list it under secrets:. Users are prompted at install time and the key is stored in a local secrets.env. Never hardcode credentials in the handler.

✓ Set network: true only if needed

The sandbox blocks outbound network by default — a good default for tools that don’t need it. Only set network: true on endpoints that genuinely call external services, so users can see exactly what reaches the internet.


Registry API

The registry exposes a small REST API consumed by the CLI and available for integrations. All endpoints return JSON. Rate limits apply per IP.

EndpointMethodDescriptionRate limit
/api/publish POST Publish or update a tool listing 10 / hour
/api/search?q= GET Full-text search across name, description, and tags 60 / minute
/api/resolve/:owner/:name GET Resolve a slug to repo URL and metadata (used by the CLI) 60 / minute
/api/tools/:owner/:name GET Full tool record (all stored fields) 60 / minute
/api/tools/:owner/:name/downloads POST Increment download counter (called by CLI on install) 30 / minute

Publish request body:

POST /api/publish Content-Type: application/json { "token": "ghp_YOUR_GITHUB_TOKEN", "repo": "owner/repo-name" }

Search example:

curl "https://registry.livefoldersfs.org/api/search?q=weather"