MCPcopy Index your code
hub / github.com/DDecoene/WebBaseIII

github.com/DDecoene/WebBaseIII @v1.1.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.1.1 ↗ · + Follow
492 symbols 1,580 edges 75 files 17 documented · 3%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

WebBase-III

dBASE III is back. In your browser. USE customers like it's 1984.

WebBase-III demo — USE, LIST, SEEK, BROWSE

Remember the dot prompt? Before SQL won, before ORMs, before anyone said "full-stack" — there was dBASE III. You typed USE customers, then LIST, and your data was just there. WebBase-III brings that whole world back: the terminal, the language, BROWSE, @ SAY GET forms, .prg programs, indexes, reports — rebuilt from scratch as a modern web app with its own interpreter in TypeScript, backed by Node.js, WebSockets, and SQLite.

Try it in one click — no install:

Open in GitHub Codespaces

The Codespace installs dependencies and starts the dev server automatically. Open the forwarded port 5173 and you're at the dot prompt.


Screenshots

Terminal REPL

The command interface — type W3Script and see results instantly.

Terminal REPL


LIST — tabular record display

LIST prints all records in active index order. The status bar shows the active database and table.

LIST output


Indexing & SEEK

INDEX ON name TO BYNAME creates a SQLite index and activates it — subsequent LIST output is sorted alphabetically. SEEK "Delta NV" jumps the record pointer to the first match in O(log n).

Index and SEEK


BROWSE — editable grid

BROWSE opens a spreadsheet-style grid. Records are shown in active index order. Tab/Enter to edit a cell, Ctrl+N for a new row, Delete to remove a row, Esc to return to the terminal.

BROWSE grid


Program editor

EDIT <name> opens the built-in .prg source editor. Programs support the full W3Script language: DO CASE/ENDCASE, DO WHILE/ENDDO, IF/ENDIF, form layouts, and all data commands. Ctrl+S saves, Esc cancels.

Program editor


Form engine — @ SAY GET / READ

@ row,col SAY "label" GET variable lays out character-cell form fields. READ renders them as a live form and waits for the user to fill in values and submit.

Form engine


The Assistant — sidebar

The permanent left sidebar with category pickers and action buttons.

The Assistant sidebar


The Assistant — New table wizard

Wizards open in the main area with a live W3Script preview.

New table wizard


The Assistant — Modify Structure wizard

MODIFY STRUCTURE (or sidebar action) opens the column editor prefilled with the current schema — rename, retype, add, or drop columns, then apply in one click.

Modify Structure wizard


Aggregate commands & dBASE III parity

SUM, AVERAGE, ? ROUND(…), ? MAX(…), and SORT ON … TO — numeric aggregates and sorted copies, honouring the active filter.

Parity commands — SUM AVERAGE ROUND MAX SORT


CSV import / export

COPY TO <file>.csv exports the current table (browser download); APPEND FROM <file>.csv imports via the file picker.

CSV COPY TO output


Features

Feature Details
W3Script interpreter dBASE III command dialect: navigation, filters, variables, loops, conditionals, forms, programs
BROWSE grid Inline cell editing, keyboard nav, index-ordered display
Form engine @ ROW,COL SAY … GET character-cell layout with READ
Indexing INDEX ON, SEEK, FIND — active index controls all record order
DO CASE Multi-branch conditional, OTHERWISE fallback
Built-in functions EOF(), BOF(), FOUND(), RECNO(), SUBSTR(), STR(), AT(), CTOD(), DTOC() and more
Program files Save, edit, and run .prg scripts with DO / EDIT
The Assistant Permanent left sidebar — open databases/tables, browse, filter, CSV import/export, sort, sum/average, index, search, reindex, pack, design reports, run programs without typing
Multi-user Each WebSocket connection gets its own isolated interpreter session
Live propagation Edit a record in one session and every other session BROWSE-ing that table refreshes automatically — no re-query
Persistent storage better-sqlite3 with WAL mode — databases survive server restart

The Assistant

The sidebar on the left drives everything without typing: open or create databases and tables, browse and filter data, import/export CSV, sort into a new table, sum or average a numeric field, build indexes, search, reindex, pack the database, design and run reports, run programs, and modify table structure. Every click generates a real W3Script command that echoes into the terminal — watch it to learn the language. Wizards (New table, Filter, Sort, Sum/Average, Modify structure, report designer, …) open in the main area and show a live preview of the command they will run.


Quick start

npm install
npm run dev        # http://localhost:5173

Production:

npm run serve      # builds, then serves everything on http://localhost:3000

LAN / Tailscale: the server binds to 0.0.0.0, so http://<tailscale-ip>:3000 works out of the box.


Example session

