sillydev
The Python client for the Silly Development panel API: start, stop and
restart your bots, send console commands, manage files and backups, and deploy from Git, all from
your own code. It also comes with a sillydev command line tool and an MCP server for AI assistants.
Full API docs: https://sillydev.co.uk/docs/panel
Install
pip install sillydev
Python 3.9 or later. The only dependency is httpx.
Quick start
Create an API key in the panel under Account, API keys and put it in the SILLYDEV_API_KEY
environment variable. Keys start with sdevc_ (older ptlc_ keys keep working).
from sillydev import SillyDev
client = SillyDev() # or SillyDev(api_key="sdevc_...")
for server in client.panel.servers.list():
print(server["identifier"], server["name"])
client.panel.servers.power("1a7ce997", "restart")
client.panel.servers.command("1a7ce997", "say Back in a minute")
Each server has an 8-character identifier, shown in the panel and in the identifier field of
every server. Every method takes it (or the full UUID) as its first argument.
Examples
from sillydev import SillyDev
client = SillyDev()
panel = client.panel
server = "1a7ce997"
# Live state and resource use
stats = panel.servers.resources(server)
print(stats["current_state"], stats["resources"]["memory_bytes"])
# Restart and wait until it's running again (raises WaitTimeoutError after 120 seconds)
panel.servers.restart(server)
panel.servers.wait_for_state(server, "running", timeout=120)
# Files
for f in panel.files.list(server, directory="/"):
print(f["name"], f["size"])
config = panel.files.read(server, "/config.json")
panel.files.write(server, "/config.json", config.replace("debug", "info"))
# Backups
backup = panel.backups.create(server, name="before-update")
print(backup["uuid"])
# Deploy the linked Git repository
deployment = panel.git.deploy(server)
print(deployment["status"]) # "queued"
# Startup variables
panel.startup.set_variable(server, "MAIN_FILE", "bot.py")
Responses
Methods return plain dicts and lists. The API's {"object": ..., "attributes": {...}} envelopes
are removed, so panel.servers.get(server)["name"] just works.
Pagination
panel.servers.list(), panel.backups.list(), panel.servers.activity() and
panel.account.activity() return iterators that fetch the next page as you go. For one page at a
time, with the list's meta, use the *_page methods:
page = panel.servers.list_page(page=1, per_page=25)
print(page.total, page.has_next, page.meta.get("pending_orders"))
Async
import asyncio
from sillydev import AsyncSillyDev
async def main():
async with AsyncSillyDev() as client:
async for server in client.panel.servers.list():
print(server["name"])
await client.panel.servers.restart("1a7ce997")
asyncio.run(main())
Errors
Every error is a sillydev.SillyDevError. Errors the API answers with have their own class:
| Status | Exception |
|---|---|
| 400 | BadRequestError |
| 401 | AuthenticationError |
| 403 | PermissionDeniedError |
| 404 | NotFoundError |
| 409 | ConflictError |
| 422 | ValidationError (.errors has every problem, .fields groups them by field) |
| 429 | RateLimitError (.retry_after in seconds) |
| 5xx | ServerError |
If the API cannot be reached at all you get APIConnectionError.
from sillydev import ConflictError, NotFoundError
try:
panel.servers.restart(server)
except ConflictError:
print("The server is installing or being transferred; try again later")
except NotFoundError:
print("No such server, or the key cannot reach it")
Retries and limits
Each account may make 768 requests a minute. Requests answered 429 are retried
twice by default, and reads answered 502, 503 or 504 too (a command or power action is not
repeated, since the server may already have run it), waiting as long as the Retry-After header asks. Change it with
SillyDev(max_retries=...); 0 turns retries off.
Ordering a paid server (panel.billing.checkout(...)) always sends an Idempotency-Key, so a
retried request never buys twice. Pass idempotency_key= yourself to make retries safe across runs.
Everything else
client.panel has one attribute for each area of the API:
| Attribute | What it covers |
|---|---|
servers |
list, get, delete, resources, activity, permissions, power, command, share logs, websocket |
settings |
rename, reinstall, Docker image, status badge |
startup |
startup command and variables |
files |
list, read, write, rename, copy, compress, decompress, delete, folders, chmod, pull, signed URLs |
backups |
list, create, get, delete, download, lock, restore |
schedules |
schedules and their tasks |
network |
allocations (ports) |
subusers |
other accounts with access to a server |
git |
link a repository, deploy, deployments, sillydev.conf |
account |
the key's account and its activity |
server_creation |
create free servers |
databases |
free MariaDB and Postgres databases |
billing |
paid servers and subscriptions |
Every method's docstring names the API operation it calls, so you can look it up in the API reference.
Command line
export SILLYDEV_API_KEY="sdevc_..."
sillydev servers list
sillydev status 1a7ce997
sillydev power 1a7ce997 restart
sillydev command 1a7ce997 "say hi"
sillydev deploy 1a7ce997
sillydev files ls 1a7ce997 /src
sillydev files cat 1a7ce997 /config.json
sillydev backups list 1a7ce997
sillydev backups create 1a7ce997 --name before-update
Add --json to any command for JSON output. python -m sillydev works too.
MCP server
The MCP server lets an AI assistant (Claude Desktop, Claude Code, Cursor and others) check on and control your servers. It needs Python 3.10 or later:
pip install 'sillydev[mcp]'
Then add it to your assistant's MCP settings, for example:
{
"mcpServers": {
"sillydev": {
"command": "sillydev-mcp",
"env": { "SILLYDEV_API_KEY": "sdevc_..." }
}
}
}
Its tools are: list servers, server status, power action, send command, list files, read file, Git deploy and list backups. There is nothing for billing or for deleting anything. Give it a key limited to the servers and permissions you want the assistant to have.
Configuration
| Option | Environment variable | Default |
|---|---|---|
api_key |
SILLYDEV_API_KEY |
(required) |
base_url |
SILLYDEV_BASE_URL |
https://sillydev.co.uk/panel/api/client |
timeout |
60 seconds | |
max_retries |
2 |
License
MIT
Metadata
Release files for sillydev 1.0.0
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 | |
|---|---|---|---|---|
| sillydev-1.0.0.tar.gz | 29.9 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sillydev-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 64.8 kB
Release files / sillydev-1.0.0.tar.gz
| Download URL | sillydev-1.0.0.tar.gz |
|---|---|
| Size | 29.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
831d36e652e93c5f6589a83f7c0a977282b433f00d64fbd18d12c5b04c52004d
|
|
BLAKE2b-256 checksum How to use checksums |
8e5e6fd8150e0182be0178c4825ccf31ac55d553abeb85cea0f5c6490b8e012f
|
| 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 Oct 13, 2026.
Transparency logRelease files / sillydev-1.0.0-py3-none-any.whl
| Download URL | sillydev-1.0.0-py3-none-any.whl |
|---|---|
| Size | 34.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f77efa41575a3481458115c445498c189277abdbd389eb318b6783b90da32092
|
|
BLAKE2b-256 checksum How to use checksums |
80ade3d46263e3ad071d32875f310e880d82dd6e0ec0c72faa902380279c8d31
|
| 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 Oct 13, 2026.
Transparency logSecurity for sillydev 1.0.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for sillydev-1.0.0.tar.gz
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 Oct 13, 2026.
Transparency logA 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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.