Architecture Overview
Relevant source files
The following files were used as context for generating this wiki page:
The putio-cli is a modern, agent-first command-line interface for the put.io API. Built using the Effect ecosystem, it emphasizes deterministic automation, service-based dependency injection, and a rigid contract for machine-readable output. Unlike traditional CLIs that prioritize human-readable text, this architecture treats JSON/NDJSON as the primary contract while providing an adapter layer for terminal-based human interactions. Sources: README.md, CLAUDE.md:14-16
Core Design Principles
The architecture is governed by several key technical constraints:
- Effect-Native Design: Control flow, error handling, and environment management are handled via
Effect,Layer, andSchema. Ad-hoc control flow is avoided in favor of functional patterns. Sources: CLAUDE.md:17-18 - Agent-First Contract: The CLI provides a
describecommand that exposes its entire command surface, including flag types, default values, and JSON payload shapes for mutations. Sources: src/internal/metadata.ts:14-30, skills/putio-cli/SKILL.md:12-18 - Separation of Concerns: Business logic is moved into internal helpers and services, keeping command modules thin. Terminal output is strictly a separate adapter layer from the core data processing. Sources: CLAUDE.md:15-19
Layered Architecture
The system is structured as a stack of Effect Layers, progressing from the raw runtime environment to the command execution logic.
This diagram shows the flow of a CLI request through the layered service architecture.
Sources: src/internal/app-layer.ts, src/internal/runtime.ts
1. Runtime Layer
The CliRuntime service abstracts environment-specific operations such as file system access, hostname retrieval, and terminal interactivity checks. This allow the CLI to remain testable by providing a FileSystem.makeNoop or mock environment during in-process tests. Sources: src/internal/runtime.ts, src/internal/state.test.ts:85-110
2. Configuration & State
The CLI manages two types of configuration:
- Runtime Configuration: Derived from environment variables (e.g.,
PUTIO_CLI_TOKEN,PUTIO_CLI_PROFILE) and platform-specific paths like XDG config directories. Sources: src/internal/config.ts:86-105 - Persisted State: Managed via
src/internal/state.ts, which handles the storage of OAuth tokens and named profiles in aconfig.jsonfile. The system ensures private file permissions (chmod0o600) for sensitive data. Sources: src/internal/state.ts, src/internal/state.test.ts:60-75
3. Command System
Commands are defined using the @effect/cli package. The architecture differentiates between Read commands (querying data) and Write commands (mutating state). Sources: src/internal/command.ts:15-40
Command Input Handling
Mutation commands support a dual-input model:
- Flag-based: Standard CLI flags (e.g.,
--id,--name). - Raw JSON: A
--jsonflag allows agents to pass a complete payload that matches the SDK's schema. Sources: src/internal/command.ts:316-335, src/commands/files.ts:250-270
Pagination and Streaming
For read workflows, the CLI supports cursor-based pagination. The collectAllCursorPages helper automatically follows cursors until exhaustion when the --page-all flag is present. Sources: src/internal/command.ts:408-450
Authentication Flow
The CLI supports three tiers of authentication resolution:
- Environment Variables:
PUTIO_CLI_TOKENtakes highest precedence and overrides all other settings. - Named Profiles: Specific accounts or environments selected via
PUTIO_CLI_PROFILEorputio auth profiles use. - Default Profile: The fallback persisted token in the configuration file. Sources: src/internal/state.ts, src/internal/config.ts:90-95
Authentication resolution priority flow.
Sources: src/internal/state.ts, src/internal/state.test.ts:370-395
Output & Security Architecture
The OutputService is responsible for rendering results while maintaining security guardrails.
Rendering Modes
| Mode | Use Case | Characteristics |
|---|---|---|
json | Automation/Agents | Stable, machine-readable, includes safety metadata. |
ndjson | Large Reads | Stream-friendly, newline-delimited objects for large datasets. |
terminal | Human Users | ANSI-formatted tables, loaders, and branded success messages. |
Sources: src/internal/output-service.ts, src/internal/command.ts:460-480
Security Sanitization
The architecture enforces strict sanitization of all output:
- Redaction: Sensitive keys like
auth_token,password, andtokenare recursively redacted from JSON and terminal output. - URL Scrubbing: OAuth tokens are stripped from query parameters in URLs before display.
- Agent Safety: For AI agents, the CLI identifies "untrusted" text paths in API responses (e.g., file names or notes that might contain prompt injections) and annotates them with
_meta.agentSafetymetadata.
Sources: src/internal/output-service.ts, src/internal/output.test.ts:15-55, src/internal/agent-dx.ts:110-120
Agent Developer Experience (Agent-DX)
A unique module, src/internal/agent-dx.ts, calculates a scorecard for the CLI's compatibility with LLM-based agents. It evaluates dimensions such as machineReadableOutput, rawPayloadInput, and contextWindowDiscipline (the ability to filter fields to save tokens). Sources: src/internal/agent-dx.ts:35-80
Key Agent-DX Dimensions
| Dimension | Requirement |
|---|---|
fieldSelection | Supports --fields to limit response size. |
dryRun | Every mutating command supports --dry-run for plan verification. |
streaming | Large lists support NDJSON to prevent memory/context overflow. |
rawJsonInput | Mutating commands accept structured JSON for deterministic writes. |
Sources: src/internal/agent-dx.ts:40-100, src/internal/metadata.ts:50-80
Summary
The putio-cli architecture is a specialized implementation of a CLI where the human user is considered a secondary consumer to the automated agent. By leveraging Effect's functional constraints, it provides a highly predictable execution environment, rigorous security through automatic redaction, and a comprehensive introspection system that allows agents to discover and operate the API with minimal ambient knowledge. Sources: CLAUDE.md, README.md, src/internal/agent-dx.ts