feat(cli): add host and port config flags

Amolith created

Add CLI arguments to configure server bind address and port:
- --host : Bind to specific interface (default: localhost)
- --port : Listen on specific port (default: 8294)

Update documentation in README.md and AGENTS.md to reflect new options.
Use onListen callback to suppress Deno's default "Listening
on..." message.

Assisted-by: Claude Sonnet 4.5 via Crush

Change summary

AGENTS.md | 16 +++++++++++++---
README.md | 19 +++++++++++++++++++
server.ts | 20 ++++++++++++++++++--
3 files changed, 50 insertions(+), 5 deletions(-)

Detailed changes

AGENTS.md πŸ”—

@@ -26,14 +26,23 @@ Run the server
 deno run --allow-net=:8294 --allow-read=./static/,./lists.db,$HOME/.cache/deno/plug --allow-write=./lists.db,$HOME/.cache/deno/plug --allow-env --allow-ffi server.ts
 ```
 
+CLI options:
+- `--host <hostname>`: Bind to specific interface (default: `localhost`, use `0.0.0.0` for all interfaces)
+- `--port <port>`: Listen on specific port (default: `8294`)
+
+Example with custom host/port:
+```bash
+deno run --allow-net=:3000 --allow-read=./static/,./lists.db,$HOME/.cache/deno/plug --allow-write=./lists.db,$HOME/.cache/deno/plug --allow-env --allow-ffi server.ts --host 0.0.0.0 --port 3000
+```
+
 Required permissions:
-- --allow-net=:8294: HTTP server and WebSocket connections (restricted to port 8294)
+- --allow-net=:PORT: HTTP server and WebSocket connections (update PORT to match --port flag)
 - --allow-read: Serve static files from ./static/, read database, cache SQLite library
 - --allow-write: SQLite database operations and cache directory for native library
 - --allow-env: SQLite library reads environment variables (unavoidable for sqlite3 FFI)
 - --allow-ffi: SQLite3 native library access (unavoidable for sqlite3)
 
-Server listens on http://localhost:8294
+Server listens on http://HOST:PORT (defaults to http://localhost:8294)
 
 Database inspection
 ```bash
@@ -348,7 +357,8 @@ No build artifacts, no dependencies beyond Deno stdlib and sqlite3. An optional
 ## Important Constants
 
 - Room ID generation: crypto.randomUUID()
-- Server port: 8294
+- Default server host: localhost (configurable via --host)
+- Default server port: 8294 (configurable via --port)
 - WebSocket path: /ws
 - API endpoints: /api/create (POST, returns room code)
 - Default userId: generated via crypto.randomUUID() and stored in localStorage

README.md πŸ”—

@@ -47,6 +47,25 @@ deno run \
 
 Then open <http://localhost:8294> in your browser.
 
+### CLI options
+
+- `--host <hostname>` β€” Bind to specific interface (default: `localhost`, use `0.0.0.0` for all interfaces)
+- `--port <port>` β€” Listen on specific port (default: `8294`)
+
+Example binding to all interfaces on port 3000:
+
+```bash
+deno run \
+  --allow-net=:3000 \
+  --allow-read=./static/,./lists.db,$HOME/.cache/deno/plug \
+  --allow-write=./lists.db,$HOME/.cache/deno/plug \
+  --allow-env \
+  --allow-ffi \
+  server.ts --host 0.0.0.0 --port 3000
+```
+
+Note: Update `--allow-net` permission to match your chosen port.
+
 ## How it works (for users)
 
 1. Create a room and share the link, or join an existing room by code

server.ts πŸ”—

@@ -379,6 +379,17 @@ function cleanupInactiveRooms() {
 cleanupInactiveRooms();
 setInterval(cleanupInactiveRooms, 24 * 60 * 60 * 1000); // Every 24 hours
 
+// Parse command-line arguments
+let hostname = 'localhost';
+let port = 8294;
+for (let i = 0; i < Deno.args.length; i++) {
+  if (Deno.args[i] === '--host' && i + 1 < Deno.args.length) {
+    hostname = Deno.args[i + 1];
+  } else if (Deno.args[i] === '--port' && i + 1 < Deno.args.length) {
+    port = parseInt(Deno.args[i + 1], 10);
+  }
+}
+
 serve(async (req) => {
   const url = new URL(req.url);
 
@@ -449,6 +460,11 @@ serve(async (req) => {
   }
 
   return new Response("Not found", { status: 404 });
-}, { port: 8294 });
+}, { 
+  port, 
+  hostname,
+  onListen: () => {
+    console.log(`🌿 Sift ready at http://${hostname}:${port}`);
+  }
+});
 
-console.log("🌿 Sift ready at http://localhost:8294");