ClrKernel.Fabric 0.8.0

dotnet add package ClrKernel.Fabric --version 0.8.0
                    
NuGet\Install-Package ClrKernel.Fabric -Version 0.8.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ClrKernel.Fabric" Version="0.8.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ClrKernel.Fabric" Version="0.8.0" />
                    
Directory.Packages.props
<PackageReference Include="ClrKernel.Fabric" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ClrKernel.Fabric --version 0.8.0
                    
#r "nuget: ClrKernel.Fabric, 0.8.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ClrKernel.Fabric@0.8.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ClrKernel.Fabric&version=0.8.0
                    
Install as a Cake Addin
#tool nuget:?package=ClrKernel.Fabric&version=0.8.0
                    
Install as a Cake Tool

CI Release

ClrKernel

A Jupyter kernel for .NET. C# cells are evaluated with Roslyn's scripting engine (Microsoft.CodeAnalysis.CSharp.Scripting), with more CLR languages (PowerShell, F#) on the roadmap. Notebooks run interactively in JupyterLab / VS Code (Jupyter extension) and headlessly via nbconvert or papermill — including from schedulers like SQL Server Agent.

ClrKernel is a maintained fork of SciSharp/ICSharpCore, created after Microsoft deprecated .NET Interactive / Polyglot Notebooks (April 2026). Relative to upstream it adds: correct headless execution under nbclient/papermill, full output capture for async/await cells, control channel + heartbeat + graceful shutdown_request handling, patched vulnerable dependencies, and the kernelspec shipped inside the NuGet package.

Install

dotnet tool install --global ClrKernel
jupyter kernelspec install "$(clrkernel --kernel-spec-path)" --user --name clrkernel
jupyter kernelspec list   # should show: clrkernel

Requires a .NET 8+ runtime (RollForward=Major: newer majors work) and Jupyter.

Use

