- introduce `sdt` subcommands for run, debug, setup, env, favorite, and explain - add project/workspace discovery plus config bootstrap and migration helpers - expand tests for CLI parsing, project role detection, and headless flows
SDT (Stan's Dev Tools)
Cross-platform terminal orchestrator for project workflows, toolchain checks, and prerequisite gating.
Current State
- Standalone
.NETTUI app (net10.0) - Domain-separated source projects under
src/:DevTool.Engine(workflow/config/orchestration services)DevTool.Runtime(process/command execution primitives)DevTool.Host.Tui(terminal UI host surface)
- Workflow-first config model in
devtool.json - Strict-by-default legacy migration (
targets-only configs fail unless compat mode is enabled) - Python-first diagnostics/build script layer under
scripts/ - Fail-fast execution with install prompt gating for missing prerequisites
- Debug profiles with attach metadata and diagnostics bundle generation
- Workspace-first project switching with support for external project paths
- Workspace-level defaults layering via
sdt-defaults.json(ancestor defaults merged, project config wins) - Project status tracking is maintained in
ROADMAP.md - Core run-event stream (
RunEvent) shared by workflow + debug execution (TUI consumes it; GUI-ready) - Run events are persisted to JSONL at
.sdt/events/for external tooling/GUI consumers - Run events now include versioned contract fields:
run_event_version,run_id,project_root,env_profile,timestamp_utc,event_type - TUI includes
SYSTEM -> View run eventsto inspect persisted JSONL event logs SYSTEM -> Run config doctorcan apply common autofixes (missing working dirs, legacy migration)SYSTEM -> Keybinding helpprovides normalized cross-platform shortcut guidanceSYSTEM -> Run historysupports rerun from prior execution context- First-run projects are prompted to run a setup wizard (doctor + autofix + optional toolchain setup)
- Toolchain management now includes toolchain doctor + auto-fix flow with installer prompts and post-install verification
- Env profiles (
envProfiles) support deterministic inheritance (dev/ci/release) and runtime profile selection fromSYSTEM -> Select env profile - Diagnostics bundles include managed secret redaction policy (env-key pattern redaction + output token redaction)
- Workspace quick actions/favorites can run workflows across projects (auto switch-and-run)
- Quick-action pinning is supported from workflow run results and events viewer
- Bootstrap detects additional project stacks (
go,maven,gradle) and setsproject.type(dotnet,node,python,rust,go,java,tauri,polyglot,generic) - Headless execution mode is available for workflow/debug automation with JSON output
- Terminal capability fallback modes supported via
NO_COLOR/SDT_NO_COLORandSDT_NO_UNICODE
Run
dotnet run --project DevTool.csproj
Run from any subdirectory inside a project; SDT walks up to find devtool.json.
If devtool.json is missing, SDT now offers to scan the repo and generate a default config.
Explicit bootstrap command:
dotnet run --project DevTool.csproj -- init
Headless workflow/debug commands:
sdt run <workflowId> --json [--project-root <path>] [--env-profile <id>] [--non-interactive]
sdt debug <profileId> --json [--project-root <path>] [--env-profile <id>] [--non-interactive]
GUI bridge read/manage command:
sdt bridge --stdio [--project-root <path>]
Workspace inventory scan (GUI/TUI shared discovery contract):
sdt workspace scan --json [--project-root <path>]
SDT_NONINTERACTIVE=1 globally enables non-interactive behavior for install prompts.
Bootstrap detects common stacks (dotnet, npm/node, python, cargo/tauri, go, maven/gradle, git, docker) and generates:
- default workflows
- toolchain/tooling defaults
- debug profiles + diagnostics defaults
Config Model
SDT supports both:
workflows(preferred)targets(legacy; compat mode only)
Legacy Migration Mode (v1.2)
- Default: strict mode
- Behavior:
targets-only config fails early with migration instructions - Preview file: SDT writes
devtool.generated.workflows.jsonfor migration help - Temporary rollback: set
SDT_LEGACY_MODE=compat
Permanent fix (recommended):
- Open
devtool.generated.workflows.json - Copy its
workflowsintodevtool.json - Remove or empty legacy
targets - Run
sdt.exeagain in strict mode
Workflow shape (preferred)
{
"id": "build",
"label": "Build",
"description": "Build project",
"group": "Build",
"dependsOn": [],
"steps": [
{
"id": "dotnet-build",
"label": "dotnet build",
"action": "dotnet-build",
"actionArgs": [],
"workingDir": ".",
"requires": [
{ "tool": "dotnet", "installPolicy": "Prompt" }
]
}
]
}
Extra sections
tooling.tools[].preferredInstallCommands: preferred install commands per tooltooling.tools[].executables: explicit executable candidates for non-standard PATH setupsproject.rootHints: files/folders that identify project rootenv: session-level environment variable editor valuesdebug.profiles[]: run/attach debug profilesdebug.diagnostics: diagnostics bundle policy (.sdt/debugby default)- secure default: allowlist-only environment capture
- set
includeAllEnv=trueto opt into full environment capture
Workspace Defaults Layering
If SDT finds sdt-defaults.json in the project directory tree (current project root or an ancestor), it merges it into the effective config before runtime:
- base layer:
sdt-defaults.json - override layer: project
devtool.json(project values win)
Merge behavior:
- objects merge recursively
- arrays/scalars are replaced when project provides the property
This is useful for shared defaults like toolchains, diagnostics policies, and baseline env definitions across multiple projects in one workspace.
Execution Behavior
For each workflow step:
- Resolve dependencies (topological order)
- Probe required tools
- If missing, show install commands and prompt (
Promptpolicy) - On decline/install failure/step failure, stop immediately
- Render step summary table with exit code + elapsed time
- On workflow/debug failure, generate diagnostics bundle when enabled
Installer command precedence:
tooling.tools[].preferredInstallCommandsscripts/diag.py install-plan- built-in C# fallback templates (used automatically if script planning fails)
When a tool probe fails, SDT now prints probe diagnostics (including command resolution source/path) in run output before prompting for installs.
Headless exit code contract:
0success10missing prerequisite11install failed12command failed13validation/config error14user-declined / non-interactive prompt refusal
Scripts
See scripts/README.md.
Primary Python entrypoints:
scripts/diag.pyscripts/build.pyscripts/dotnet-min.pyscripts/pip-min.pyscripts/publish-*.py
Workspace Support
- Uses
sdt-workspace.jsonwhen present - If missing, can auto-discover nearby projects containing
devtool.json - Workspace screen can add external project roots (absolute paths supported)
projects[].disabled,projects[].tags, andprojects[].toolFamiliesare supported- Hybrid inventory model discovers marker-only candidates (
.slnx/.sln/.csproj) without silently mutating workspace config - TUI workspace screen supports:
Add candidateAdd + initialize devtool.jsonIgnore for now(session-only)
- Inventory snapshot is cached at
.sdt/workspace-inventory.jsonfor GUI-readiness
GUI Direction
- Planned GUI stack for current phase: Tauri-first
- Avalonia is deferred for re-evaluation after first GUI milestone ships on top of the same headless contracts
- GUI workspace scaffold: TauriShell README
- Hybrid GUI bridge is active:
- execution:
sdt run/debug --json - read/manage:
sdt bridge --stdio
- execution:
- Bridge contract doc: gui-bridge-contract.md
- Parity manifest: gui-tui-parity.json
- GUI will consume:
sdt workspace scan --jsoninventory payloadrun/debug --jsonsummaries- persisted run events from
.sdt/events/*.jsonl
Dev Shell Bootstrap
Python-first cross-shell dev environment bootstrap:
# PowerShell
. ./scripts/dev-shell.ps1
# cmd
scripts\dev-shell.cmd
# bash/zsh
source ./scripts/dev-shell.sh
Underlying implementation is scripts/dev_shell.py:
python scripts/dev_shell.py export --shell pwsh --jsonpython scripts/dev_shell.py doctor
Legacy PowerShell Compatibility
Legacy .ps1 scripts remain for migration compatibility only. New functionality is implemented in Python scripts first. script-common.ps1 is legacy-only.
Legacy runtime behavior in v1.2:
- strict mode rejects
targets-only configs by default - compat mode (
SDT_LEGACY_MODE=compat) temporarily allows legacy execution - TUI
SYSTEMincludesMigrate legacy targets -> workflowsto apply migration in place (with backup) - Python reroute is authoritative for legacy
pwsh -File ...ps1targets .ps1fallback is opt-in only: setSDT_PWSH_LEGACY_FALLBACK=1for temporary compatibility
Deprecation target:
- v1.x: compatibility only (no new behavior guarantees)
- v2.0: remove legacy
.ps1scripts from default SDT workflows and docs
Testing
Run unit/integration tests:
dotnet test tests/DevTool.Tests/DevTool.Tests.csproj
Run Python script smoke checks:
python -m py_compile scripts/*.py
Verify workflow route/path resolution:
python scripts/verify-workflow-routes.py --project-root .
python scripts/verify-workflow-routes.py --project-root . --workflow build --workflow tauri --execute --env-profile dev