XRSH Manual 
===========

```
 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
 . .  ____  _____________  ________. ._. ._. . . . . . . . .
 . . _\   \/  /\______   \/   _____//   |   \. . . . . . . .
 . . _ \     /  |       _/\_____  \/    ~    \ . . . . . . .
 _ _   /     \  |    |   \/        \    Y    / _ _ _ _ _ _ _
 . .  /___/\  \ |____|_  /_______  /\___|_  /. . . . . . . .
 . . . . . .\_/. . . . \/ . . . .\/ . . _ \/ . . . . . . . .
 ================ https://xrsh.isvery.ninja ================

 Open, local-first, polyglot, unix hackable & selfcontained XR apps.
 Using worlds first WebXR linux distro.

 credits:  NLnet           | @nlnet@nlnet.nl https://nlnet.nl/project
           all FOSS devs   | copy.sh (v86) aframe.io (AFRAME)
           Leon van Kammen | @lvk@mastodon.online
           Fabien Benetou  | @utopiah@mastodon.pirateparty.be 
```

# Getting started 

Please hook up your (bluetooth) keyboard to use xrsh.

> tip use ctrl+a+0/1/2/3/.. to switch (GNU) screen terminals (and ctrl+a+c to create new ones)
  
| usecase               | command                                                |
|-----------------------|--------------------------------------------------------|
| require <URL>         | adds javascript or CSS url to DOM                      |
| js run                | js 'alert("hello")'                                    |
| js console.log:       | console document.baseURI                               |
| js inspect:           | js "return document.baseURI"                           |

# Polyglot environment

Currently the following languages are supported:

* shellscript (busybox sh)
* awk (busybox awk v1.33.0)
* python (micropython)
* javascript (via your browser)
* lua (5.3.6)

> TIP: type `ls -la ~/hook.d/alert/*` for examples

# Editors 

* vi (busybox vi)
* nano (busybox nano)
* mg (microemacs)

# Multiple terminals [GNU screen]

## From the cmdline 

```
xrsh # screen –DR        # list of detached screen
xrsh # screen –r PID     # attach detached screen session
xrsh # screen –dmS Myses # start a detached screen session
xrsh # screen –r MySes   #attach screen session with name MySession
```

## Basics

```
ctrl a c -> create new window
ctrl a A -> set window name
ctrl a w -> show all window
ctrl a 1|2|3|… -> switch to window n
ctrl a " -> choose window
ctrl a ctrl a -> switch between window
ctrl a d -> detach window
ctrl a ? -> help
ctrl a [ -> start copy, move cursor to the copy location, press ENTER, select the chars, press ENTER to copy the selected characters to the buffer
ctrl a ] -> paste from buffer
```

## Advanced

```
ctrl a S -> cre­ate split screen
ctrl a TAB -> switch between split screens
ctrl a Q -> Kill all regions but the current one.
ctrl a X -> remove active window from split screen
ctrl a O -> logout active window (disable output)
ctrl a I -> login active window (enable output)
```

# Importing files 

Files can be imported (always to /mnt/clipboard) in various ways:

