A CLI tool for AI agents (and human engineers) to assess and migrate a Webix v6+ codebase to React with vanilla ES6 JavaScript, preferring dependency-light output wherever practical.
Webix is a DOM-manipulation framework (jQuery-adjacent) with several mechanisms
that create invisible coupling across module boundaries — a global widget ID
registry ($$("id")), a prototype-based custom widget API (webix.protoUI)
with lifecycle and layout-math overrides, a pixel-computing layout engine, and a
proxy/data layer that hides client-server contracts inside string prefixes and
callback transforms. Ad-hoc exploration (grep, file-by-file reading) is slow,
token-expensive, and blind to these implicit couplings.
dewebix sweeps the codebase once, builds a persistent, queryable fact index, and exposes analysis, planning, refactoring, and verification commands whose outputs are designed for machine consumption first. The tool surfaces blast radius, migration categories, risk scores, API contracts, data-fetching behavior, styling dependencies, and React-integration traps — making agents and engineers more efficient, safer, and more consistent throughout a migration.
dewebix does not fully automate every migration. Its primary job is to make the next person or agent dramatically more effective by providing the data they need, not just the code.
A sweep parses every file in scope and records two kinds of facts:
- Entities — named Webix constructs: views
(
webix.ui({ view: "datatable" })), custom widgets (webix.protoUI(...)), proxies, collections, React wrappers, event handlers, styles, and templates. Every entity has a numeric ID assigned by the index (shown bydewebix inventory). (Target state: stable human-readable IDs likeid:ordersGrid) - Findings — occurrences of known Webix patterns, each tagged with a rule ID
(e.g.
WX-ID-REF,WX-PROXY-URL,WX-EVENT). Each finding carries a risk score, confidence level, a snippet, and a suggested action.
The sweep writes these facts to an embedded SQLite index (.dewebix/index.db,
WASM-compiled via sql.js). Most subsequent commands query the index — they never
re-parse source files unless performing a write. The exception is analyze jet,
which scans the filesystem root directly and does not use the index.
dewebix computes two complementary risk scores:
| Score | Range | Purpose |
|---|---|---|
| Entity risk | 0–5 | Per-widget or per-path, driven by additive factors (proto-UI lifecycle overrides, leaky wrappers, registry fan-out, sync chains, CSS internals, dynamic IDs, etc.) |
| File risk | 0–100 | Roll-up per file for triage: 0–20 low, 21–45 medium, 46–70 high, 71–100 critical |
A file whose worst entity is risk-5 can never land in the "low" file-risk band. The two scores are always consistent in direction.
React components that mount Webix widgets are classified by how tightly coupled they are to the Webix internals:
| Class | Meaning |
|---|---|
| L0 sealed | Data in via props, events out via callbacks. The contract is clean. |
| L1 instance-leaky | The Webix instance is exposed via ref, imperative handle, or callback. |
| L2 registry-leaky | The widget registers a global id that other modules reach via $$. |
| L3 data-entangled | The widget participates in sync/bind/DataProcessor chains that cross the wrapper boundary. |
L2 and L3 wrappers are first-class migration risks. The refactor wrapper
command refuses to rewrite them without --force and prints a blast-radius
summary first.
The SQLite index stores:
files— path, content hash, language, lines-of-codeentities— kind, name, defining file/span, normalized data JSONrelations— typed edges between entities (references,syncs_with,binds,saves_to,leaks,styles, etc.)findings— rule, file/span, entity link, risk, confidence, snippetmeta— tool version, Webix version, config hash, git commit at scan time
Indexing is incremental: files are keyed by content hash; unchanged files are skipped on re-sweeps. The index is queryable by any command without re-parsing.
┌───────────┐ ┌──────────────┐ ┌──────────────────────────────┐
│ CLI │──▶│ Commands │──▶│ Index store (SQLite) │
│ (cmd tree)│ │ (sweep/ │ │ entities / relations / │
└───────────┘ │ analyze/ │ │ findings / file-hash cache │
│ refactor) │ └──────────────▲───────────────┘
└──────┬───────┘ │
│ │
┌──────────────┼──────────────┐ │
▼ ▼ ▼ │
┌──────────┐ ┌────────────┐ ┌───────────┐ │
│ Scanners │ │ Analyzers │ │ Codemods │────┘ (read index,
│ JS/TS AST│ │ blast-rad. │ │ diff-first│ write files
│ CSS, HTML│ │ layout, │ │ scaffold, │ only w/ --write)
│ (rule │ │ proxies, │ │ ids, proxy│
│ catalog)│ │ styles, │ │ wrapper… │
└──────────┘ │ wrappers, │ └───────────┘
│ graph, plan│ ┌───────────┐ ┌────────────────┐
└────────────┘ │ Reporters │ │ Ledger │
│ json/csv/ │ │ .dewebix/ │
│ md/table/ │ │ state.json │
│ sarif │ └────────────────┘
└───────────┘
- Scanners run rule visitors over parsed files and write facts to the index. Incremental: unchanged files (by content hash) are skipped.
- Analyzers are queries/graph algorithms over the index. Most
subcommands (component, blast-radius, layout, proxies, styles, wrappers) read
from the index.
analyze jetscans the filesystem directly and does not use the index. - Codemods re-parse target files at mutation time and produce
format-preserving diffs. Default
--dry-run;--writeapplies. - Most commands require an existing index. Run
dewebix sweepto build or refresh it before using analyze/refactor commands. Commands that need the index will exit 5 if it is missing.
Run dewebix init to probe the repository and generate a starter
dewebix.config.json. The config controls what is scanned, how Webix globals
are named, target language preferences, and which shell commands
verify project runs.
{
"roots": ["."],
"include": ["src/**/*.{js,jsx,ts,tsx}", "styles/**/*.{css,scss,less}"],
"exclude": ["**/node_modules/**", "**/dist/**", "**/*.min.js"],
"webixGlobals": ["webix", "$$"],
"webix": { "version": "auto" },
"aliases": "auto",
"customProxyPrefixes": [],
"wrapperHints": [],
"knownReactWrapperNames": ["WebixView", "WebixWidget", "WebixHost"],
"react": { "version": 18, "style": "function-components" },
"targets": {
"table": "vanilla",
"data": "fetch",
"state": "module",
"forms": "vanilla",
"styles": "css-modules"
},
"verify": {
"allowTodos": true
},
"ledger": ".dewebix/state.json"
}Key config knobs:
| Key | Default | Description |
|---|---|---|
roots |
["."] |
Directories to scan |
include / exclude |
standard set | Glob patterns for files to include or skip |
webixGlobals |
["webix", "$$"] |
Identifiers treated as Webix globals |
webix.version |
"auto" |
Override auto-detected Webix version |
aliases |
"auto" |
Resolve path aliases from tsconfig/webpack/vite |
wrapperHints |
[] |
File paths suspected to be React/Webix wrappers |
knownReactWrapperNames |
["WebixView", "WebixWidget", "WebixHost"] |
Component names known to be wrappers (merged with probe results) |
targets.* |
vanilla-first | Preferred output patterns per category |
verify.*Command |
null |
Shell commands run by verify project |
pnpm install
pnpm run build
node dist/bin/dewebix.js --versiondewebix init # Probe repo and write dewebix.config.json
dewebix sweep [--incremental] # Build or refresh the fact index
dewebix inventory [--kind …] # List indexed entities (JSON/CSV/table)
dewebix analyze component <entity-id> # Full dossier: config, events, data, styles, layout, contracts (numeric ID)
dewebix analyze blast-radius <entity> # Transitive impact set with risk (CSV/JSON)
dewebix analyze layout <entity|file> # Normalized layout tree + CSS suggestions + hazards
dewebix analyze proxies # All data pathways, endpoint table, transform bodies verbatim
dewebix analyze styles [--for <entity>] # Style coupling in both directions
dewebix analyze wrappers # All wrappers with leakage class (L0–L3) and contracts
dewebix analyze graph [--around <entity>] # Typed dependency graph (dot/mermaid/JSON)
dewebix analyze risk <target> [--fail-on <n>] [--format json|table] # Risk score (file:<path> | entity:<id> | bare path/int)
dewebix brief # Migration brief (JSON): first targets, hazards, avoid-list
dewebix explain WX-IMPORT # Known rule IDs return short JSON descriptionsdewebix plan [--waves] [--unit <entity>] # Ordered migration waves (leaf-first dependency order)
dewebix status # Ledger + coverage summary, suggested next unit
dewebix mark <entity> --status <status> # Update ledger status (pending|in-progress|migrated|verified|blocked|deferred)
dewebix todos --paths <dirs> # List DEWEBIX-TODO markers left by scaffoldsdewebix refactor scaffold <entity> --out <dir> # Generate React skeleton + sidecars (MIGRATION.md, CSS, data)
dewebix refactor ids <paths...> --mode shim # Break $$() cross-references (wave-0 friendly; use --mode registry for full registry replacement)
dewebix refactor proxy <name> --out <dir> # Generate fetch-based ES6 data module from a proxy's endpoint table
dewebix refactor template <paths...> # Convert #prop# templates to JSX render functions
dewebix refactor wrapper <entity> # Swap wrapper innards preserving the external contract (guarded by leakage class)dewebix verify contract <wrapper> [--baseline <file>] # Snapshot/diff a wrapper's external prop+callback API
dewebix verify no-webix <path…> [--allow <ruleId,…>] # Assert zero Webix findings in given paths (exit 1 on findings)
dewebix verify project # Run configured typecheck/lint/test commands; report Webix-usage delta| Flag | Effect |
|---|---|
--format json|csv|table |
Output format (default: table on TTY, json otherwise) |
--fields a,b,c |
Limit output columns |
--max-results N |
Cap results (default 100) |
--full |
Emit all available detail |
--config <path> |
Use a specific config file |
| --quiet | Suppress non-essential output |
| -C <dir> | Run as if in a different directory |
Command-specific formats: analyze jet --format md outputs Markdown;
verify no-webix --output sarif emits SARIF.
| Code | Meaning |
|---|---|
0 |
Success (and, for verify, no violations) |
1 |
Stub command not implemented (doctor, cache clear, suggest, inspect, cookbook, graph); or verification/gating failure (verify no-webix violations, verify project command failure, verify contract drift, --fail-on breach) |
2 |
Usage or config error |
3 |
Invalid entity ID (numeric ID required) |
4 |
Internal error |
5 |
Missing index (no .dewebix/index.db found) |
6 |
Target could not be resolved |
A typical migration session using dewebix as the primary planning and verification interface:
# ── Setup ───────────────────────────────────────────────────
dewebix init # Probe repo and write dewebix.config.json
dewebix sweep # Build/refresh the index
dewebix inventory # List entities with numeric IDs for next steps
# ── Orientation ───────────────────────────────────────────
dewebix brief # Migration brief (JSON): first targets, hazards, avoid-list
dewebix status # What's done, what's pending, suggested next unit
dewebix plan --waves # Ordered migration waves (leaf-first)
# ── Per migration unit ─────────────────────────────────────
# Use entity IDs from inventory output (e.g., 1, 2, 3)
dewebix analyze component 1 # Dossier: config, events, data, styles
dewebix analyze blast-radius 1 # Who breaks if this changes (CSV output)
dewebix refactor scaffold 1 --out src/orders/ # React skeleton + sidecars
# … agent implements, guided by structured DEWEBIX-TODO markers …
dewebix todos --paths src/orders/ # Remaining structured TODOs
dewebix verify contract OrdersGridWrapper # External prop/callback API unchanged
dewebix verify no-webix src/orders/ # Zero webix references remain
dewebix mark 1 --status migrated # Update entity status| Milestone | Status | Notes |
|---|---|---|
| M1 | 🟡 Partial | Config, scanner framework, index, init/sweep/inventory, JSON/CSV/table reporters. doctor and cache clear remain placeholders. |
| M2 | 🟡 Partial | Component dossier, blast-radius, layout, proxies, styles, wrappers, graph (via analyze graph), risk, brief (JSON), explain (known rules). inspect, suggest, cookbook, and root graph remain stubs. |
| M3 | 🟡 Partial | Index-backed plan, ledger (mark/status/todos), and verification commands. Contract and project verification are still baseline implementations, not full index-driven migration gates. |
| M4 | ✅ Done | Codemods: scaffold, ids, proxy, template, wrapper + conservative helpers. Acceptance M4 gate satisfied. |
| M5 stretch | ✅ Done | experimental-layout-skeleton, parity (Playwright skeleton generation), Jet inventory deep-dive, watch mode, help-json (M1–M5 coverage). No formal acceptance gate per spec §18. |
- Initial Specification — Full project specification
- M1 Implementation Plan — Phase-by-phase implementation plan
- Node.js ≥ 20
No native compilation required — dewebix uses sql.js
(WASM-compiled SQLite) for its embedded database. pnpm install works on all
platforms without a C++ toolchain.
The following capabilities are documented in the Initial Specification but are not yet delivered. Each item below links to the relevant spec section.
These commands return "not implemented" errors and should not be used:
| Command | Spec section | Status |
|---|---|---|
dewebix doctor |
§8 | deferred |
dewebix cache clear |
§8 | deferred |
dewebix graph |
§8 | deferred (use dewebix analyze graph) |
dewebix inspect |
§8, §8.4 | deferred |
dewebix suggest |
§8 | deferred |
dewebix cookbook |
§8 | deferred |
explain <findingId> |
§8 | partial (known rule IDs only) |
explain recipe:* |
§8 | deferred |
| Feature | Spec section | Description |
|---|---|---|
| Human-readable entity IDs | §7.1 | id:ordersGrid, proto:kanbanBoard instead of numeric IDs |
Narrative agent-brief.md |
§8.3 | brief currently emits compact JSON, not a Markdown file |
MIT