A Unix-like shell for microcontrollers, with users, networking and SSH,
that also runs on a PC. TinyDesk Shell (tdsh) is the
shell inside TinyDesk, the
terminal desktop for microcontrollers, and works on its own too.
Actual serial-console capture of the standalone firmware.
- Parser with variables, quoting, redirection, pipelines, command
substitution, arithmetic and conditions; scripts (
.tdsh, uScript 1.1.1). - Line editor: Tab completion, history, arrows, Home/End, Ctrl+A/E/U/K/L/C.
- Files on LittleFS (
/fs),nano,write; per-user homes with a sandbox. - Users in NVS with salted, hashed passwords;
login,passwd, boot user, physical-console recovery. - Wi-Fi (per-user saved networks), W6100 Ethernet, LAN/Wi-Fi policy,
ping, SNTP time, time zones. - SSH/SFTP server (wolfSSH, per-device host key), FTP server, SMB2/3 mounts,
the SD card at
/sd(sd mount, FAT over SPI, optional mount at boot). - Board configuration: pins for RS-485, Ethernet and SD come from a
key = valuefile (boardcommand,tdsh_board.h), not from the code. - Hardware loopback tests (
hwtest), heap and task information. - A portable core with POSIX (Linux) and Windows host ports and regression
tests;
tdsh.exeruns the shell natively on Windows.
The C API uses the prefix tdsh_ (tdsh.h, tdsh_espidf.h); scripts end in .tdsh.
This is a developer preview.
- From the browser: the TinyDesk web installer flashes TinyDesk Shell onto an ESP32-C6 or ESP32 (Chrome or Edge), and the web terminal opens the board afterwards.
- Files: every release has a factory image
per board (flash at offset 0 with esptool), the Linux program, the Windows
program (
tdsh.exe, run it in Windows Terminal) andSHA256SUMS.txt. On a PC the shell keeps its files apart from yours: in~/.local/share/tdsh/rootfson Linux,%LOCALAPPDATA%\tdsh\rootfson Windows.
A release is made by pushing a tag v<VERSION>: .github/workflows/release.yml
runs the host tests, builds both firmware projects and the Linux and Windows
programs, and
creates a draft pre-release with the files (tools/make_release.py packages
them; it runs locally too).
git clone https://github.com/schikani/tinydesk-shell.git
cd tinydesk-shell| Board | Project | Console |
|---|---|---|
| ESP32-C6, 8 MB flash | the repository root | built-in USB Serial/JTAG |
| classic ESP32, 4 MB flash or more, PSRAM optional | projects/esp32 |
UART0 (the USB-UART chip), 115200 baud |
idf.py build # in the root, or in projects/esp32
idf.py -p PORT flash monitorOn Windows, build_windows.cmd runs an environment check first
(build_windows.cmd -p COM7 flash monitor). Keep the checkout in a short
folder such as C:\src\tinydesk-shell: ESP-IDF's nested build folders
otherwise run past Windows' 260-character path limit (ninja: error: mkdir(...): No such file or directory). The ESP-IDF component manager
downloads the dependencies declared in
ports/esp_idf/components/tdsh/idf_component.yml.
You start as root; the factory root password (for SSH, FTP and login) is
TinyDesk: change it locally with passwd before remote access. SSH and FTP
refuse remote authentication while the factory root password remains. Then, for example:
wifiadd MyNetwork mypassword # save a network (per user)
wificonnect
ssh start
hello # the example application command (main/main.c)
RS-485 lines, a W6100 Ethernet chip and an SD card are configured with
key = value settings, not in the code. Copy the project's
board.example.conf to board.conf (ignored by git) and edit it before
building, or set them on the running board as root:
board set eth.chip w6100
board set eth.miso 2
...
reboot
board show lists the settings. See the annotated
board.example.conf for keys and defaults.
The partition tables: ESP32-C6: application at
0x10000(3 MB), LittleFSstorageat0x310000; classic ESP32: application at0x10000(2.5 MB), LittleFS at0x290000(1.4 MB). The file system is formatted if it cannot be mounted. Do not useerase-flashas a routine step.
Add ports/esp_idf/components to EXTRA_COMPONENT_DIRS, then:
#include "tdsh_espidf.h"
extern const char board_conf[] asm("_binary_board_conf_start"); /* optional, EMBED_TXTFILES */
tdsh_espidf_config_t cfg = TDSH_ESP_IDF_CONFIG_DEFAULT();
cfg.hostname = "mydevice";
cfg.board_config = board_conf; /* built-in pins; /fs/etc/board.conf overrides them */
ESP_ERROR_CHECK(tdsh_espidf_init(&cfg));
ESP_ERROR_CHECK(tdsh_espidf_start()); /* the ESP-IDF console: USB Serial/JTAG or UART */Register your own commands with tdsh_register_commands(). See
docs/EMBEDDING.md and examples/esp_idf/embed_in_app.
TinyDesk embeds the shell this way and runs its console in a desktop window.
An integration that shares this console with a remote transport must call
tdsh_console_mark_remote() before accepting remote input and refuse the
connection if it returns false. This prevents remote use of physical password
recovery; successful takeover revokes physical trust until reboot.
cmake -S . -B build-host -G Ninja -DTDSH_BUILD_HOST=ON
cmake --build build-host
ctest --test-dir build-host --output-on-failureOn Windows add -DCMAKE_C_COMPILER=gcc (MinGW-w64); the program is
build-host/tdsh_host.exe. docs/POSIX_HOST.md and docs/WINDOWS_HOST.md
explain the host ports.
Put commands in a .tdsh file and run it with tdsh run. The script
language (uScript 1.1.1) has variables, single and double quotes, $(…),
integer arithmetic $((…)), if/elseif/else/endif,
while/endwhile, for … in/endfor (with * and ? globs),
break/continue, functions with arguments and return status
(function/end, $1, $#, $?), test and [ … ], pipes,
>, >> and < redirection, and &&, || and ;.
#!/bin/tdsh
function check
if test -f "$1"
echo "$1: $(cat $1)"
return 0
endif
echo "$1 is missing"
return 1
end
for F in ~/logs/*.txt
check $F || echo "problem with $F"
endfor
N=$((3 * 4 + 1))
if $N >= 10
echo "N is $N"
endiftdsh run ~/check.tdsh # run and wait; $? is its status
tdsh run ~/tools # a folder runs its main.tdsh
tdsh run ~/logger.tdsh --bg # in the background
A script runs in a copy of the session, so its variables and cd do not
leak back. On the ESP32 each user's ~/.tdshrc.tdsh runs when their local
console starts (for example wificonnect). The full reference, with every
condition form, the limits and a tested example: docs/SCRIPTING.md.
tests/scripts/ holds self-checking test scripts.
| File | Content |
|---|---|
docs/SCRIPTING.md |
the .tdsh script language: syntax, conditions, loops, functions, pipes, limits |
docs/FUNCTIONS.md |
API and command inventory |
docs/ARCHITECTURE.md, docs/PORTING.md |
structure, porting to another platform |
docs/DEPENDENCIES.md |
component versions |
CHANGELOG.md |
changes per version |
TinyDesk Shell is released under the MIT licence.
Third-party components keep their own licences: see THIRD_PARTY_LICENSES.md and NOTICE. Firmware built with the ESP-IDF component includes wolfSSH and wolfSSL (GPL-3.0) and is therefore distributed under the GPL-3.0 as a whole.
Issues and pull requests are welcome. Run the host tests and build the standalone firmware before sending a change, and keep board-specific pins out of the code (use board configuration keys).
