diff --git a/app/nose/bin/apps.tsx b/app/nose/bin/apps.tsx
index 81a93d6..1dbc9a8 100644
--- a/app/nose/bin/apps.tsx
+++ b/app/nose/bin/apps.tsx
@@ -1,3 +1,5 @@
+// Show the webapps hosted on this NOSEputer.
+
import { $ } from "bun"
import { apps } from "app/src/webapp"
@@ -12,6 +14,6 @@ export default async function () {
port = port === "80" ? "" : `:${port}`
return <>
- {apps().map(app => <>{app}{" "}>)}
+ {apps().map(app => {app})}
>
}
\ No newline at end of file
diff --git a/app/nose/bin/cat.ts b/app/nose/bin/cat.ts
index 760c88e..48bacfc 100644
--- a/app/nose/bin/cat.ts
+++ b/app/nose/bin/cat.ts
@@ -1,3 +1,5 @@
+// Show the contents of a file, if possible.
+
import { escapeHTML } from "bun"
import { readdirSync } from "fs"
import { join, extname } from "path"
diff --git a/app/nose/bin/cd.ts b/app/nose/bin/cd.ts
index 3f2c937..19b14cd 100644
--- a/app/nose/bin/cd.ts
+++ b/app/nose/bin/cd.ts
@@ -1,3 +1,5 @@
+// Change directory.
+
import { dirname, resolve, isAbsolute } from "path"
import { statSync } from "fs"
import { projectDir } from "@/project"
diff --git a/app/nose/bin/counter.tsx b/app/nose/bin/counter.tsx
index 307aef3..5b37583 100644
--- a/app/nose/bin/counter.tsx
+++ b/app/nose/bin/counter.tsx
@@ -1,3 +1,5 @@
+// stream() demo. Counts.
+
import { stream } from "@/stream"
export default async function () {
diff --git a/app/nose/bin/echo.ts b/app/nose/bin/echo.ts
index 0e06a22..07c0d30 100644
--- a/app/nose/bin/echo.ts
+++ b/app/nose/bin/echo.ts
@@ -1,3 +1,5 @@
+// Monkey see, monkey do.
+
export default function (...args: string[]): string {
return args.join(" ")
}
\ No newline at end of file
diff --git a/app/nose/bin/edit.tsx b/app/nose/bin/edit.tsx
index 469921e..0d0633f 100644
--- a/app/nose/bin/edit.tsx
+++ b/app/nose/bin/edit.tsx
@@ -1,3 +1,5 @@
+// Open the Advanced Text Editor and start editing a file.
+
import { readdirSync } from "fs"
import { join, extname } from "path"
diff --git a/app/nose/bin/env.ts b/app/nose/bin/env.ts
index df35c62..700be9a 100644
--- a/app/nose/bin/env.ts
+++ b/app/nose/bin/env.ts
@@ -1,3 +1,7 @@
+// NOSE developer feature.
+//
+// Show some debugging information.
+
import { NOSE_STARTED, NOSE_SYS, NOSE_DIR, GIT_SHA } from "@/config"
export default function () {
diff --git a/app/nose/bin/game.tsx b/app/nose/bin/game.tsx
index d70bd4e..a1a93b8 100644
--- a/app/nose/bin/game.tsx
+++ b/app/nose/bin/game.tsx
@@ -1,4 +1,6 @@
///
+// Small game demo.
+
export const game = true
import type { InputState } from "@/shared/types"
diff --git a/app/nose/bin/greet.ts b/app/nose/bin/greet.ts
deleted file mode 100644
index f2e21f7..0000000
--- a/app/nose/bin/greet.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function (name: string): string {
- return `Hi, ${name || "stranger"}!!!!`
-}
\ No newline at end of file
diff --git a/app/nose/bin/help.ts b/app/nose/bin/help.ts
new file mode 100644
index 0000000..d0ade0c
--- /dev/null
+++ b/app/nose/bin/help.ts
@@ -0,0 +1,26 @@
+// Show helpful information about a command.
+//
+// (Hopefully.)
+
+import { commandPath } from "@/commands"
+
+export default async function (cmd: string) {
+ const path = commandPath(cmd)
+ if (!path) throw `${cmd} not found`
+
+ const code = (await Bun.file(path).text()).split("\n")
+ let docs = []
+
+ for (const line of code) {
+ if (line.startsWith("///")) {
+ docs.push("Runs in the browser.\n")
+ continue
+ } else if (line.startsWith("//")) {
+ docs.push(line.slice(2).trim())
+ } else if (line.trim()) {
+ break
+ }
+ }
+
+ return docs.join("\n")
+}
\ No newline at end of file
diff --git a/app/nose/bin/load.ts b/app/nose/bin/load.ts
index 6857499..12377c6 100644
--- a/app/nose/bin/load.ts
+++ b/app/nose/bin/load.ts
@@ -1,8 +1,11 @@
+// Load a project so you can work on it.
+
import { apps } from "app/src/webapp"
import { getState } from "@/session"
export default function (project: string) {
const state = getState()
+ if (!project) throw `usage: load `
if (state && apps().includes(project)) {
state.project = project
diff --git a/app/nose/bin/ls.tsx b/app/nose/bin/ls.tsx
index 28abd31..44a1756 100644
--- a/app/nose/bin/ls.tsx
+++ b/app/nose/bin/ls.tsx
@@ -1,3 +1,5 @@
+// Look around.
+
import { readdirSync } from "fs"
import { NOSE_WWW } from "app/src/config"
import { projectName, projectDir } from "@/project"
diff --git a/app/nose/bin/mkdir.ts b/app/nose/bin/mkdir.ts
index f884bdd..6732727 100644
--- a/app/nose/bin/mkdir.ts
+++ b/app/nose/bin/mkdir.ts
@@ -1,3 +1,7 @@
+// Makes a directory inside the current directory.
+//
+// Essentially `mkdir -p`.
+
import { mkdirSync } from "fs"
import { join } from "path"
import { projectDir } from "@/project"
diff --git a/app/nose/bin/new.ts b/app/nose/bin/new.ts
index 4a788b5..d8d7c4a 100644
--- a/app/nose/bin/new.ts
+++ b/app/nose/bin/new.ts
@@ -1,3 +1,7 @@
+// Create a new project.
+//
+// We should probably rename this...
+
import { mkdirSync, writeFileSync } from "fs"
import { join } from "path"
@@ -8,7 +12,7 @@ import { isDir } from "app/src/utils"
import load from "./load"
export default function (project: string) {
- if (!project) throw "Please provide a name for your new project\n> new "
+ if (!project) throw "usage: new "
if (apps().includes(project)) throw `${project} already exists`
diff --git a/app/nose/bin/project.ts b/app/nose/bin/project.ts
index 2537616..f49e27f 100644
--- a/app/nose/bin/project.ts
+++ b/app/nose/bin/project.ts
@@ -1,3 +1,5 @@
+// Print the currently loaded project.
+
import { getState } from "@/session"
export default function () {
diff --git a/app/nose/bin/projects.tsx b/app/nose/bin/projects.tsx
index f03c95c..1e859a4 100644
--- a/app/nose/bin/projects.tsx
+++ b/app/nose/bin/projects.tsx
@@ -1,3 +1,5 @@
+// Show the projects on this NOSEputer.
+
import { apps } from "app/src/webapp"
import { getState } from "@/session"
diff --git a/app/nose/bin/pwd.ts b/app/nose/bin/pwd.ts
index 72aa856..2bec605 100644
--- a/app/nose/bin/pwd.ts
+++ b/app/nose/bin/pwd.ts
@@ -1,3 +1,5 @@
+// Show the current working directory.
+
import { dirname } from "path"
import { projectDir } from "@/project"
import { getState } from "@/session"
diff --git a/app/nose/bin/rm.ts b/app/nose/bin/rm.ts
index 5efd262..a80e1ba 100644
--- a/app/nose/bin/rm.ts
+++ b/app/nose/bin/rm.ts
@@ -1,3 +1,5 @@
+// Remove a file.
+
import { unlinkSync, readdirSync } from "fs"
import { join } from "path"
import { projectDir } from "@/project"
diff --git a/app/nose/bin/rmdir.ts b/app/nose/bin/rmdir.ts
index f8f0d97..a924434 100644
--- a/app/nose/bin/rmdir.ts
+++ b/app/nose/bin/rmdir.ts
@@ -1,3 +1,5 @@
+// Remove a directory, and all its children.
+
import { rmdirSync, readdirSync } from "fs"
import { join } from "path"
import { projectDir } from "@/project"
diff --git a/app/nose/bin/share.ts b/app/nose/bin/share.ts
index 849dcdd..b99235f 100644
--- a/app/nose/bin/share.ts
+++ b/app/nose/bin/share.ts
@@ -1,3 +1,5 @@
+// Share a webapp with the public internet.
+
import { apps } from "app/src/webapp"
import { connectSneaker, sneakers, sneakerUrl } from "app/src/sneaker"
diff --git a/app/nose/bin/touch.ts b/app/nose/bin/touch.ts
index 6770e8c..5f6f6b9 100644
--- a/app/nose/bin/touch.ts
+++ b/app/nose/bin/touch.ts
@@ -1,3 +1,5 @@
+// Create an empty text file.
+
import { join } from "path"
import { readdirSync } from "fs"
import { projectDir } from "@/project"
diff --git a/app/nose/bin/unshare.ts b/app/nose/bin/unshare.ts
index 57fa553..128f71d 100644
--- a/app/nose/bin/unshare.ts
+++ b/app/nose/bin/unshare.ts
@@ -1,3 +1,5 @@
+// Stop sharing a webapp with the public internet.
+
import { apps } from "app/src/webapp"
import { disconnectSneaker, sneakers } from "app/src/sneaker"
diff --git a/app/nose/bin/update.ts b/app/nose/bin/update.ts
index 1ef1f81..8ac2a8b 100644
--- a/app/nose/bin/update.ts
+++ b/app/nose/bin/update.ts
@@ -1,3 +1,5 @@
+// Update NOSE itself and restart.
+
import { $ } from "bun"
export default async function () {
diff --git a/app/nose/bin/uptime.ts b/app/nose/bin/uptime.ts
index 8fbb831..0f97652 100644
--- a/app/nose/bin/uptime.ts
+++ b/app/nose/bin/uptime.ts
@@ -1,3 +1,7 @@
+// How long has the NOSE app been running?
+//
+// Totally different from the host computer's uptime. Usually.
+
import { NOSE_STARTED } from "@/config"
export default function () {