10 KiB
T-DeckARD: T-Deck Augmented Runtime Distribution
About
T-DeckARD is a curated, interconnected and integrated collection of Python 3 modules developed for CircuitPython 10.x on LilyGO T-Deck (but also mostly compatible with MicroPython and desktop CPython) aimed at turning the stock (Circuit)Python REPL into an easy to use operating environment.
T-DeckARD modules are divided into two categories: components, which are the building blocks anyone can use to easily create their own applications, and ready-made applets which can already be used as stand-alone applications, as well as included as components of other, more complicated ones.
Prerequisites for T-Deck (Plus)
On T-Deck (Plus), the following components must be installed:
- CircuitPython 10.x (tested on 10.0.3);
- Adafruit Library Bundles from the official CircuitPython page;
- tdeck_repl installed and set to boot on startup.
On other generic platforms, most modules which are not T-Deck-specific are set to work on both CPython and MicroPython.
Installation on T-Deck (Plus)
Current installation process doesn't involve any .mpy module compilation, so, after installing the prerequisites, you just need to copy the deck and app directories into the root of the CIRCUITPY removable volume.
Components (deck.*)
As of now, T-DeckARD implements the following component modules.
deck.input
A library for single-line and multi-line (ed-like) text input.
Exported functions:
input(prompt=None): standard single-line Python inputinput_multi(prompt=None, terminator='.'): multi-line input, end with the terminator string on a separate line
deck.pager
A library for paged text output. In CPython, relies on the terminal dimensions provided by the host OS. In CircuitPython and MicroPython, it requires correct values to be provided inside TERM_COLS and TERM_ROWS environment variables. In case they are not provided, these values default to 53 columns and 19 rows (the actual value for T-Deck running tdeck_repl in CircuitPython).
Exported functions:
term_size(): return the terminal dimensions tuple in the(rows, columns)formatreflow(text): split text into a list of lines not exceeding terminal widthprint_paged(text): reflow and print the text in a paginated manned, prompting for Enter presses to move to the next page
deck.chat
A generic chat UI helper library. Exports a single class called DeckChat with the following parameters:
chat_instance = DeckChat(start_state={}, chat_prefix='> ', command_prefix='/')
where the constructor parameters are:
start_state: the state object to be modified by chat actionschat_prefix: the prefix to be displayed before each user's message inputcommand_prefix: the prefix to be prepended to every registered chat command
Every chat instance exposes the following methods:
command(command_name, handler): register a command under thecommand_nameaccording to the handler specification (see below); e.g. if the prefix is/and the command name islist, the chat will react to the/listcommand and pass everything after it as the argument to the handler functionstart(): start the chat loop (keyboard interrupts, if any are supported, exit the loop)
The handler accepts two parameters: a message and a state object, and returns the response and the new state object. If the returned state object is None, then the chat loop exits. Non-command handler (i.e. what should be done on any user input that doesn't start with a registered command) is registered under the default command.
deck.fs (WIP)
FS helper librаry.
Exports the following functions:
unlock_rootfs(): make the device root filesystem read-write (does nothing on desktop)lock_rootfs(): make the device root filesystem read-only (does nothing on desktop)
deck.net
T-Deck/CircuitPython-specific library for Wi-Fi connection and returning requests and socket library instances.
Exported functions:
wifi_scan(): scan available Wi-Fi networks and return the list of(ssid, rssi)tuples (sorted from the strongest signal to the weakest)wifi_connect(ssid=None, password=None): connect to a Wi-Fi SSID without waiting (default credentials are pulled from the/settings.tomlfile)wifi_connect_wait(ssid=None, password=None, tmout=15, retries=3): connect to a Wi-Fi SSID (with the same parameters aswifi_connect) and wait until the connection is establishedmy_ip(): return the current local IPv4 (as a string)ssl_context(): get the default SSL context for wrapping in a raw socketinit_socket(): return the active reference to thesocketlibraryinit_requests(): return the active reference to therequestslibrary
A normal flow for instantiating a Requests library looks like this:
# init requests library in a platform-agnostic way
requests = None
try:
from deck import net
print('Waiting for online status...')
status, stext, myip = net.wifi_connect_wait()
if status:
print("We're online, initing requests lib...")
requests = net.init_requests()
except:
import requests
deck.llm
A helper library for interaction with remote LLM (large language model) endpoints that expose OpenAI-compatible API. As of now, it only exports a single class, LLMChat, to encapsulate all the interaction.
To initialize, this class requires a provider configuration object from a JSON file that looks like this:
{
"temperature": 0.7,
"system_prompt": "You are a concise, embedded assistant.",
"active_provider": "openrouter",
"providers": {
"openrouter": {
"base_url": "https://openrouter.ai/api/v1",
"api_key": "...",
"model": "xiaomi/mimo-v2-flash:free",
"extra_headers": {}
},
"pollinations": {
"base_url": "https://text.pollinations.ai/openai",
"api_key": "",
"model": "openai-fast",
"extra_headers": {}
}
}
}
Then, we initialize it like this:
llm = LLMChat(config_file=CONFIG_FILE_PATH, message_limit=20)
The instance exposes the following methods (all returning a (status, result) tuple where applicable):
load_config(config_file='llmcfg.json'): load configuration from a config filesave_config(): save current configuration into the config filesetup_provider(): load currently active provider settingsreset_context(): clear the conversation history and re-add the system promptget_completion(prompt): prompt the LLM and return the response messagelist_models(): list available model IDs from the current active provider
Applets (app.*)
As of now, T-DeckARD implements the following applets.
app.ed
A simple line-oriented text editor and page-oriented text viewer for MicroPython/CircuitPython implementing a POSIX ed subset (feature-wise, it still is closer to EDLIN from DOS).
Exports the following functions:
edit(filename): start aned-like text editor (see below)view(filename, lno=False): start amore-like pager for viewing a text file (pass an additional parameter to view it with line numbers)
The editor mode supports the following subset of POSIX ed commands in the standard [range][command][param] syntax:
p: print out the rangen: print out the range with line numbersa: append new text to the end of the rangei: insert new text to the start of the rangec: replace the range with new textd: delete the ranges/old/new: replace text in the range (doesn't support regex syntax from POSIX ed)f: set the current filename to write tow: save changes to the current filenameq: quit (q!force-quits without prompting for saving changes)
app.llmchat
A simple interactive chat with remote LLMs. Configured via llmcfg.json (see the deck.llm module reference) placed into the storage root.
Supported chat commands:
/help: display a brief help/clear: clear the conversation context/system: display or set the system prompt/temp: display or set the model temperature/prov: display or set the current provider selection/model: display or set the current model selection/provlist: list provider IDs in the config/modellist: list model IDs available for current provider/exitor/quit: exit the chat applet
FAQ
Is this an OS shell?
No, but it provides comparable functionality to the on-device Python REPL. You can easily build a shell application from the T-DeckARD components.
Why doesn't it include a shell by default?
It may at some point, but the entire idea is to give you the foundation to easily create your own custom shells for any special purposes. The project carries the spirit of early personal computing days when the programming language REPL (BASIC, Forth, Lisp etc) was your primary operating environment. In this case, the on-device Python REPL is such an environment.
Which platforms is T-DeckARD being tested on?
CircuitPython 10.x on a T-Deck Plus and MicroPython for modern x86_64 Linux. That's it.
So, can I use T-DeckARD outside CircuitPython or even MicroPython?
Yes, but don't expect some modules (like deck.net) to work at all. Wrap your code inside try-blocks to achieve maximum compatibility.
Is there any feature roadmap for core components?
The foundational module set is going to at least include high-level capabilities for:
- exposing low-level socket and HTTP APIs (done),
- high-level HTTP APIs,
- high-level LLM APIs (partially done),
- date and time informaion,
- file system manipulation (partially done),
- text viewing and editing (done),
- device information collection,
- chat UI creation (done).
After all this is implemented, future phases may also include device-specific features like GPS, graphics, sound and touchscreen input.
Is there any feature roadmap for applets?
No. All applets are created ad-hoc when the author needs them.
Credits
Created by Luxferre in 2025-2026, released into public domain with no warranties.
Special thanks to RetiredWizard for providing a wonderful tdeck_repl wrapper.