Quick Start

Open shiro.computer and start typing. The terminal is a full Unix shell with 220+ commands, persistent files, WASM runtimes, and Spirit AI.

# Create files and directories
mkdir -p ~/project/src
echo 'Hello from Shiro' > ~/project/README.md

# List and search
ls -la ~/project
find ~/project -name "*.md"

# Pipes and redirects
echo "hello world" | sed 's/hello/goodbye/' | wc -c

# Files persist across reloads
cat ~/project/README.md

Everything runs in the browser. Files are stored in IndexedDB and survive page reloads. No server needed.

Filesystem

Shiro has an IndexedDB-backed POSIX filesystem. Files persist across sessions. The root is / with standard directories.

Key Paths

PathPurpose
/home/userHome directory (~)
/tmpTemporary files (not cleared automatically)
/usr/local/binGlobal binaries (npm -g installs here)
/usr/local/libGlobal node_modules

File Operations

# Create, copy, move, remove
touch file.txt
cp file.txt backup.txt
mv backup.txt renamed.txt
rm renamed.txt

# Directory operations
mkdir -p deep/nested/path
rmdir empty-dir
rm -r deep

# Permissions (stored but not enforced)
chmod 755 script.sh
ls -l script.sh

# Symbolic links
ln -s /home/user/target /home/user/link
readlink /home/user/link

# Disk usage
du -sh /home/user

Shell

The shell is bash-compatible with pipes, redirects, variables, arrays, arithmetic, functions, process substitution, extended globbing, traps, and programmable tab completion.

Pipes and Redirects

# Pipe output between commands
ls -la | grep ".js" | wc -l

# Redirect to file
echo "hello" > output.txt
echo "more" >> output.txt    # append

# Input redirect
cat < output.txt

# Stderr redirect
command-that-fails 2> errors.txt

Variables

# Set and use variables
NAME="Shiro"
echo "Welcome to $NAME"
echo "Home is ${HOME}"

# Built-in variables
echo $HOME          # /home/user
echo $SHELL         # /bin/sh
echo $?             # last exit code

# Export for child processes
export API_KEY=abc123

Compound Commands

# AND — run next only if previous succeeds
mkdir -p /tmp/test && echo "created"

# OR — run next only if previous fails
cat /nonexistent 2>/dev/null || echo "file not found"

# Semicolons — run sequentially regardless
echo "first" ; echo "second" ; echo "third"

Quoting

# Single quotes — literal, no expansion
echo '$HOME is not expanded'

# Double quotes — variables expanded
echo "Home is $HOME"

# Backslash escapes
echo "line one\nline two"

npm & Node.js

Install real npm packages from the registry. require() resolves from node_modules. Node.js scripts run with CommonJS and ES module support.

# Initialize a project
mkdir -p ~/myapp && cd ~/myapp
npm init -y

# Install packages (real tarballs from registry.npmjs.org)
npm install lodash
npm install -g prettier

# Use in scripts
node -e "console.log(require('lodash').uniq([1,1,2,3]))"

# Run a script file
echo 'const _ = require("lodash"); console.log(_.chunk([1,2,3,4,5,6], 2));' > app.js
node app.js

# npm scripts
npm run start

# Package management
npm list
npm uninstall lodash

# npx — run package binaries (auto-installs if needed)
npx prettier --write app.js
npx typescript --version
npx @scope/pkg arg1 arg2

esbuild Bundler

# Bundle TypeScript/JavaScript
build src/app.ts --bundle --outfile=dist/app.js

Spirit (AI)

Built-in AI assistant powered by Claude. Pipe data through it, generate code, or ask questions. Requires an Anthropic API key.

# Set your API key
export ANTHROPIC_API_KEY=sk-ant-...

# Ask a question
spirit "explain how DNS works"

# Pipe data through AI
cat data.csv | spirit "summarize this data"

# Generate code
spirit "write an Express API with /users endpoint" > server.js

# Use a specific model
spirit --model claude-opus-4-20250514 "review this code" < app.js

# Set a system prompt
spirit --system "You are a bash expert" "how do I find large files?"

# List available models
spirit --list-models

WASM Runtimes

Six language runtimes compiled to WebAssembly, lazy-loaded on first use (~1MB each, cached in IndexedDB).

C Compiler (xcc)

echo '#include <stdio.h>
int main() { printf("Hello from C!\\n"); return 0; }' > hello.c
cc hello.c -o hello
./hello

SQLite (sql.js)

sqlite3 app.db "CREATE TABLE users (name TEXT, age INTEGER);"
sqlite3 app.db "INSERT INTO users VALUES ('Alice', 30), ('Bob', 25);"
sqlite3 app.db "SELECT * FROM users WHERE age > 28;"
sqlite3 app.db ".tables"

Python (Pyodide)

python3 -c "print('Hello from Python!')"
python3 -c "import json; print(json.dumps({'key': 'value'}, indent=2))"

# Run a script
echo 'for i in range(5): print(f"Count: {i}")' > count.py
python3 count.py

Lua (Fengari)

lua -e "print('Hello from Lua!')"
lua -e "for i=1,5 do print(i) end"

jq (JSON processor)

echo '{"name":"Alice","scores":[95,87,92]}' | jq '.scores | add / length'
echo '[1,2,3,4,5]' | jq 'map(. * 2)'

Git

Full client-side git via isomorphic-git. init, add, commit, diff, log, clone, push, and remote operations all work.

# Initialize and make commits
git init
echo "# My Project" > README.md
git add .
git commit -m "Initial commit"

# Make changes and diff
echo "Updated" >> README.md
git diff
git add . && git commit -m "Update readme"

# View history
git log --oneline
git status

# Clone a repo (HTTP only, needs CORS proxy)
git clone https://github.com/user/repo.git

# Push (needs GITHUB_TOKEN)
GITHUB_TOKEN=$GITHUB_TOKEN git push origin main

Claude Code

The real @anthropic-ai/claude-code CLI runs inside Shiro's Node.js runtime. It can read, write, edit, and search files in the virtual filesystem.

Setup

Run setup to sign in with your Anthropic account via OAuth. Your credentials persist in IndexedDB.

# Sign in (opens OAuth flow)
setup

# Print mode — one-shot code generation
claude -p "Write a function that checks if a number is prime"

# Pipe input for analysis
cat app.js | claude -p "Review this code for bugs"

# Interactive mode (opens in a terminal window)
sc

What Works

Limitations

Editors & Viewers

Shiro includes rich code editors and file viewers. The open command uses file associations to pick the right tool automatically.

Code Editors

# CodeMirror editor (lightweight)
code app.js

# Monaco editor (VS Code engine)
monaco app.ts

# Auto-detect: open picks editor by extension
open app.js        # opens in code editor

Markdown Viewer

The mdview command renders markdown as formatted HTML with syntax-highlighted code blocks, tables, and dark-theme styling.

# View a markdown file
mdview README.md

# Pipe markdown content
echo '# Hello World
- item one
- item two

```js
console.log("highlighted!")
```' | mdview

# open auto-detects .md files
open notes.md      # renders with mdview

HTML & Images

# Render HTML in a window
echo '<h1>Hello</h1>' | html
html page.html

# Display an image
img screenshot.png

Web APIs

Browser-native capabilities exposed as Unix commands. Pipe them together with standard shell tools.

# Text-to-speech
echo "Hello world" | speak
speak -r 1.5 "Fast speech"
speak --list                  # list voices

# Speech-to-text
listen                        # single utterance to stdout
listen | sh                   # speak a command to execute it
listen -c >> notes.txt        # dictate continuously

# Desktop notifications
build && notify "Build complete"
notify -t "Alert" "Check this"

# Webcam snapshot
camera -o selfie.png
camera && img camera-*.png

# Computer vision (camera → Claude AI)
camera | cv "describe this"
cv -f photo.png "what's in this image?"

# Process monitor
top                           # interactive TUI (q to quit)
top -b -n 1                   # batch mode, one snapshot

# Manual pages
man grep                      # full man page in less pager
man -k search                 # search all descriptions