Pick the ClrKernel (C#) kernel in JupyterLab or VS Code. Cells support #r "nuget: Package, Version" and #r "path/to/local.dll" references, with REPL-style state persisting across cells.

Importing shared libraries

#!import loads C# code from another file into the session — use it to share helper libraries between notebooks, no .NET Interactive required:

#!import "../lib/jobbooks.dib"

Supports .dib (C# sections run; markdown and other-language sections are skipped), .ipynb (code cells run), and .csx/.cs (whole file). Relative paths resolve against the notebook's directory, and nested #!imports inside a library resolve relative to that library's own file. Each resolved file runs once per session — re-importing is a no-op unless you pass --force (#!import --force "lib.dib"), which is handy while iterating on the library itself. Imported files can use #r directives, including #r "nuget: ...", and can #!import further files.

SQL cells

Set a cell's language to SQL (or start it with #!sql) to run T-SQL against Microsoft SQL Server. You get T-SQL highlighting, live syntax checking, keyword/function completion, and results as the same interactive grid (sort, a global filter, per-column filters and value pickers that combine, and Analyze) that C# query results use.

ClrKernel interactive results grid with a per-column value picker open

Connections are named and secret-free — passwords never go in the notebook. Define them with #!sql-connect, or use the connection button next to the cell's language picker, which prompts for credentials and stores the password in your OS credential store (macOS Keychain, Windows Credential Manager, Linux libsecret):

#!sql-connect --name analytics --server sql-warehouse --database reports --auth integrated --default

--auth integrated is Windows Integrated auth on Windows and Microsoft Entra (Azure AD) sign-in on macOS/Linux; --auth sql --user <u> is a SQL login whose password comes from the secret store (or the CLRKERNEL_SECRET_SQL_<NAME> env var for headless runs). A cell targets the default connection, or one named with a leading -- connections <name> comment. Multiple connections can be used across cells in one notebook. A #!sql-connect --name analytics also binds a C# variable analytics (when the name is a valid identifier) so C# cells can query it straight away; use --var <name> for a custom variable or --no-var to skip. See samples/Sql.nb.md.

Querying from C#

C# cells get an ergonomic query API on Sql — no #!sql-connect needed for ad-hoc work. Sql.Connection(server, database) opens a connection (Integrated Security by default), and .Query(sql).Results() returns rows that render as the interactive grid and are enumerable as dynamic rows in the same object:

var dw = Sql.Connection("dw.db.local", "datawarehouse");

var orders = dw.Query("select * from dbo.Orders").Results();  // grid when shown…
foreach (var o in orders) Console.WriteLine($"{o.OrderId}: {o.Total}");  // …rows in code

.Results<T>() maps rows to a record or class; .Query(sql, new { id }) binds parameters; .Scalar<T>(sql) and .Execute(sql) cover single values and non-queries. A .Table(name) reads as a source and writes as a bulk-copy target (createIfMissing builds it from the source schema), and .Transaction() scopes a unit of work:

var recent = dw.Query("select * from dbo.Orders where Year = @y", new { y = 2026 }).Results<Order>();
dw.Table("stg.Orders").BulkCopyFrom(dw.Query("select * from dbo.Orders"), createIfMissing: true);
record Order(int OrderId, string Customer, decimal Total);

For a SQL login use Sql.Connection(server, db, user, "sql:secretRef") (password from the secret store); Sql.AzureConnection(...) for Entra, or Sql.Database("analytics") to reuse a registered #!sql-connect connection. See samples/SqlQuery.nb.md.

Bulk copy & MERGE (ETL)

SQL cells can also move and upsert data, as cell magics or a C# API (both share the same connections). #!sql-bulk streams a query's rows into a table (with a live progress bar); #!sql-merge upserts a source into a target on key columns and reports inserted/updated/deleted counts:

#!sql-bulk  --from analytics --query "SELECT * FROM dbo.Orders" --to warehouse --table stg.Orders --truncate
#!sql-merge --connection warehouse --target dbo.Customers --source stg.Customers --on Id

From C# cells, Sql bulk-loads any collection (POCOs, dictionaries, scalar arrays) and runs MERGEs — Sql.BulkCopy("warehouse", "dbo.Items", rows), Sql.Merge("warehouse", new MergeSpec { Target = "dbo.Customers", Source = "stg.Customers", KeyColumns = new[] { "Id" } }). See samples/SqlEtl.nb.md.

Pipelines & deployment

Annotate SQL cells with -- step <name> and -- needs <a, b> to build an ETL pipeline. #!sql-run executes the steps as a dependency DAG — independent steps run in parallel, a failure skips everything downstream, and a live status board tracks each step. #!sql-deploy --path <folder> deploys a folder of .sql definitions idempotently (CREATE OR ALTER, retried across passes to resolve cross-file dependencies). The -- step / -- needs directives and every #!sql-* magic and flag autocomplete (Ctrl+Space) — -- needs even completes step names from your other cells. See samples/SqlPipeline.nb.md.

Other databases (Oracle, ODBC, JDBC)

The fluent query API isn't SQL-Server-only. Opt-in provider packages give the exact same Query(sql).Results() experience — interactive grid + dynamic rows, typed .Results<T>(), .Table(), .Transaction() — against other engines. Load a provider per notebook with #r "nuget: …" so its driver isn't pulled unless you use it:

#r "nuget: ClrKernel.Data.Oracle"
using ClrKernel.Data.Oracle;
var erp = Oracle.Connect("orahost", 1521, "ORCL", "scott", "oracle:erp");   // password from the secret store
erp.Query("select * from emp").Results()
#r "nuget: ClrKernel.Data.Odbc"
using ClrKernel.Data.Odbc;
var db = Odbc.FromConnectionString("Driver={PostgreSQL Unicode};Server=host;Database=app;");
db.Query("select * from public.orders").Results<Order>();

ClrKernel.Data.Jdbc (experimental) runs Java JDBC drivers via IKVM, including an OpenEdge helper — you supply the driver assembly; validate on Windows before relying on it.

Config-file connections. Keep connection settings out of notebooks in a connections.json (searched up the folder tree; $type selects the provider, passwords are secret references resolved from the OS store / env var):

{
  "erp": { "$type": "Oracle", "server": "orahost", "port": 1521,
           "serviceName": "ORCL", "userId": "scott",
           "password": { "secret": "oracle:erp" } }
}
var erp = Oracle.FromConfig("erp");   // Odbc.FromConfig(...) too

All providers share the ClrKernel.Data core (the same secret store and result grid as #!sql cells). See samples/MultiProvider.nb.md.

Analysis Services (SSAS / Fabric)

C# cells can drive Tabular models — on-prem SQL Server Analysis Services, Azure Analysis Services, or Microsoft Fabric / Power BI semantic models — via the Ssas helper: query with DAX, read table/partition metadata, and process the model.

var cube = Ssas.Connect("ssas.db.local", "DataWarehouse");   // Integrated auth
cube.Query("EVALUATE TOPN(100, 'Sales')");                   // DAX → interactive grid
cube.Tables().DisplayTable();                                // model metadata
cube.ProcessPartitions(new[] { ("Sales", "2026") });         // refresh a partition
cube.Recalculate();

Ssas.ConnectFabric("Workspace", "Model") connects to a Fabric/Power BI semantic model with Entra auth. On-prem SSAS + Integrated auth + processing generally run on Windows (e.g. SQL Server Agent). See samples/AnalysisServices.nb.md.

DAX cells

Set a cell's language to DAX (or start it with #!dax) to run DAX against a cube, results in an interactive grid. Define cubes with #!dax-connect (the default, or --connections <name> per cell); the #!dax-* magics/flags, cube names, and DAX keywords/functions autocomplete.

#!dax-connect --name analytics --server ssas.db.local --database DataWarehouse --default
EVALUATE TOPN(100, SUMMARIZECOLUMNS('Date'[Year], "Revenue", [Total Sales]), [Revenue], DESC)

#!dax-connect --fabric --workspace W --model M targets a Fabric / Power BI semantic model. See samples/Dax.nb.md.

Fabric warehouse writes

C# cells can write to Microsoft Fabric Warehouse tables via the Fabric helper (ClrKernel.Fabric). It bulk-inserts a data reader by staging Parquet to a lakehouse in OneLake and loading it with OPENROWSET — the fast path for large loads — and it can create the target table from the reader's schema using Fabric-supported types (UTF-8 varchar, datetime2 — never nvarchar). All auth is Microsoft Entra; no passwords are handled.

var wh = Fabric.Connect()                       // interactive / default Entra sign-in
    .Workspace("Analytics")
    .Warehouse("SalesDW")
    .WithStaging("Lakehouse_Staging");          // a lakehouse in the same workspace

// Bulk-insert any IDataReader (e.g. a SQL Server query via ClrKernel.Sql):
using var conn = Sql.OpenConnection("analytics");
using var cmd = new SqlCommand("SELECT * FROM dbo.Orders", conn);
using var reader = cmd.ExecuteReader();
wh.BulkInsert(reader, "dbo.Orders", createIfMissing: true);

The reload-batch wrapper deletes a segment and reloads it for a set of tables in parallel — each table gets a fresh source reader from your factory:

var requests = new[] {
    new FabricReloadRequest { TableName = "FactSales", SegmentFilter = "Year = 2026" },
    new FabricReloadRequest { TableName = "FactReturns", SegmentFilter = "Year = 2026" },
};
var results = wh.ReloadBatch(
    requests,
    req => {
        var c = Sql.OpenConnection("analytics");
        var q = new SqlCommand($"SELECT * FROM {req.TableName} WHERE {req.SegmentFilter}", c);
        return q.ExecuteReader(CommandBehavior.CloseConnection); // reader owns/closes the connection
    },
    maxParallelism: 4);
results.DisplayTable();

For a service principal, use Fabric.ClientSecret(tenantId, clientId, secret). See samples/FabricWarehouse.nb.md. (Fabric execution needs a live tenant, so validate against your own workspace.)

Headless / scheduled execution:

jupyter nbconvert --to notebook --execute --output out.ipynb etl.ipynb
papermill etl.ipynb runs/etl_out.ipynb -k clrkernel --language .net-csharp -p run_date 2026-08-04

A failing cell exits non-zero (job schedulers see the failure); papermill also persists the partially-executed output notebook as a diagnostic artifact.

Build & test

A cross-platform task runner (built on Nuke) drives build, test, format, and the VS Code extension. It needs only the .NET SDK — no extra tools to install. Use ./build.sh on macOS/Linux, .\build.ps1 (or build.cmd) on Windows.

./build.sh --help                        # list all targets and flags
./build.sh                               # default: restore + build + test the solution
./build.sh Build                         # build the whole solution
./build.sh Test                          # run all unit tests
./build.sh Build --project ClrKernel.Http   # build one project (searches src/ then test/)
./build.sh Test  --filter Mermaid           # run a subset of tests (dotnet test --filter)
./build.sh Format                        # verify formatting  (Format --apply to fix)
./build.sh Extension                     # build the VS Code extension (npm install + tsc)
./build.sh All                           # solution build + test AND the extension
./build.sh Clean                         # delete bin/obj and the extension's out/
./build.sh --configuration Debug Build   # any target accepts --configuration

Targets chain their dependencies automatically (e.g. Test builds first), so a bare ./build.sh restores, builds, and tests in one go.

Develop

./scripts/install-dev-kernel.sh    # kernel 'clrkernel-dev' running from bin/ output
                                   # iterate: dotnet build + restart kernel
./scripts/install-local-tool.sh    # pack + install the global tool from a local
                                   # feed; tests the full packaged experience
clrkernel --kernel-spec-details    # show which kernelspec the binary resolves

License

Apache 2.0, preserving the upstream license. Original work © SciSharp (Kerry Jiang, Haiping Chen, and contributors); fork maintained by ClrKernel.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on ClrKernel.Fabric:

Package Downloads
ClrKernel.Core

Execution core for ClrKernel: Roslyn C# scripting engine with #r nuget resolution, #!import/#!lib document loading (.dib, .ipynb, .csx), and display primitives — independent of any notebook transport (Jupyter, VS Code, CLI runners).

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.8.0 104 8/10/2026