Interfacing
Section to describe programmatic interfaces to Neurodesk
Connecting/attaching to a running Neurodesktop session via a plain shell
You can start a neurodesktop container using docker or the neurodeskapp. If you want to connect to this running session using a shell you can do this as well:
docker ps
# note the name of the running container, e.g. neurodeskapp-49977
# now connect to this container
docker exec --user=jovyan -ti neurodeskapp-49977 bash
API interface to Jupyter
Install necessary tools, e.g. for macos
brew install coreutils
brew install websocat
Start a jupyter notebook session, e.g. on EXAMPLE_API_URL=“play-europe.neurodesk.org”
Then open a terminal in jupyter and find your jupyterhub token and your username:
echo $JUPYTERHUB_USER
echo $JPY_API_TOKEN
Now you can interface with Jupyter through:
USER=$JUPYTERHUB_USER
USER_TOKEN=$JPY_API_TOKEN
API_URL=$EXAMPLE_API_URL
TERMINAL_RESPONSE=$(curl -k -s -X POST \
-H "Authorization: token $USER_TOKEN" \
"https://$API_URL/user/$USER/api/terminals" || echo '{"error": "curl_failed"}')
echo "Terminal API response: $TERMINAL_RESPONSE"
TERMINAL_NAME=$(echo "$TERMINAL_RESPONSE" | jq -r '.name // empty')
if [ -n "$TERMINAL_NAME" ] && [ "$TERMINAL_NAME" != "null" ] && [ "$TERMINAL_NAME" != "empty" ]; then
echo "✅ Terminal created successfully: $TERMINAL_NAME"
else
echo "❌ Terminal creation failed"
echo "Full response: $TERMINAL_RESPONSE"
# more info about the user
echo "Checking user info..."
USER_INFO=$(curl -k -s -H "Authorization: token $USER_TOKEN" "https://$API_URL/hub/api/users/$USER" || echo '{"error": "failed"}')
echo "User info: $USER_INFO"
exit 1
fi
# Function to test WebSocket connection
test_websocket_connection() {
local token="$1"
echo "Testing WebSocket connection..."
# Test connection
WS_TEST=$(echo '["stdin", "echo test_connection\r\n"]' | \
timeout 15 websocat --text "ws://$API_URL/user/$USER/terminals/websocket/$TERMINAL_NAME" \
-H "Authorization: token $token" 2>&1 | head -10)
if [ $? -eq 0 ] && [ -n "$WS_TEST" ]; then
echo "WebSocket response: $WS_TEST"
# Check if we got expected output format
if echo "$WS_TEST" | grep -q '\["stdout"'; then
echo "✅ WebSocket connection successful with proper output format"
return 0
elif echo "$WS_TEST" | grep -q 'test_connection'; then
echo "✅ WebSocket connection successful"
return 0
else
echo "⚠️ WebSocket connected but unexpected format"
echo "Raw output: $WS_TEST"
return 1
fi
else
echo "❌ WebSocket connection failed"
echo "Error: $WS_TEST"
return 1
fi
}
# Test with user token
if test_websocket_connection "$USER_TOKEN"; then
echo "✅ WebSocket connection working with user token"
else
echo "❌ WebSocket connection failed"
echo ""
echo "🔍 Additional debugging info:"
echo "- Terminal exists: $TERMINAL_NAME"
echo "- User token: ${USER_TOKEN}..."
echo "- API accessible: $(curl -k -s -o /dev/null -w "%{http_code}" "$API_URL")"
echo "- WebSocket URL: ws://$API_URL/user/$USER/terminals/websocket/$TERMINAL_NAME"
fi
# Function to send command and get response
send_command() {
local cmd="$1"
echo "Testing command: $cmd"
local clean_api_url=${API_URL#*//}
local output=""
for attempt in {1..3}; do
echo " Attempt $attempt..."
echo "$ $cmd"
# Send command
echo "[\"stdin\", \"$cmd\\r\\n\"]" | \
websocat --text \
"wss://$clean_api_url/user/$USER/terminals/websocket/$TERMINAL_NAME" \
-H "Authorization: token $USER_TOKEN" >/dev/null 2>&1
# Wait for command to complete
sleep 5
# get the terminal output
local output=$(echo '["stdin", ""]' | \
timeout 10 websocat --text \
"wss://$clean_api_url/user/$USER/terminals/websocket/$TERMINAL_NAME" \
-H "Authorization: token $USER_TOKEN" 2>/dev/null)
if [ -n "$output" ]; then
echo "$output" | \
grep '^\["stdout"' | \
sed 's/^\["stdout", *"//; s/"\]$//' | \
sed 's/\\u001b\[[?]*[0-9;]*[a-zA-Z]//g; s/\\r\\n/\n/g; s/\\r/\n/g' | \
sed -n "/\$ $command/,/\$ /p" | \
sed '1d; $d' | \
grep -v "^$"
return 0
fi
echo "(no output)"
sleep 2
done
echo " ❌ Command failed after 3 attempts"
echo " Output: $output"
return 1
}
send_command "touch test.txt"
send_command "ls"
send_command "ml fsl; fslmaths"
# To start an interactive terminal session
interactive_terminal() {
local clean_api_url=${API_URL#*//}
echo "=== Interactive Terminal Started ==="
echo "Type 'exit' to quit"
echo "=================================="
while true; do
echo -n "$ "
read -r user_cmd
# Exit condition
if [[ "$user_cmd" == "exit" ]]; then
echo "Terminal session ended."
break
fi
# Skip empty commands
if [[ -z "$user_cmd" ]]; then
continue
fi
echo "Executing: $user_cmd"
# Send command
echo "[\"stdin\", \"$user_cmd\\r\\n\"]" | \
websocat --text \
"wss://$clean_api_url/user/$USER/terminals/websocket/$TERMINAL_NAME" \
-H "Authorization: token $USER_TOKEN" >/dev/null 2>&1
# Wait for execution
sleep 5
# Get output
local output=$(echo '["stdin", ""]' | \
timeout 10 websocat --text \
"wss://$clean_api_url/user/$USER/terminals/websocket/$TERMINAL_NAME" \
-H "Authorization: token $USER_TOKEN" 2>/dev/null)
if [ -n "$output" ]; then
echo "$output" | \
grep '^\["stdout"' | \
sed 's/^\["stdout", *"//; s/"\]$//' | \
sed 's/\\u001b\[[?]*[0-9;]*[a-zA-Z]//g; s/\\r\\n/\n/g; s/\\r/\n/g' | \
sed -n "/\$ $command/,/\$ /p" | \
sed '1d; $d' | \
grep -v "^$"
else
echo "(no output)"
fi
echo ""
done
}
interactive_terminal