Virtual Servers

Serve web apps from the virtual filesystem using a Service Worker. Interact with them from the shell using page commands.

# Start a server
serve /tmp/myapp 3000

# Interact with the page
page :3000 text "body"           # read text
page :3000 click "#button"       # click an element
page :3000 input "#name" "Alice" # type into input
page :3000 eval "document.title" # run JavaScript

# Split view — dock app beside the terminal
serve /tmp/myapp 3000 --split right
serve open 3000 --split bottom
serve unsplit

# Full-screen app mode
become 3000 myapp    # URL becomes /myapp
unbecome             # return to terminal

Remote Control

An outer Claude Code instance can control Shiro remotely via MCP tools over WebRTC. Peer-to-peer with no data going through the server after signaling.

In Shiro (browser)

remote start     # Generate connection code
remote status    # Check connection
remote stop      # End session

In Claude Code (desktop)

Add to ~/.claude.json:

{
  "mcpServers": {
    "shiro": { "command": "shiro-mcp" }
  }
}

Then use tools: shiro:connect, shiro:exec, shiro:read, shiro:write, shiro:list, shiro:eval.

Node.js Compatibility

Shiro shims ~50 Node.js modules to run in the browser. Most are functional for common use cases. Some are stubs that satisfy import checks without full behavior.

ModuleStatusNotes
fsWorksreadFile, writeFile, stat, mkdir, readdir, unlink, rename, existsSync, promises
pathWorksjoin, resolve, basename, dirname, extname, relative, parse, format, sep
bufferWorksBuffer.from, alloc, toString, slice, concat, compare
eventsWorksEventEmitter: on, once, emit, removeListener
processWorksenv, cwd, exit, nextTick, argv, platform, version, stdout, stderr
child_processWorksexec, execSync route through the virtual shell
cryptoWorkscreateHash (sha256, sha1, md5), randomBytes, randomUUID
osWorksplatform, arch, homedir, tmpdir, cpus, EOL
urlWorksURL class, parse, format
utilWorkspromisify, format, inspect, types, parseArgs
streamPartialReadable, Writable, Transform constructors exist; no full piping
httpPartialcreateServer for virtual servers; no outgoing HTTP
httpsPartialSame as http; uses fetch() internally
netStubSocket constructor exists; no TCP
tlsStubSatisfies imports; no real TLS
dnsStubresolve/lookup return mock results
zlibPartialgzip/gunzip via DecompressionStream
readlinePartialcreateInterface works for stdin reading
string_decoderWorksStringDecoder UTF-8
querystringWorksparse, stringify, encode, decode
assertWorksok, equal, deepEqual, throws, strict
modulePartialcreateRequire, _resolveFilename
worker_threadsStubisMainThread = true; no real threads
clusterStubisMaster/isPrimary = true
vmStubrunInNewContext wraps eval
async_hooksStubcreateHook returns no-op
perf_hooksPartialperformance.now() works

Works = most APIs functional   Partial = core APIs work, edge cases may fail   Stub = satisfies imports, limited functionality

Command List

220+ commands, 2250+ tests. Core coreutils are loaded at boot. Large commands (build, python, sqlite3, etc.) are lazy-loaded on first use.

Core

ls cat echo mkdir rm cp mv touch pwd cd head tail wc sort uniq tee tr cut paste yes true false rev tac shuf split csplit

Search & Text

grep sed awk find rg diff xargs glob basename dirname realpath cmp dos2unix unix2dos

Archives & Compression

tar gzip gunzip zip unzip

Math & Data

dc factor numfmt cksum base32 base64 xxd dd

Dev Tools

node npm npx git build vi nano ed cc gcc python3 pip sqlite3 lua jq

Network & Servers

fetch curl wget serve page become unbecome remote mcp group

System

env export which type uname hostname whoami date uptime free ps kill sleep clear history help top w who users lsof nice man

Web APIs

speak listen notify camera cv

Editors & Viewers

code monaco less mdview html img open

AI

spirit claude sc cv

Shiro-specific

setup seed image spawn hud js-eval