Native Shell
Native Shell: AI-generated UI, native in your app, on every platform. Apps on iOS, Android, macOS, Windows and Linux, GPUI apps and web pages load signed, sandboxed TSX modules at run time and draw th
A fast viewer for JSON, NDJSON and CSV logs that runs entirely in your browser. No upload, no server, no telemetry — your logs never leave your machine.
Developer toolsTypeScript · JavaScriptGitHub @sabeesoftOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
A powerful VS Code extension for viewing, filtering, and analyzing JSON log files with real-time search, field visibility controls, and custom JavaScript transformations.
Taken from the repository README
Loading the full README.
Read the full README ↗A lightweight log viewer for reading and querying log files. Open any JSON, NDJSON or CSV log, search it, filter by level, find the spike. One engine runs three ways — a VS Code extension, a web app, and an installable PWA — and your logs never leave your machine: no upload, no server, no telemetry. In the editor it follows your VS Code color theme (dark, light and high contrast).
Private by design. Log files often carry production data — tokens, emails, customer records. Log Lens parses and queries everything locally, so there is nothing to leak. See Private by design below.
Log Lens is built so there is nothing to send and nothing to collect — and so you can verify that yourself:
connect-src 'none' — the browser itself forbids it from making any
network request. Pull your network cable and it still works.npm run check:no-network) fails the
build if any network API sneaks into the source. The guarantee is tested, not
promised.The same engine powers all three surfaces, so the privacy guarantee is identical whether you use the extension, the web app or the PWA.
Log Lens never needs an active editor:
.json, .log, .ndjson or .csv file → Open with Log LensLog Lens: Open Log File…, or load the file in the current
editor with Load Current JSON File, Load Log File (NDJSON) or Load CSV FileWhile a Log Lens tab is focused, a status bar item shows the match count, the number of parse errors (click to view them) and the detected format.
The same UI runs as a standalone web app, with nothing but static files behind it. Load a log by any of:
The toolbar's Open file menu can either replace the current logs or add a file to them, so you can merge several logs into one view.
Install it (PWA). In a Chromium browser, use the install icon in the address
bar to install Log Lens as a desktop app. It then works fully offline and
registers as a handler for .json / .ndjson / .log / .csv files, so you
can double-click a log or choose Open with → Log Lens — just like the editor
integration, but as its own app. Nothing about the files is cached or sent.
Log Lens has two modes, toggled in the toolbar. The query text is the state: level chips and column headers rewrite it.
One input that matches the message and every field (nested values included).
Press Enter to run. Level chips (error / warn / info / debug / …) filter by
level and understand numeric Pino/Bunyan levels (30 ≡ info).
A CloudWatch Logs Insights–style pipeline, prefilled from your current search so nothing is lost:
fields @timestamp, level, message
| filter level = "error" and status >= 500
| sort @timestamp desc
| limit 100
fields picks the columns (omit it, or fields *, to see the full raw rows).
Clicking a column header sorts and rewrites the | sort line.filter supports = != < <= > >=, like (substring, or a /regex/), in (...),
and / or / not, grouping with ( ), and bare terms for free-text search.
like on an object field (e.g. a CloudWatch @message container) matches its
JSON text, like a free-text search.# starts a line comment). Run is disabled while the query has errors.level surfaces @message.level) and
keywords as you type.A level-stacked histogram sits under the toolbar, bucketed from the detected timestamp field — red for errors, yellow for warnings, blue for the rest — with start / middle / end time labels, so you can see when things broke at a glance.
{…} N keys or
{…} N.N KB badge (full value in the tooltip).{…} N keys, long strings and stack traces truncate and expand in place — one
affordance for everything.The Filters button opens a side panel with the structured controls:
When trace fields are detected, a SERVICE MAP action opens a service graph:
trace_id / traceId, span_id, parent_span_id, service /
serviceName / service.name, including when nested inside containers like
@message, message, data, body or payload (AWS CloudWatch compatible)Log Lens reads three input formats and auto-detects the level and timestamp fields from common shapes.
JSON array — a .json file containing an array of entries (objects or strings).
NDJSON — a .log / .ndjson file with one JSON object per line; malformed
lines are skipped and reported.
CSV — including AWS Athena / data-lake exports. Columns are auto-detected from
the header row, Unix epoch timestamps (seconds or milliseconds) are converted to
ISO 8601, and Java-style {key=value, nested={…}} notation is parsed into
structured objects (nested objects, arrays, booleans, nulls and numbers).
Common JSON shapes it handles:
// Pino / Bunyan (numeric levels, epoch time)
{ "level": 30, "time": 1234567890, "msg": "Request received" }
// Winston
{ "level": "info", "message": "Server started", "timestamp": "2024-01-15T10:30:00.000Z" }
// AWS CloudWatch (nested @message container)
{
"@timestamp": "2024-01-15T10:30:00.000Z",
"@message": { "level": "info", "message": "Processing request", "service": "api-gateway" }
}
git clone https://github.com/sabeesoft/log-lens.git
cd log-lens
npm run install:all # install extension + webview deps
npm run build:webview # build the React UI
Then open the folder in VS Code and press F5 to launch the Extension Development Host.
log-lens/
├── packages/core/ # @sabeesoft/loglens-core — framework-agnostic
│ # parsing (JSON/NDJSON/CSV, Java notation, …),
│ # runs in the browser and Node, zero host deps
├── src/ # VS Code extension host (Node) — a thin shell
│ ├── extension.ts # Commands, Activity Bar view, status bar
│ ├── fileLoader.ts # Reads a file, parses via loglens-core, displays
│ ├── panels/ # Webview panel manager + status bar item
│ ├── views/recentFiles.ts # Recent-files tree view (globalState)
│ └── utilities/ # getNonce, getUri
├── webview-ui/ # Shared React UI (Vite)
│ ├── public-web/ # PWA manifest, service worker, icon, _headers
│ ├── web.html # Web/PWA entry (vite.config.web.ts)
│ └── src/
│ ├── host/ # HostAdapter seam: vscodeHost / webHost
│ ├── web/ # Web app shell: file loading, PWA, theme
│ ├── components/ # QueryBar, QueryEditor, SearchBar, Histogram,
│ │ # LogTable/LogList/LogRow, Sidebar, TraceModal, …
│ ├── store/ # Zustand store
│ └── hooks/ utils/ types # field discovery, mapping, helpers
└── assets/ # icon + hero + logo sources
The query language lives in its own package, @sabeesoft/insightql.
Scripts:
npm run install:all # install all dependencies
npm run start:webview # Vite dev server for the webview
npm run build:webview # production build of the webview
npm run compile # compile the extension TypeScript
npm run watch # compile in watch mode
npm run lint # lint the extension sources
Inside webview-ui/ (the web app / PWA):
npm run dev:web # dev server for the standalone web app (open the root)
npm run build:web # production build → webview-ui/build-web/
npm run preview:web # preview the production build
npm run check:no-network # fail if any network API is used in the source
Built with the VS Code Extension API, React 19, TypeScript, Zustand,
react-window, @xyflow/react + @dagrejs/dagre (service map), Vite and Lucide
icons. Parsing is @sabeesoft/loglens-core; the query language
is @sabeesoft/insightql —
both self-contained and dependency-free.
The web app is a folder of static files — host it anywhere, no backend required.
cd webview-ui && npm run build:web # outputs build-web/
Serve build-web/ from any static host (GitHub Pages, Netlify, Cloudflare Pages,
or npx serve build-web). The build bakes a strict CSP (connect-src 'none')
into index.html, so the core privacy guarantee holds on any host.
For defense in depth, set the security headers that can only be delivered over
HTTP (not via <meta>) at the hosting layer: public-web/_headers does this
automatically on Netlify and Cloudflare Pages (frame-ancestors,
X-Frame-Options, Referrer-Policy, Permissions-Policy, …). GitHub Pages
can't set custom headers, but the CSP <meta> still enforces the no-network
promise there.
Contributions are welcome — please open an issue or a pull request.
Licensed under the Apache-2.0 License.
For bugs and feature requests, open an issue on the GitHub repository.