USE DATABASE mydb
CREATE TABLE customers (name CHAR(40), phone CHAR(20), country CHAR(30))
USE customers

APPEND RECORD
REPLACE name WITH "Acme Corp", phone WITH "555-1234", country WITH "BE"
APPEND RECORD
REPLACE name WITH "Zeta Ltd", phone WITH "555-5678", country WITH "NL"

INDEX ON name TO BYNAME
LIST                        * sorted A→Z

SEEK "Zeta Ltd"             * jump to record instantly
BROWSE                      * open editable grid
SET FILTER TO country == "BE"
LIST                        * filtered view
SET FILTER TO               * clear filter

W3Script command reference

Work areas

WebBase-III supports unlimited work areas — each independently holding a table, record pointer, filter, and index. Link areas by key field using SET RELATION TO for relational data access. Cross-area field access uses alias.field dot notation.

Note: dBASE III supported a maximum of 10 work areas (DOS file handle limit). WebBase-III has no such limit. dBASE III used alias->field arrow syntax; WebBase-III uses modern alias.field dot notation.

Command What it does
SELECT <alias> Activate (or create) a work area by name
USE <table> [ALIAS <name>] Open table in active area; optional alias override
SET RELATION TO <expr> INTO <alias> Link active area to another; auto-seeks on every navigation
SET RELATION TO Clear relation on active area
LIST [col, alias.col, ...] List records; optional column list with cross-area fields
LIST AREAS Show all open work areas, pointers, indexes, and relations
CLOSE Close active area's table
CLOSE ALL Close all work areas, reset to single empty area 1

Cross-area field access: use alias.field dot notation anywhere an expression is accepted — SET FILTER TO, IF, REPLACE, LIST, INDEX ON.

Data & navigation

Command What it does
USE <table> Select a table; restores any saved active index
USE DATABASE <name> Open a named SQLite database
LIST Print records in active index order (up to 500)
LIST STRUCTURE Show column schema
LIST TABLES Show all tables with record counts
LIST DATABASES Show all databases on disk (alias: LIST DBS)
BROWSE Open the editable grid
CLEAR Clear terminal output
CREATE TABLE <n> (col TYPE, ...) Create a table
DROP TABLE <name> Delete a table
APPEND RECORD Insert a blank row
DELETE / DELETE ALL Delete current or all records
PACK VACUUM the SQLite file
GO TOP / GO BOTTOM / GO <n> Move record pointer
SKIP <n> Move pointer forward/back
REPLACE <field> WITH <val>, ... Update field(s) on current row
REPLACE ALL <field> WITH <val>, ... Update all (filtered) rows
SET FILTER TO <expr> Set a WHERE clause; empty clears it
SUM <field> [FOR <cond>] [TO <var>] Total a numeric field over the current table (honours active filter); TO <var> stores the result in a variable instead of printing
AVERAGE <field> [FOR <cond>] [TO <var>] Mean of a numeric field over the current table (honours active filter); TO <var> stores the result in a variable instead of printing
COPY TO <file>.csv Export current table to a CSV download (honours filter + index order)
APPEND FROM <file>.csv Import a CSV (browser file picker) into the current table
MODIFY STRUCTURE Open the Modify-structure wizard for the active table
ALTER TABLE <t> ADD <col> <type> Add a column to a table
ALTER TABLE <t> DROP <col> Remove a column from a table
ALTER TABLE <t> RENAME <col> TO <new> Rename a column
ALTER TABLE <t> ALTER <col> <type> Change a column's type (copy-table dance; data preserved)

Column ops that can invalidate an index (DROP, RENAME, ALTER type) drop all of the table's indexes and warn you to rebuild with INDEX ON.

CSV format (COPY TO / APPEND FROM): Unlike dBASE III's headerless, positional DELIMITED/SDF formats, WebBase-III uses modern header-based CSV (RFC-4180, mapped by column name). Export downloads through the browser and honours the active filter + index order. Import opens a file picker and is lenient: up to 10 bad rows are skipped and reported (line + reason); more than 10 aborts with nothing appended. Limits: 5 MB import, 50,000-row export.

Indexing & search

Command What it does
INDEX ON <expr> TO <tag> Create index on expression; sets it active immediately
SET INDEX TO <tag> Activate a previously created index
SET INDEX TO Clear active index — restores natural insert order
REINDEX Rebuild SQLite indexes for current table
LIST INDEXES Print all indexes for current table with * active marker
SEEK <expr> Position record pointer at first index match
FIND <string> Alias for SEEK (unquoted string — dBASE III legacy form)
SORT ON <field>[/D] TO <newtable> Write a sorted copy of the table to a new table; /D = descending; honours the active filter
JOIN WITH <alias> TO <file> FOR <cond> [FIELDS <list>] Materialize a snapshot table by joining the active area with <alias>; honours the active filter

