Norns execution through bash?

I am developing via Visual Studio and then rsyncing onto the device … I would love to add to my build script a command that will run the program on the file … is there an SSH command to start a program in norns (right now I am running the script within maiden by hitting cmd+p)

lua REPL is connected to a websocket endpoint, and this is how maiden talks to it.

so if i understand correctly, you want to be able to issue a command in bash on your dev machine that runs a lua script on the norns.

and the best way i can think of doing that is to send something to the norns lua REPL websocket. you can’t do this in bash directly but websockets are widely supported in python, node &c.

this has come up a lot so we should probably make a demo.


exactly … I am having it rsync through ssh to my norns box … I suppose I could setup a node.js socket server and reverse engineer it all … but having an .sh command I can simply run on the server akin to loading the lua script would be the best.

./ --location=/here/we/go.lua

or something

I got it working with node.js … Thanks so much for idea!


install ws

npm install ws --save-dev

node script:

const WebSocket = require('ws');

const ws = new WebSocket('ws://norns.local:5555/', ['']);

ws.on('open', function open() {

ws.on('message', (d) => {
    if (d.trim() === '<ok>') {
        console.log('-- Updated Norns --');


excellent, you just beat me to it.

FWIW, i also tried python3 and dart… in both cases i couldn’t get them to properly handle the nanomsg bus protocol headers.

One nice (and adorably named) tool for this is websocat.


Thank goodness I am a JS engineer and I notice they had sourcemaps … So I was able to fudge through the protocol … this seciton of code may help you?

  if (action.component === 'sc') {
    // lame, sclang expects commands to be terminated with special command bytes
  } else {

for posterity … here is my Visual Studio Code Build Task (replace paths with your own project locations) … but now I got it updating files and then restarting the task

    // See
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
            "label": "sync",
            "type": "shell",
            "command": "rsync -a ${workspaceFolder}/. we@norns.local:/home/we/dust/code/betterTouche && cd ${workspaceFolder}/socketserver && npm start",
            "group": {
                "kind": "build",
                "isDefault": true


i understand the REPL quirks, this is something about the header itself i think (?). nodejs websockets explicitly support nanomsg BUS subprotocol, but these other libraries don’t appear to.

i’m not sure i care enough about this to investigate further myself, but would be curious if anyone has an easy answer. here’s what i tried:


import asyncio
import websockets
import sys

msg = "print('hello')\n"
ip = "norns.local"
port = "5555"

argc = len(sys.argv)
if argc > 1: msg = sys.argv[1]
if argc > 2: ip = sys.argv[2]
if argc > 3: port = sys.argv[3]

async def tx():
    uri = "ws://{}:{}/".format(ip, port)
    print ("sending message '{}' to server {}".format(msg, uri))
    async with websockets.connect(uri) as websocket:
        await websocket.send(msg)        
        response = await websocket.recv()



import 'dart:io';

void main(List<String> args) async {
  var msg = 'print("hello")\n';
  var ip = '';
  var port = '5555';

  if (args.length > 0) { msg = args[0]; }
  if (args.length > 1) { ip = args[1]; }
  if (args.length > 2) { port = args[2]; }

  var uri = "ws://$ip:$port/";

  print("connecting to $uri ...");
  var webSocket = await WebSocket.connect(uri);
  if (webSocket != null && webSocket.readyState == WebSocket.OPEN) {
  } else {
    print('WebSocket not connected, message $msg not sent');

both programs hang on “connecting…”. if i halt execution i see the python script stuck in some HTTP header parsing. thats as far as i’ve gone. my third try was nodejs, which of course works fine and is used in maiden. (it just seems like an onerous dependency for a CLI tool.)

also: we don’t need to be using nanomsg at all. it was an expedient choice in the early days of the project, before websockets were even decided on as the REPL transport layer. but if there’s a better option i’ve no problem swapping it out.

1 Like

nice work (well … almost) … I was gonna go the python route … but node.js seemed easier to me :slight_smile: good luck on figuring it out!

ok, well python was easy:

 websockets.connect(uri, subprotocols=[''])

i think dart:io websockets don’t yet support subprotocols…?