Skip to content

Cadenza Console

Jung Hyun, Nam edited this page May 28, 2026 · 2 revisions

Cadenza (Console)

The base SDK. Use it for CLI tools, shell-replacement scripts, deploy helpers, one-shot data munging — anything you'd otherwise reach for bash, Python, or Node for.

#:sdk Cadenza@1.0.15
Base SDK Microsoft.NET.Sdk
Output Console application
AOT-clean Yes
Default deploy Self-contained single binary (~30–40 MB JIT, ~10–30 MB AOT)

Minimal example

#!/usr/bin/env dotnet run
#:sdk Cadenza@1.0.15

foreach (var file in Glob("**/*.md"))
{
    var content = ReadText(file);
    WriteLine($"{file}: {content.Length:N0} bytes");
}

Glob, ReadText, WriteLine are Tier 1 bare names — they work without using directives because the SDK adds global using static for them. See Tier 1 API.

What you get bare

// Filesystem (Fs.*)
ReadText / WriteText / Glob       // also: ReadBytes, WriteBytes, Exists, Delete,
                                  //       Move, Copy, MakeDir, TempDir

// Process / shell (Sh.*)
Run("cmd [args…]")                // exit code; opt-in throw on non-zero
Capture("cmd [args…]")            // stdout; throws on non-zero

// Console
WriteLine / Write / ReadLine

// HTTP (Http.*)
await Http.GetJson<T>(url, JsonCtx.Default);
await Http.PostJson<TReq, TResp>(url, body, ReqCtx.Default, RespCtx.Default);
await Http.GetText(url);
await Http.Download(url, "./out.bin");
Http.Client                       // raw HttpClient when you need it

// Environment (Env.*)
Env.Get("VAR")     Env.Args     Env.Cwd     Env.ScriptPath
Env.IsCi           Env.IsLinux  Env.IsMacOS Env.IsWindows
Env.Exit(code)

// JSON (Json.*)
Json.Parse<T>(text, JsonCtx.Default)
Json.Stringify<T>(value, JsonCtx.Default)

// Interactive input (Prompt.*)
Prompt.Confirm("Continue?", defaultValue: true)
Prompt.Text("Name", defaultValue: "anon")
Prompt.Select("Pick", new[] { "a", "b", "c" })   // returns the index
Prompt.Password("API key")

The full surface (with signatures) is on Tier 1 API.

Cookbook

Deploy guard — only deploy from clean main

#:sdk Cadenza@1.0.15

var branch = Capture("git rev-parse --abbrev-ref HEAD").Trim();
if (branch != "main")
{
    WriteLine($"Refusing to deploy from '{branch}'. Switch to main first.");
    Env.Exit(1);
}

if (Capture("git status --porcelain").Trim().Length > 0)
{
    WriteLine("Working tree has uncommitted changes.");
    Env.Exit(1);
}

if (Run("dotnet build -c Release") != 0) Env.Exit(2);
if (Run("dotnet publish -c Release -o ./dist") != 0) Env.Exit(3);
WriteLine("Deploy artifacts written to ./dist");

Full sample: samples/console-deploy-guard.cs.

Typed HTTP fetch (AOT-clean)

#:sdk Cadenza@1.0.15
using System.Text.Json.Serialization;

Http.Client.DefaultRequestHeaders.UserAgent.ParseAdd("cadenza-sample/1.0");

var repo = await Http.GetJson<Repo>(
    "https://api.github.com/repos/dotnet/runtime",
    JsonCtx.Default);

WriteLine($"{repo.full_name}{repo.stargazers_count:N0} stars");

record Repo(string full_name, int stargazers_count);

[JsonSerializable(typeof(Repo))]
partial class JsonCtx : JsonSerializerContext { }

Source-generated JsonSerializerContext keeps the script AOT-clean. Full sample: samples/console-http-fetch.cs.

Interactive bootstrapper

#:sdk Cadenza@1.0.15

var name    = Prompt.Text("Project name", defaultValue: "my-app");
var langIdx = Prompt.Select("Language", new[] { "C#", "F#", "VB" });
var withGit = Prompt.Confirm("Initialize git repository?", defaultValue: true);

MakeDir(name);
WriteText(Path.Combine(name, "README.md"), $"# {name}\n");
if (withGit) Run($"git init {name}", throwOnError: true);

WriteLine($"Done. Project ready at ./{name}");

In CI, set CADENZA_PROMPT_<QUESTION_KEY> to inject answers (see the Prompt XML docs in the source). Full sample: samples/console-prompt-setup.cs.

Glob and count

#:sdk Cadenza@1.0.15

long totalBytes = 0;
int  totalFiles = 0;
foreach (var file in Glob("**/*.cs"))
{
    totalBytes += new FileInfo(file).Length;
    totalFiles++;
}
WriteLine($"{totalFiles} files, {totalBytes:N0} bytes");

When to use it

  • Shell automation: file walks, log parsing, deploy guards
  • CLI utilities you want to hand off as a single binary
  • Glue scripts that need typed JSON, HTTP, or library access without the bash escaping tax

When not to use it

  • You need a hosted background service → use Cadenza Worker
  • You're serving HTTP → use Cadenza Web
  • You're building a library DLL → use a regular .csproj

Samples

  • console-hello.cs — minimal Tier 1
  • console-count-files.cs — directory walk and summarize
  • console-http-fetch.cs — typed HTTP + JSON source gen
  • console-deploy-guard.cs — real-world deploy precondition
  • console-prompt-setup.csPrompt.* walkthrough

See Samples for the full annotated list.

Shipping

dotnet publish app.cs -c Release --self-contained -r linux-x64

See Deployment Single Binary for AOT and trimming.

See also

Clone this wiki locally