JOIN differs from classic dBASE III: FOR is required (dBASE allowed omitting it); cross-area fields use alias.field dot syntax (not alias->field); FOR is a SQL predicate (like SET FILTER); the join runs on SQLite's planner, not an O(n×m) nested loop; on a column-name clash the active table wins and the duplicate is dropped with a warning (dBASE dropped it silently); and there are no 128-field / 10-char-name limits.

Limitation: if a SET FILTER is active on the source area, its predicate is applied to the joined query; a filter referencing a column whose name exists in both joined tables may be ambiguous — qualify it or clear the filter before JOIN.

Reports

Command What it does
CREATE REPORT <name> Create a new report definition (opens JSON editor)
MODIFY REPORT <name> Edit an existing report definition
REPORT FORM <name> Run report — ASCII to terminal + HTML preview panel
LIST REPORTS List all saved report definitions
DELETE REPORT <name> Delete a report definition

Programs

Command What it does
DO <name> Run a saved .prg program
EDIT <name> Open .prg source editor
LIST PROGRAMS Show all saved programs

Demo programs live in demos/*.prg and are the single source of truth: they are seeded into the program store on every server start, overwriting any store copy. Matching report definitions live in demos/reports/*.json and are seeded the same way.

Two of them are usable example apps you can build off — run them, then EDIT to adapt: - DO crm — a mini-CRM: companies, contacts, and deals with pipeline totals (SUM … FOR), top-deals sort, a grouped report, CSV export, and a companies+deals JOIN. - DO inventory — a stock manager: categories, products (with reorder levels), and a stock-movements ledger, plus valuation totals, a low-stock report, sort, CSV export, and a products+categories JOIN.

Both lean on multi-work-area relations (alias.field), indexes, and @ SAY … GET/READ forms, and invite you to open a second window to watch live multiuser propagation.

Variables & I/O

Command What it does
? <expr>[, <expr>...] Evaluate expression(s) and print the result (numbers right-justified; bare ? prints a blank line; ?? also accepted)
STORE <val> TO <var> Assign a variable
INPUT "prompt" TO <var> Collect keyboard input
@ r,c SAY "text" GET <var> Define a form field
READ Display the form and wait for submit

Control flow

Command What it does
IF <cond> … ENDIF Conditional block
DO WHILE <cond> … ENDDO Loop
DO CASE … ENDCASE Multi-branch conditional (CASE, OTHERWISE)
HELP Print command reference
QUIT Exit

Built-in functions

Functions work anywhere an expression is accepted — IF, DO WHILE, STORE, REPLACE, INDEX ON, SET FILTER TO, etc.

| Functio

Extension points exported contracts — how you extend this code

IndexCommandsHost (Interface)
(no doc) [2 implementers]
src/interpreter/IndexCommands.ts
IDatabaseBridge (Interface)
(no doc) [2 implementers]
src/shared/types.ts
AssistantHost (Interface)
(no doc)
src/ui/Assistant.ts
Token (Interface)
(no doc)
src/interpreter/Lexer.ts
IIndexStore (Interface)
(no doc) [2 implementers]
src/shared/types.ts
ActionDef (Interface)
(no doc)
src/ui/Assistant.ts
ExecResult (Interface)
(no doc)
src/interpreter/Executor.ts
ColInfo (Interface)
(no doc)
src/shared/types.ts

Core symbols most depended-on inside this repo

handleMessage
called by 402
server/Session.ts
adv
called by 140
src/interpreter/Parser.ts
peek
called by 90
src/interpreter/Parser.ts
peekKw
called by 59
src/interpreter/Parser.ts
q
called by 55
src/interpreter/Executor.ts
callStateless
called by 50
src/interpreter/Builtins.ts
get
called by 49
server/SessionManager.ts
cmd
called by 47
scripts/capture-screenshots.mjs

Shape

Method 281
Function 142
Class 42
Interface 27

Languages

TypeScript100%

Modules by API surface

src/interpreter/Executor.ts73 symbols
src/interpreter/Parser.ts53 symbols
src/shared/types.ts28 symbols
src/ui/Grid.ts20 symbols
src/terminal/Terminal.ts19 symbols
src/interpreter/Lexer.ts16 symbols
src/ui/Assistant.ts15 symbols
src/interpreter/IndexCommands.ts15 symbols
server/ServerDatabaseBridge.ts13 symbols
server/Session.ts12 symbols
server/ReportRunner.ts10 symbols
tests/inventory.spec.ts9 symbols

For agents

$ claude mcp add WebBaseIII \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact