diff --git a/CLAUDE.md b/CLAUDE.md index 60b2954..fbaa16d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -47,8 +47,8 @@ Path aliases: `$` = server, `@` = shared, `%` = lib (defined in tsconfig.json). ### Server (`src/server/`) - `apps.ts` -- **The heart**: app discovery, process spawning, health checks, auto-restart, port allocation, log management, graceful shutdown. Exports `APPS_DIR`, `TOES_DIR`, `TOES_URL`, and the `App` type (extends shared `App` with process/timer fields). -- `api/apps.ts` -- REST API + SSE stream. Routes: `GET /` (list), `GET /stream` (SSE), `POST /:name/start|stop|restart`, `GET /:name/logs`, `POST /` (create), `DELETE /:name`, `PUT /:name/rename`, `PUT /:name/icon`. -- `api/sync.ts` -- File sync protocol: manifest comparison, push/pull with hash-based diffing. +- `api/apps.ts` -- REST API + SSE stream. Routes: `GET /` (list), `GET /stream` (SSE), `POST /:name/start|stop|restart`, `GET /:name/logs`, `POST /` (create via git), `POST /:name/rename`, `POST /:name/icon`, env var CRUD, tunnel management. +- `api/sync.ts` -- File sync API: manifest endpoint, file read/write, app reload (triggered by git tool after deploy), file watch SSE. - `index.tsx` -- Entry point. Mounts API routers, tool URL redirects (`/tool/:tool`), tool API proxy (`/api/tools/:tool/*`), initializes apps. - `shell.tsx` -- Minimal HTML shell for the SPA. - `tui.ts` -- Terminal UI for the server process (renders app status table when TTY). @@ -79,23 +79,22 @@ Client-side SPA rendered with `hono/jsx/dom`. No build step -- Bun serves `.tsx` CLI commands: - **Apps**: `list`, `info`, `new`, `get`, `open`, `rename`, `rm` -- **Lifecycle**: `start`, `stop`, `restart`, `logs`, `metrics`, `cron` -- **Sync**: `push`, `pull`, `status`, `diff`, `sync`, `clean`, `stash` -- **Config**: `config`, `env`, `versions`, `history`, `rollback` +- **Lifecycle**: `start`, `stop`, `restart`, `logs`, `metrics`, `cron`, `share`, `unshare` +- **Config**: `env` ### Shared (`src/shared/`) Types shared between browser and server. **Cannot use Node/filesystem APIs** (runs in browser). - `types.ts` -- `App`, `AppState`, `LogLine`, `Manifest`, `FileInfo` -- `gitignore.ts` -- `.toesignore` pattern matching +- `gitignore.ts` -- `.gitignore` pattern matching (used by sync API and file watchers) ### Lib (`src/lib/`) Server-side code shared between CLI and server. Can use Node APIs. - `templates.ts` -- Template generation for `toes new` (bare, ssr, spa) -- `sync.ts` -- Manifest generation, hash computation +- `sync.ts` -- Manifest generation, hash computation (used by sync API for file diffing in tools) ### Tools Package (`src/tools/`) @@ -126,7 +125,7 @@ Tools are apps with `"toes": { "tool": true }` in package.json. From the server' ### Versioning -Apps live at `APPS_DIR//` with timestamped version directories and a `current` symlink. Push creates a new version; rollback moves the symlink. +Apps use git for version control. Each app has a bare git repo at `DATA_DIR/repos/.git`. Deploying is a `git push` to the server's git tool, which extracts HEAD into `APPS_DIR//` and reloads the app. History, diffing, and rollback use standard git commands. ### Environment Variables @@ -215,4 +214,4 @@ function start(app: App): void { ## Writing Apps and Tools -See `docs/CLAUDE.md` for the guide to writing toes apps and tools. +See `docs/GUIDE.md` for the guide to writing toes apps and tools. diff --git a/docs/APPS.md b/docs/APPS.md index 4562efa..3bbdd59 100644 --- a/docs/APPS.md +++ b/docs/APPS.md @@ -6,10 +6,8 @@ An app is an HTTP server that runs on its assigned port. ``` apps// - / # YYYYMMDD-HHMMSS - package.json - index.tsx - current -> # symlink to active version + package.json + index.tsx ``` **package.json** must have `scripts.toes`: diff --git a/docs/CRON.md b/docs/CRON.md index 800c950..b16dd1c 100644 --- a/docs/CRON.md +++ b/docs/CRON.md @@ -9,7 +9,7 @@ The cron tool discovers jobs from all apps and runs them automatically. Add a file to `cron/` in any app: ```ts -// apps/my-app/current/cron/daily-cleanup.ts +// apps/my-app/cron/daily-cleanup.ts export const schedule = "day" export default async function() { @@ -73,7 +73,7 @@ Jobs track: ## discovery The cron tool: -1. Scans `APPS_DIR/*/current/cron/*.ts` +1. Scans `APPS_DIR/*/cron/*.ts` 2. Imports each file to read `schedule` 3. Validates the schedule 4. Registers with croner diff --git a/docs/GUIDE.md b/docs/GUIDE.md index e7401de..08d806b 100644 --- a/docs/GUIDE.md +++ b/docs/GUIDE.md @@ -19,13 +19,11 @@ Toes is a personal web appliance that runs multiple web apps on your home networ - [CLI Reference](#cli-reference) - [App Management](#app-management) - [Lifecycle](#lifecycle) - - [Syncing Code](#syncing-code) + - [Deploying Code](#deploying-code) - [Environment Variables](#environment-variables) - - [Versioning](#versioning) - [Cron Jobs](#cron-jobs-1) - [Metrics](#metrics) - [Sharing](#sharing) - - [Configuration](#configuration) - [Environment Variables](#environment-variables-1) - [Health Checks](#health-checks) - [App Lifecycle](#app-lifecycle) @@ -40,7 +38,7 @@ Toes is a personal web appliance that runs multiple web apps on your home networ # Install the CLI curl -fsSL http://toes.local/install | bash -# Create a new app +# Create a new app (scaffolds, inits git, and pushes to server) toes new my-app # Enter the directory, install deps, and develop locally @@ -48,8 +46,9 @@ cd my-app bun install bun dev -# Push to the server -toes push +# Deploy changes (standard git) +git add . && git commit -m "my changes" +git push toes main # Open in browser toes open @@ -57,7 +56,7 @@ toes open Your app is now running at `http://my-app.toes.local`. -> **Tip:** Add `.toes` to your `.gitignore`. This file tracks local sync state and shouldn't be committed. +`toes new` automatically sets up a `toes` git remote pointing at the server. Pushing to it triggers a deploy. --- @@ -85,8 +84,8 @@ A generated SSR app looks like this: ``` my-app/ + .gitignore # Files to exclude from sync and deploy .npmrc # Points to the private registry - .toesignore # Files to exclude from sync (like .gitignore) package.json # Must have scripts.toes tsconfig.json # TypeScript config index.tsx # Entry point (re-exports from src/server) @@ -457,13 +456,11 @@ app.get('/', c => { const appName = c.req.query('app') if (!appName) return c.html(

No app selected

) - const appPath = join(APPS_DIR, appName, 'current') + const appPath = join(APPS_DIR, appName) // Read files from appPath... }) ``` -Always go through the `current` symlink — never access version directories directly. - **Calling the Toes API:** ```tsx @@ -522,19 +519,21 @@ toes new my-app --bare # Minimal template toes new my-app --spa # SPA template ``` -Creates the app locally, then pushes it to the server. If run without a name, scaffolds the current directory. +Scaffolds the app locally, initializes a git repo with a `toes` remote pointing at the server, and pushes. The git push triggers a deploy. If run without a name, scaffolds the current directory. **`toes info [name]`** — Show details for an app (state, URL, port, PID, uptime). -**`toes get `** — Download an app from the server to your local machine. +**`toes get `** — Clone an app from the server to your local machine. ```bash -toes get my-app # Creates ./my-app/ with all files +toes get my-app # Clones into ./my-app/ cd my-app bun install bun dev # Develop locally ``` +The clone comes with a `toes` remote already configured, so `git push toes main` deploys. + **`toes open [name]`** — Open a running app in your browser. **`toes rename [name] `** — Rename an app. Requires typing a confirmation. @@ -562,54 +561,38 @@ toes logs my-app -f -g error # Follow and filter Duration formats for `--since`: `1h` (hours), `2d` (days), `1w` (weeks), `1m` (months). -### Syncing Code +### Deploying Code -Toes uses a manifest-based sync protocol. Each file is tracked by SHA-256 hash. The server stores versioned snapshots with timestamps. - -**`toes push`** — Push local changes to the server. +Toes uses git for deployments. Each app has a `toes` remote that points to the server's git tool. Pushing to it extracts the latest commit and deploys it. ```bash -toes push # Push changes (fails if server changed) -toes push --force # Overwrite server changes +# Make changes, commit, and deploy +git add . +git commit -m "update homepage" +git push toes main ``` -Creates a new version on the server, uploads changed files, deletes removed files, then activates the new version. The app auto-restarts. +The git push triggers the server to: +1. Store the commit in a bare repo at `DATA_DIR/repos/.git` +2. Extract HEAD into the app directory +3. Run `bun install` and restart the app -**`toes pull`** — Pull changes from the server. +Use standard git commands for history, diffing, and rollback: ```bash -toes pull # Pull changes (fails if you have local changes) -toes pull --force # Overwrite local changes +git log # View deploy history +git diff HEAD~1 # See what changed +git revert HEAD # Undo last deploy +git push toes main # Deploy the revert ``` -**`toes status`** — Show what would be pushed or pulled. +To clone an existing app from the server: ```bash -toes status -# Changes to push: -# * index.tsx -# + new-file.ts -# - removed-file.ts -``` - -**`toes diff`** — Show a line-by-line diff of changed files. - -**`toes sync`** — Watch for changes and sync bidirectionally in real-time. Useful during development when editing on the server. - -**`toes clean`** — Remove local files that don't exist on the server. - -```bash -toes clean # Interactive confirmation -toes clean --force # No confirmation -toes clean --dry-run # Show what would be removed -``` - -**`toes stash`** — Stash local changes (like `git stash`). - -```bash -toes stash # Save local changes -toes stash pop # Restore stashed changes -toes stash list # List all stashes +git clone http://git.toes.local/my-app +cd my-app +bun install +bun dev # Develop locally ``` ### Environment Variables @@ -640,26 +623,12 @@ toes env rm -g API_KEY # Remove global var ### Versioning -Every push creates a timestamped version. The server keeps the last 5 versions. - -**`toes versions [name]`** — List deployed versions. +Every `git push toes main` creates a new deploy. Version history is managed through git. ```bash -toes versions my-app -# Versions for my-app: -# -# → 20260219-143022 2/19/2026, 2:30:22 PM (current) -# 20260218-091500 2/18/2026, 9:15:00 AM -# 20260217-160845 2/17/2026, 4:08:45 PM -``` - -**`toes history [name]`** — Show file changes between versions. - -**`toes rollback [name]`** — Rollback to a previous version. - -```bash -toes rollback my-app # Interactive version picker -toes rollback my-app -v 20260218-091500 # Rollback to specific version +git log --oneline # List deploys +git revert HEAD # Undo last change +git push toes main # Deploy the revert ``` ### Cron Jobs @@ -717,10 +686,6 @@ toes share my-app **`toes unshare [name]`** — Stop sharing an app. -### Configuration - -**`toes config`** — Show the current server URL and sync state. - --- ## Environment Variables diff --git a/docs/TOOLS.md b/docs/TOOLS.md index 6dbe0ce..3fe7785 100644 --- a/docs/TOOLS.md +++ b/docs/TOOLS.md @@ -44,21 +44,17 @@ app.get('/', c => { ## accessing app files -Always go through the `current` symlink: - ```ts const APPS_DIR = process.env.APPS_DIR! -const appPath = join(APPS_DIR, appName, 'current') +const appPath = join(APPS_DIR, appName) ``` -Not `APPS_DIR/appName` directly. - ## linking to tools Use `/tool/:name` URLs to link directly to tools with params: ```html - + View in Code ```