Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>PolarSenseNew to Visual Studio Code? Get it now.
PolarSense

PolarSense

Pinch

|
89 installs
| (5) | Free
Visualize data files rows, column statistics and charts + column completion, typo checks and hover statistics for polars, pandas and duckdb — all read from the parquet, CSV, Arrow, Delta, Iceberg, JSON or Excel file behind your DataFrame. No Python interpreter, no code execution.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

PolarSense

Demo GIF

Column-name autocompletion for polars, pandas and duckdb, read from the file your DataFrame actually comes from.

import polars as pl

df = pl.scan_parquet("data/sales.parquet")
out = df.select(pl.col("re␣"))
#                      ◆ region      str
#                      ◆ revenue     f64
#                      ◆ returns_qty i32

Column names are strings, so no type checker can see inside them. But the schema is sitting in the file on disk — a parquet footer, a CSV header row, an Arrow IPC footer, a Delta commit log, an Iceberg metadata pointer, an xlsx header row. PolarSense reads it and offers the names.

It never imports polars, never spawns a Python interpreter, and never runs your code. It reads bytes out of your data files and nothing else — and by default only the metadata part of them.

Open a .parquet file and you see the data rather than a binary-file notice — the same viewer, with no code around it.

Completion, wherever a column name goes

Inside the string literals polars, pandas and duckdb expect a column in: pl.col, select, with_columns, filter, group_by, agg, sort, join (including right_on=, which completes from the frame being joined in), rename and cast dict keys, over, pivot, unpivot, df["region"], polars.selectors, and struct fields as deep as they go. On the pandas side groupby, sort_values, merge, astype, query and the rest; on the duckdb side the relational API.

Column names complete inside SQL too:

df.sql("SELECT ␣ FROM self")
pl.sql("SELECT ␣ FROM df")
duckdb.sql("SELECT s.␣ FROM 'sales.parquet' s")

It follows the chain

What you are offered is what exists at that point, not what the file started with:

narrow = df.select("region", "revenue").rename({"revenue": "rev"})
narrow.select("␣")           # region, rev — not the other seven columns

joined = a.join(b, on="region")
joined.select("␣")           # both frames' columns, collisions suffixed _right

df.group_by("region").agg(pl.col("revenue").sum()).select("␣")   # region, revenue

df.select(cs.numeric()).select("␣")   # revenue, units — the numeric ones
df.unnest("address").select("␣")      # the struct's fields, in its place

Frames built in another file work too — the import is resolved and that file is read the same way, so a loader function's narrowing survives the import. Paths don't have to be literals either: module constants, f-strings, Path(...) / "f.parquet", os.path.join(...) and Path(__file__).parent all fold down to a path first.

When a path genuinely can't be read — it arrives as a function parameter, a config attribute, an environment variable — a comment names it:

# polarsense: data/sales.parquet
return pl.scan_parquet(cfg.source_path)

It catches typos

df.select("regoin")
#          ~~~~~~   No column "regoin" in this frame. Did you mean "region"?

One click to fix. The check only speaks when it is sure: if anything between the file and the cursor couldn't be modelled, it stays quiet rather than guessing. A diagnostic that cries wolf gets switched off and never switched back on.

Hover, status bar, schema

The status bar shows how many columns the frame at your cursor has. Clicking it — or PolarSense: Show schema — lists them with dtype and statistics, and picking one writes it at the cursor. Hovering a column name gives you the same for one:

region · str

min APAC · max US · no nulls

data/sales.parquet · 3 rows

Three panels beside your code

PolarSense: Show details — a row per column, with the numbers the file's own metadata carries:

sales.parquet · df
1,048,576 rows · 9 columns · 24.1 MB · 8 row groups · zstd

Column       Type   Nulls   Min         Max
region       str    0       APAC        US
revenue      f64    3       12.5        9930.0
order_date   date   0       2026-01-02  2026-06-30

It reads nothing the completions haven't already read, so it opens on a four-million-row file as fast as on a small one.

PolarSense: Show data (reads rows) opens the file itself, a hundred rows at a time, header and row index pinned. The page on screen is the read: only those rows and only the columns being drawn are fetched. Click a column header to sort by it — ascending, descending, then the file's own order back. Sorting is the one thing that reads past the page: up to polarsense.sort.maxRows rows, and the panel says when that was a window rather than the file.

PolarSense: Show graph (reads rows) draws the shape of a column instead of listing it — a histogram, a bar of counts, a line over a date, a scatter — picked by dtype, with the aggregate (count, sum, mean, median, min, max) and the chart type a click away, and a date by picker for year/month/week/day. The rows never reach the panel: bins are counted in the extension, so a histogram of four million rows is thirty numbers. A download button writes the chart to a PNG at twice its drawn size, on the panel's own background.

Split by a column from the same per group menu: price over datetime, split by category, is one coloured line per category — or bars side by side, a shared histogram, a coloured scatter. Hover any bar, line or point for its exact value, every series at that x, and how many rows an aggregate was taken over.

In a notebook, all three are a click away from the output itself:

   shape: (200, 4)
   ┌────────┬──────────┬─────────┐
   │ region ┆ order_id ┆ revenue │
   └────────┴──────────┴─────────┘

   POLARSENSE  [ Details ]  [ Data ]  [ Graph ]

No kernel needed to find the frame — the buttons work on a notebook you've opened but never run, on a frame defined eight cells earlier. And a frame with no file at all, built with pl.DataFrame({...}), still gets a Graph: with the notebook's kernel running, its columns and values are read from there.

Or just open the file

A .parquet file opens as its own tab: the same paginated grid, no Python anywhere near it, and Details and Graph buttons in its bar.

sales.parquet
1,048,576 rows · 9 columns · 24.1 MB · 8 row groups · zstd

‹ rows  rows ›   rows 0–99 of 1,048,576   ‹ columns  columns ›   [filter]  [Details] [Graph]

The page on screen is still the whole read — a four-million-row file opens as fast as a small one — and the tab redraws itself when a script rewrites the file under it. It is a read-only editor with no save path at all. View: Reopen Editor With… gets VS Code's own editor back.

Values, if you ask for them

Everything above reads metadata. Turn on polarsense.values.enable and the positions holding a value of a column start answering too:

df.filter(pl.col("region") == "␣")     # US, EU, APAC — read out of the file
df.filter(region="␣")
df.filter(pl.col("region").is_in(["␣"]))

This is the only feature that reads the rows of your data file, which is why it is off until you turn it on. It stays quiet on purpose more often than it speaks: more than 50 distinct values offers nothing rather than a truncated list, and non-string columns offer nothing, because a value position is always inside quotes. Hive partition columns are exact and free — region=EU/ is the value.

Formats

Format How the schema is read
Parquet Footer only — two range reads, independent of file size
CSV Header row, honouring separator, has_header, skip_rows, comment_prefix, quote_char
Arrow IPC The schema flatbuffer, from the footer or the first message
Delta _delta_log walked newest-first, with a checkpoint fallback
Iceberg version-hint.text → the current schema
JSON / NDJSON The first 50 objects of a bounded prefix; nested objects keep their fields
Excel The header row, out of the .xlsx zip

Rows and graphs come from parquet and CSV; values from parquet plus hive partition names. Schemas are read when a file opens rather than when you first ask, so the first completion is a cache hit, and a rewritten file invalidates itself.

Settings

Setting Default What it does
polarsense.enable true Turn completions off without uninstalling
polarsense.pathRoots [] Extra directories to try for relative paths
polarsense.followImports true Follow imports into other files in the workspace
polarsense.csv.inferDtypes false Guess CSV dtypes from the first rows
polarsense.https.enabled false Allow reading schemas over https://
polarsense.values.enable false Offer real values from your data. Reads rows, not just metadata
polarsense.sort.maxRows 100000 Rows read when a header is clicked to sort
polarsense.graph.maxRows 100000 Rows to read when drawing a graph
polarsense.diagnostics.enable true Warn about column names that don't exist
polarsense.notebook.buttons true Show the Details / Data / Graph buttons under a frame
polarsense.trace false Log every resolution to the PolarSense output channel

The full table — caps, cache size, sniff bytes, the kernel setting — is in the README on GitHub.

If nothing appears

VS Code suppresses quick suggestions inside strings by default. PolarSense ships a default that turns them on for Python, but a setting of your own takes precedence:

"[python]": { "editor.quickSuggestions": { "strings": "on" } }

Ctrl+Space always works regardless. The status bar shows what the frame at your cursor resolved to, or why it didn't; PolarSense: Show log has the detail, and that is what to attach to a bug report.

What it deliberately doesn't do

Say nothing rather than something wrong is the rule the whole extension is built on. Where it cannot be sure it marks the answer as a guess, sorts it lower, and switches the typo warning off entirely.

  • Reshapes that invent names from data — pivot, to_dummies, a bare transpose — cannot be answered without reading the rows, so they keep the columns already known and drop certainty.
  • SQL is scanned, not parsed, so a join offers both sides' columns and SQL positions are never typo-checked.
  • The details and data panels describe the source file, not the filtered frame; they say transforms not applied rather than quietly showing you four million rows and calling it the frame.
  • Imports are followed two hops, within the workspace only — nothing in site-packages, nothing indexed in the background.
  • s3:// and gs:// resolve to nothing; https:// works when enabled.
  • .xls and Feather V1 are not read — different binary formats wearing familiar extensions. They report nothing rather than guessing at their bytes.
  • The data panel views — it pages, steps columns, filters the column list and sorts by one column, capped at sort.maxRows and honest when it hits the cap. No row filter, no grouping, no editing: the query engine is polars, in your code.
  • pyarrow is not supported.

Privacy

No telemetry. Nothing leaves your machine except the byte ranges of the data files you point it at, and only over https:// if you turn that on.

Source, full documentation and issues: github.com/Shambels/polarSense. MIT licensed.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft