-
Notifications
You must be signed in to change notification settings - Fork 0
Platform Integration
How stud-cli behaves on the three supported host platforms: Linux, macOS, and Windows. This page is a cross-platform contract, not a portability apology — the differences are narrow, but they are real and worth pinning down.
| Platform | Notes |
|---|---|
| Linux | Primary development platform. |
| macOS | Supported first-class. |
| Windows | Supported with the caveats below. Uses the native shell (cmd, PowerShell) semantics; WSL2 is indistinguishable from Linux for stud-cli. |
No BSD / Solaris / Plan 9. No "POSIX in general" claim — only the three above.
The platform path resolver for user-global storage is native per OS and is pure: callers inject process.env and os.homedir(), and the resolver returns joined paths without side effects.
| Platform | Global config dir | Global data dir | Global cache dir |
|---|---|---|---|
| Linux |
$XDG_CONFIG_HOME/stud-cli if set and non-empty, else $HOME/.config/stud-cli
|
$XDG_DATA_HOME/stud-cli if set and non-empty, else $HOME/.local/share/stud-cli
|
$XDG_CACHE_HOME/stud-cli if set and non-empty, else $HOME/.cache/stud-cli
|
| macOS | $HOME/Library/Application Support/stud-cli |
$HOME/Library/Application Support/stud-cli |
$HOME/Library/Caches/stud-cli |
| Windows |
%APPDATA%\stud-cli if set and non-empty, else %USERPROFILE%\AppData\Roaming\stud-cli
|
%APPDATA%\stud-cli if set and non-empty, else %USERPROFILE%\AppData\Roaming\stud-cli
|
%LOCALAPPDATA%\stud-cli\Cache if set and non-empty, else %USERPROFILE%\AppData\Local\stud-cli\Cache
|
All platform paths are constructed with the native path API (path.join with the platform-specific joiner). Core must not hard-code / or \\ separators into returned paths. This is especially important for Windows, where the returned strings must use Win32 separators even when tests run on a non-Windows host.
Native environment reads are intentionally narrow:
- allowed surface:
get(name)andhas(name) -
has(name)returnsfalsefor unset values and for explicitly empty-string values - no bulk-read API is exposed
- banned shapes include
list,entries,all,keys,dump, or any equivalent "return the whole env" helper
This preserves invariant #2: core never offers a convenience API that can dump the process environment into model context.
Every resolved path is canonicalized before trust-list lookup and manifest recording:
- Symlinks: resolved to their final target. Two launches through different symlinks that target the same directory resolve to the same trust entry.
- Windows junctions and reparse points: resolved the same way as symlinks. A session launched under a junctioned path matches the trust entry of the canonical target.
- Case folding: on case-insensitive filesystems (default macOS, Windows), paths are lowercased for trust-list comparison. On Linux's case-sensitive filesystems, comparison is exact.
- Trailing separator: stripped before comparison.
Project root is <cwd>/.stud/ exactly — no walk-up into parent directories on any platform. See Project Root.
| Signal | Platforms | stud-cli response |
|---|---|---|
SIGINT (Ctrl-C) |
Linux, macOS, Windows (Ctrl-C) | Graceful turn cancel: stops the current turn at the next cancellation point, persists the state slot if possible, prompts the user (or exits in headless). See Concurrency and Cancellation § cancellation scopes. |
SIGTERM |
Linux, macOS (no Windows equivalent) | Persist-and-exit: final snapshot write, then exit with code 130. |
SIGHUP |
Linux, macOS | Reserved; no v1 reaction beyond the same persist-and-exit. |
| Console close (Windows) | Windows | Maps to SIGTERM-equivalent: persist-and-exit. |
A second Ctrl-C during a graceful cancel escalates to a hard exit that skips further in-flight writes. The last acknowledged snapshot is still intact — see Persistence and Recovery § Crash consistency.
| Code | Meaning |
|---|---|
0 |
Normal exit (session ended, or user quit cleanly). |
1 |
Uncaught error surfaced to the user. |
2 |
Validation failure — session did not start. See Validation Pipeline. |
3 |
Trust refused — project not trusted, session did not start. See Project Trust. |
4 |
No interactor available in a session that needed one. See Headless and Interactor. |
5 |
Resume failure — manifest could not validate. See Persistence and Recovery. |
130 |
Terminated by SIGINT / SIGTERM. Persist-and-exit completed. |
137 |
Process killed (e.g., SIGKILL or OOM). The last acknowledged snapshot is intact; anything after it is lost. |
Any code outside this list is an implementation defect — the wiki expects code to conform.
| Context | Rule |
|---|---|
| File reads (e.g., a tool reading a project file) | Native line endings preserved. Core does not normalize. |
| File writes by the Session Store | Store's choice; the bundled Filesystem store writes \n (LF) on all platforms for portability of session archives. |
| LLM context | Line-ending-agnostic; whatever the tool produced is what reaches the request. |
| stdin read by commands | Native. \r\n on Windows is consumed as one terminator. |
CRLF-sensitive tools (diff, regex with $) are the tool's problem; core does not interpose.
| Signal | Behavior |
|---|---|
| Default interactive TTY | Bundled TUI uses color. Color is part of the default product experience, not an optional enhancement. |
NO_COLOR env var set to any non-empty value |
Explicit opt-out: bundled TUI disables ANSI colors. Bundled loggers disable ANSI colors in their sinks. See the NO_COLOR convention. |
FORCE_COLOR env var |
Ignored in v1. If you want color off, NO_COLOR wins; if you want color on, a TTY and no NO_COLOR suffices. |
TERM=dumb |
Bundled TUI falls back to a plain interactor (no cursor addressing). |
| Not a TTY (pipe, redirect) | Bundled TUI degrades to line-oriented output. The interactor capability degrades accordingly — see Headless and Interactor. |
| Unicode rendering | UTF-8 only. On Windows, stud-cli sets the console code page to 65001 (UTF-8) at startup. |
CI=true (any truthy value) in the environment implies:
- No TTY assumed even if one is attached.
- Bundled TUI starts in headless mode.
- No interactive auth paths are offered in first-run; a provider that requires
Auth.DeviceCodeorAuth.Passwordfails First Run with a clear diagnostic rather than hanging. - Exit codes above are the primary signal; there is no "press any key to exit".
See Headless and Interactor and First Run.
| File | Expected permissions |
|---|---|
~/.stud/settings.json |
0600 on Linux / macOS. Windows: ACL restricted to the current user. A wider permission emits a SettingsPermissionsLoose diagnostic. |
~/.stud/trust.json (user-global trust list) |
Same as settings.json. |
~/.stud/integrity/ |
Same. |
<cwd>/.stud/ |
No enforcement — the project layer is under the user's own project rules. |
| Session-store data (bundled filesystem store) | Store's responsibility. See the reference page. |
A loose permission is a warning, not a hard error, because there are legitimate shared-development setups. The diagnostic encourages the user to tighten.
stud-cli spawns subprocesses for:
- MCP servers with
transport: stdio. - Tools that shell out (e.g., the bundled Bash tool).
- CLI-wrapper providers.
Cross-platform rules:
- Core uses the platform's native subprocess API — no shell wrapping by default, to avoid shell-injection footguns. A tool that wants shell semantics (pipes, globs) opts in and documents it.
- Inherited env: subprocesses inherit stud-cli's resolved env — including any
enventries declared for the tool / provider / MCP server. Inherited env is not filtered by core; tools and providers are trusted to not ship sensitive values. - Windows shell quoting differs per shell; tools that accept arguments are responsible for their own quoting. The bundled Bash tool requires
bashinPATHon Windows (typically provided by Git-for-Windows or WSL).
- Containerization strategy for
yolomode — see Sandboxing. - Per-provider platform quirks — see each provider page.
- The TUI's specific terminal capability matrix — see Default TUI.
- Execution Model
- Message Loop
- Concurrency and Cancellation
- Error Model
- Event and Command Ordering
- Event Bus
- Command Model
- Interaction Protocol
- Hook Taxonomy
- Host API
- Extension Lifecycle
- Env Provider
- Prompt Registry
- Resource Registry
- Session Lifecycle
- Session Manifest
- Persistence and Recovery
- Stage Executions
- Subagent Sessions
- Contract Pattern
- Versioning and Compatibility
- Deprecation Policy
- Capability Negotiation
- Dependency Resolution
- Validation Pipeline
- Cardinality and Activation
- Extension State
- Conformance and Testing
- Providers
- Provider Params
- Tools
- Hooks
- UI
- Loggers
- State Machines
- SM Stage Lifecycle
- Stage Definitions
- Commands
- Session Store
- Context Providers
- Settings Shape
- Trust Model
- Project Trust
- Extension Isolation
- Extension Integrity
- LLM Context Isolation
- Secrets Hygiene
- Security Modes
- Tool Approvals
- MCP Trust
- Sandboxing
- Configuration Scopes
- Project Root
- Extension Discovery
- Extension Installation
- Extension Reloading
- Headless and Interactor
- Determinism and Ordering
- Launch Arguments
- Network Policy
- Platform Integration
Tools
UI
Session Stores
Loggers
Providers
Hooks
Context Providers
Commands
- First Run
- Default Chat
- Tool Call Cycle
- Hook Interception
- Guard Deny Reproposal
- State Machine Workflow
- SM Stage Retry
- Hot Model Switch
- Capability Mismatch Switch
- Session Resume
- Session Resume Drift
- Approval and Auth
- Interaction Timeout
- Headless Run
- Parallel Tool Approvals
- Subagent Delegation
- Scope Layering
- Project First-Run Trust
- Reload Mid-Turn
- Compaction Warning
- MCP Remote Tool Call
- MCP Prompt Consume
- MCP Resource Bind
- MCP Reconnect