* copy-pasted text (from clipboard via ctrl/cmd+v ) 
* drag-dropped file ends up in /mnt/clipboard [based on ~/hook.d/mimetype/* things happen or not]
* type 'upload' to trigger a file-upload dialog [ends up in /mnt/clip

XRSH ships with hooks for importing .glb 3D files, text-files & zip-packages, all described below.

# XRSH Packages

A XRSH package is just a zip with an entrypoint, which gets extracted to /root/{zipname} that's it!

It can be loaded in various ways into [your own instance of] https://xrsh.isvery.ninja:

* copy the zip in a filemanager to your clipboard, and paste it into your XRSH-tab
* drag-drop the zip from a filemanager to your XRSH-tab
* download the zip, and type 'upload' in XRSH to import it

The package follows the popular `autoenv`-paradigm (a file called `.env` is automatically executed).
Currently, '.env' links to 'bin/app.sh', but there are also other scriptinglanguages it could link to as well (see bin-folder).

> see example package at https://xrsh.isvery.ninja/package.zip, and an filesystem overlay-zip
> at https://xrsh.isvery.ninja/package.overlayfs.zip

# Autoenv (.env)

When a directory contains an .env-file, it is automatically sourced.

* run echo 0 > ~/.config/autoenv/package to disable auto-execution of zip-packages
* run echo 1 > ~/.config/autoenv/prompt_cd to trigger a confirmation when cd-ing into a directory.

> TIP: check out `~/bin/annotate` to annotate directories using the power of autoenv 

# Hooks 

Hooks are filebased events.
Why filebased? Well first, because unixy is sexy.
Second: it allows reacting to events in a hackable way via polyglot scripts. 

> TLDR: events are automatically triggering scripts found in `/root/hook.d/{eventname}/*`

**OS related hooks**

| hook location           | when is this hook called?                             |
|-------------------------|-------------------------------------------------------|
| hook.d/wakeup/*         | restoring xrsh session from cache                     |
| hook.d/save/*           | saving xrsh session to cache                          |
| hook.d/alert/*          | when 'alert'-function is used in shell                |
| hook.d/prompt/*         | when 'prompt'-function is used in shell               |
| hook.d/confirm/*        | when 'confirm'-function is used in shell              |

**Clipboard related hooks**

| hook.d/clipboard/*      | user copy-pastes clipboard or (drops) file into scene |
| hook.d/mimetype/*       | clipboard activity (hook.d/clipboard/forwarder)       |
| hook.d/filetype/*       | clipboard activity (hook.d/clipboard/forwarder)       |

**XR related hooks**

| hook location           | when is this hook called?                             |
|-------------------------|-------------------------------------------------------|
| hook.d/exit-vr/*        | user exits immersive WebXR [VR] mode                  |
| hook.d/enter-vr/*       | user enters immersive WebXR [VR] mode                 |
| hook.d/exit-ar/*        | user exits immersive WebXR [AR] mode                  |
| hook.d/enter-ar/*       | user enters immersive WebXR [AR] mode                 |

> How to trigger them?

Well the isoterminal-AFRAME component triggers them automatically for you. 
But you can do it manually too:

1. from shellscript: `hook myevent` (will trigger **executable** files in /root/hook.d/myevent)
2. from javascript: `isoterminal.exec("hook myevent")` (idem)
3. via jsh: `jsh alert hello` (will trigger **executable** files in /root/hook.d/alert)

These are various ways to enable hybrid eventing between browser and terminal (languages).

## Wget: downloading remote files

Internetrequests are limited to port 80 and 443 (as they are routed via javascript's fetch()):

```
$ wget xrsh.isvery.ninja         # fetches https://xrsh.isvery.ninja (*)
$ wget http://xrsh.isvery.ninja  # fetches http://xrsh.isvery.ninja
$ wget https://xrsh.isvery.ninja # does not work (*) 
```

> \* = important for selfhosters: the browser cannot switch ports, therefore hostnames are considered HTTPS when the XRSH webapp is 
hosted via **valid** HTTPS certificates. Serving the XRSH webapp via http will render https impossible. XRSH.com (the standalone binary) also launches 
https://127.0.0.1 (instead of https://localhost) because the latter cripples the network-features.

## webrequests to the filesystem

Javascript webrequests can read from the filesystem via the 'file://host/path' protocol:

```
fetch("file://xrsh/mnt/profile.browser")
```


 NOTE: it's `file://xrsh` not `file:///` (basically it includes host `xrsh`) to prevent the browser security-model from blocking the request (and select the xrsh filesystem, not the native filesystem).

current [security] limitations:

* only /mnt directory is exposed
* file needs to be world-readable (`chmod +r /mnt/<file>`)

# Boot sequence 

The following files are loaded during boot (via `/etc/profile`)

| file                  | info                                              |
|-----------------------|---------------------------------------------------|
| /etc/profile.xrsh     | sets up xrsh environment                          |
| /etc/profile.sh       | global shellscript functions                      |
| /etc/profile.js       | global javascript functions                       |
| /mnt/profile.browser  | environment vars set by browser (`echo $HOSTNAME`)|
| /root/.profile        | user shellscript functions/settings               |
| /root/.profile.js     | user javascript functions                         |
| /root/.screenrc       | GNU screen initialisations                        |
| https://.../#ls       | URI fragment is executed as command in own screen |

> TIP: to keep things portable with future versions of XRSH: modify files in `/root/*`

# Calling terminal from javascript

```javascript
const term = document.querySelector('[isoterminal]').components.isoterminal.term
term.exec("ls -la")

// interact directly with files 
await term.worker.create_file("hello.txt", term.convert.toUint8Array("hello") )
await term.worker.update_file("hello.txt", term.convert.toUint8Array("hi") )
await term.worker.append_file("hello.txt", term.convert.toUint8Array("world") )
const buf = await term.worker.read_file("hello.txt")
const str = new TextDecoder().decode(buf);
```

# Calling javascript from terminal 

Various options:

1. Just add the `#!/bin/js` shebang to the top of a javascript file (+ chmod +x)
2. Run `js "alert('hello')"` in the shell
3. Run `jsh alert hello` in the shell
4. Run `jsh` to start an interactive shell