An ICP Python Canister Development Kit and Application Framework for the Internet Computer
Project description
Basilisk
An ICP Python Canister Development Kit and Application Framework. Write decentralized applications in Python efficiently on the Internet Computer.
Live demo: https://ic-basilisk.tech/.
Features
- Based on CPython 3.13, compiled to WASM — deploy in seconds with a pre-built template, no Rust toolchain needed
- Near-complete standard library —
os,json,re,math,datetime,hashlib,collections, networking stubs, and more. A few modules requiring native OS threads or sockets (e.g.threading,subprocess,socket) are not available
Built-in Application Framework:
- Persistent ORM — ic-python-db with typed fields, relationships, validation, and audit logging — stored in stable memory, survives canister upgrades
- Filesystem — standard
open()andoscalls, with optional persistence across upgrades - Interactive shell — Python REPL running inside the canister, accessible via an SSH/SFTP proxy
- Task management — multi-step task execution that overcomes per-call cycle limits, with one-shot and recurring scheduling
- File transfer — upload/download files to and from the canister; fetch from the internet with
wget-like command. - Encryption — per-principal key envelopes, encrypted fields, and crypto groups
- Wallet — ckBTC/ckETH and ICRC-1 token balances, transfers, and transaction history
- IC system APIs —
ic.caller(),ic.time(),ic.canister_balance(), inter-canister calls, timers, and Candid types (Principal,Record,Variant, etc.)
┌─────────────────────────────────────────────────────────┐
│ Basilisk Application Framework │
├─────────────┬────────────┬────────────┬─────────────────┤
│ Task Mgr │ Filesystem │ Database │ Shell │
│ Tasks │ POSIX-like │ Entity ORM │ Python REPL │
│ Scheduling │ os/open() │ Stable Mem │ SSH / SFTP │
│ Codex/Call │ Persistence│ │ │
├─────────────┼────────────┼────────────┼─────────────────┤
│ Wallet │ Encryption │ File Xfer │ IC System APIs │
│ ICRC-1 │ Key Envlps │ Upload/DL │ Timers, Calls │
│ ckBTC/ckETH │ Crypto Grps│ wget │ Candid Types │
├─────────────┴────────────┴────────────┴─────────────────┤
│ Basilisk CDK (Python → WASM) │
├─────────────────────────────────────────────────────────┤
│ Internet Computer (ICP) │
└─────────────────────────────────────────────────────────┘
## Quick Start
### Prerequisites
- [icp](https://internetcomputer.org/docs/current/developer-docs/setup/install/) (IC SDK)
- Python 3.10+
### Install
```bash
pip install ic-basilisk
Create, deploy, and connect
# 1. Scaffold a new project
basilisk new my_project
cd my_project
# 2. Start the local replica and deploy
dfx start --background
dfx deploy
# 3. Call your canister
dfx canister call my_project greet '("World")'
# ("Hello, World! The counter is at 0.")
# 4. Open an interactive Python shell inside the canister
basilisk shell --canister my_project
# 5. Or connect via SSH and SFTP
basilisk sshd --canister my_project
ssh -p 2222 localhost # Python shell over SSH
sftp -P 2222 localhost # browse the canister filesystem
basilisk>>> print("Hello from the IC!")
Hello from the IC!
basilisk>>> import os; os.listdir("/")
['data', 'config.json']
# Create a task with inline code
basilisk>>> %task create my_report --code "print('Generating report...'); result = 42"
# Run it immediately
basilisk>>> %task run 1
# Schedule a recurring task (every 60 seconds)
basilisk>>> %task create heartbeat every 60s --code "print('alive at', ic.time())"
# View task details and list all tasks
basilisk>>> %task info 1
basilisk>>> %task list
Database
Basilisk includes ic-python-db, an Entity ORM with typed fields, relationships, validation, and audit logging — all persisted to stable memory across canister upgrades:
from basilisk import query, update, text
from basilisk.db import Entity, String, Integer, TimestampedMixin
class User(Entity, TimestampedMixin):
__alias__ = "name"
name = String(min_length=2, max_length=50)
age = Integer(min_value=0)
@update
def add_user(name: text, age: text) -> text:
user = User(name=name, age=int(age))
return f"Created user {user.name} with id {user._id}"
@query
def get_user(name: text) -> text:
user = User[name] # Lookup by alias
return f"{user.name}, age {user.age}"
@query
def list_users() -> text:
return str([(u.name, u.age) for u in User.instances()])
dfx canister call my_project add_user '("Alice", "30")'
# ("Created user Alice with id 1")
dfx canister call my_project get_user '("Alice")'
# ("Alice, age 30")
# Data survives upgrades:
dfx deploy my_project --upgrade-unchanged
dfx canister call my_project get_user '("Alice")'
# ("Alice, age 30") ← still there!
See the ic-python-db documentation for relationships (OneToMany, ManyToOne, etc.), access control, entity hooks, and more.
CPython vs RustPython
A benchmark comparison was done between Kybra (RustPython) and Basilisk (CPython) to evaluate their performance characteristics.
| CPython 3.13 | RustPython | |
|---|---|---|
| Build time | ~seconds (template) | ~60-120s (Cargo build) |
| Wasm size | ~5.3 MB | ~26 MB |
| Python compatibility | Full (reference implementation) | Partial (~3.10) |
Benchmark Results
Wasm instruction counts measured on a PocketIC replica via GitHub Actions CI. Lower is better — fewer instructions means lower cycle cost on the IC.
| Benchmark | CPython (instructions) | RustPython (instructions) | RustPython / CPython |
|---|---|---|---|
| noop (call overhead) | 15,914 | 88,918 | 5.6x |
| increment (state mutation) | 16,050 | 92,485 | 5.8x |
| fibonacci(25) (iterative) | 37,269 | 294,649 | 7.9x |
| fibonacci_recursive(20) | 29,617,903 | 337,795,318 | 11.4x |
| string_ops (100 concatenations) | 275,375 | 2,135,202 | 7.8x |
| list_ops (500 append + sort) | 602,711 | 5,819,267 | 9.7x |
| dict_ops (500 inserts + lookups) | 3,407,101 | 23,087,720 | 6.8x |
| method_overhead (total prelude) | 11,122 | 42,216 | 3.8x |
CPython is 6–11x faster than RustPython for compute-heavy workloads due to its optimized C interpreter. The gap is largest for recursive function calls (11.4x) and list operations (9.7x). Even the minimum overhead per call is lower: 11K vs 42K instructions.
Full CI logs: CPython run · RustPython run
Run it yourself: trigger the Benchmark workflow from the Actions tab — select
cpython,rustpython, orbothas the backend, andlocaloricas the network.
The benchmark source is in benchmarks/counter/.
Why "Basilisk"?
A basilisk fountain in Basel, Switzerland — where this project was written.
This project was written in Basel, Switzerland — a city guarded by basilisks since the Middle Ages. In European mythology, the basilisk is the king of serpents — part rooster, part snake — making it a fitting patron for a Python framework.
According to local legend, a basilisk once dwelt beneath Basel's streets, turning to stone anyone who dared look upon it. The citizens, unable to defeat it by force, outwitted the creature with a mirror: confronted with its own reflection, the basilisk was petrified by its own gaze. Impressed by the creature's power, the people of Basel didn't destroy it — they adopted it. To this day, basilisk statues stand watch over the city's fountains, their water said to carry a faint enchantment of protection.
In the shadow of the Tower of the Bank for International Settlements — where the world's central banks convene to shape global finance — a basilisk fountain stands watch. It is here, at the crossroads of ancient myth and modern power, that we chose to unleash the dormant power of Python onto the Internet Computer.
The fountains still flow in Basel. And now, so does Python on the IC. Great power requires great responsibility. Handle with care.
Disclaimer
Basilisk may have unknown security vulnerabilities due to the following:
- Limited or no production deployments on the IC
- No extensive automated property tests
- No independent security reviews/audits
Documentation
For detailed architecture notes, see CPYTHON_MIGRATION_NOTES.md.
Discussion
Feel free to open issues.
License
See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ic_basilisk-0.11.13.tar.gz.
File metadata
- Download URL: ic_basilisk-0.11.13.tar.gz
- Upload date:
- Size: 864.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a808e657b35be09040305613ecd363d161d401de89626bc0847897d4169507d
|
|
| MD5 |
b7213f188173265a44e7642e9297a2ff
|
|
| BLAKE2b-256 |
1590dd042dee799653181c58adb7aab5b2211d44d8dda21b9984ef5ebcb7cdf2
|
File details
Details for the file ic_basilisk-0.11.13-py3-none-any.whl.
File metadata
- Download URL: ic_basilisk-0.11.13-py3-none-any.whl
- Upload date:
- Size: 950.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e9f5014c3be3b9679f23d24e31d1fc37065f4d4886a80ebfde5be23855c8a609
|
|
| MD5 |
824c442c95da7c407f652e0dfd84230e
|
|
| BLAKE2b-256 |
c8f204002681464cfc31aa0a01426770248c12839152d7ab4fd2bc75d20e2fdf
|