InkdownInkdown
Start writing

Claude-Code

62 filesยท4 subfolders

Shared Workspace

Claude-Code
codex

0600_headless_sdk_and_print_mode_request_flow_end_to_end

Shared from "Claude-Code" on Inkdown

Critical Flow: Headless SDK Print Mode Request To Streamed Output

This flow matters whenever the client is embedded in another product, used as a subprocess, or expected to return structured output instead of rendering the REPL.

Flow Overview

  1. main.tsx identifies non-interactive mode from flags or non-TTY output.
  2. Shared init and setup still run, but trust is treated as implicit and output is structured instead of Ink-rendered.
  3. cli/print.ts becomes the top-level session runner.
  4. A headless store is created with app state, MCP state, permission context, agents, and tools.
  5. QueryEngine.ts owns the conversation across turns.
0000_start_here_index_and_recommended_reading_order.md
0100_project_overview_tech_stack_runtime_modes_and_folder_map.md
0200_startup_flow_entry_points_and_cold_start_sequence.md
0300_codebase_modules_layers_state_models_and_schemas.md
0400_system_architecture_and_design_rationale.md
0500_interactive_repl_request_flow_end_to_end.md
0600_headless_sdk_and_print_mode_request_flow_end_to_end.md
0700_mcp_integration_connection_and_tool_call_flow.md
0800_external_services_sdks_storage_and_local_dependencies.md
0900_environment_variables_settings_feature_flags_and_failure_modes.md
1000_non_obvious_patterns_gotchas_and_debugging_traps.md
1100_full_codebase_file_inventory_grouped_by_directory.md
kimi
00-overview.md
01-entrypoints.md
02-state-management.md
03-query-system.md
04-tools-system.md
05-tasks-system.md
06-ui-components.md
07-bridge-remote.md
08-services.md
09-skills-plugins.md
10-commands.md
11-testing-architecture.md
12-permission-system.md
13-build-system.md
14-ink-internals.md
15-git-internals.md
16-context-compaction.md
17-vim-mode.md
18-mailbox-notifications.md
19-session-persistence.md
20-hooks-system.md
21-error-recovery.md
README.md
qwen
00-overview.md
01-entry-points.md
02-query-engine.md
03-tools-and-tasks.md
04-commands-and-skills.md
05-state-management.md
06-ink-rendering.md
07-bridge-remote.md
08-mcp-services.md
09-services-overview.md
10-multi-agent.md
11-system-prompt-constants.md
12-tool-interface.md
13-memory-system.md
14-buddy-companion.md
15-keybindings.md
16-stop-hooks.md
17-vim-mode.md
18-upstreamproxy.md
19-cost-tracking-history.md
20-contexts-styles-onboarding.md
21-hooks.md
22-screens.md
tweets-explain
claude-code-memory-analysis.md
compact
memory-system
agentic-architecture
  • StructuredIO and RemoteIO stream messages, control events, permission requests, and session-state changes outward.
  • Every Hop

    1. Branching into headless mode
    • main.tsx computes isNonInteractive early so auth, telemetry, and trust behavior can be configured correctly.
    • Full environment variables are applied once setup() completes because there is no trust dialog in this mode.
    2. Headless store creation
    • main.tsx builds a headless AppState via state/AppStateStore.ts and state/store.ts.
    • The store is seeded with tools, permission context, agent settings, MCP client state, and session persistence flags.
    • MCP servers are connected and their tools, commands, and resources are pushed into the store incrementally.
    3. cli/print.ts becomes the session orchestrator
    • runHeadless() in cli/print.ts owns stdout protocol formatting, command queue management, session-state notifications, replay and resume support, remote transport cases, and structured JSON or stream-json output.
    • It uses StructuredIO for framing and SDK control protocol and RemoteIO for remote transport cases.
    • utils/sessionState.ts surfaces mode, permission, and session metadata changes outward.
    4. Query engine owns the conversation
    • QueryEngine.ts wraps the lower-level query() generator and keeps mutable conversation state across turns.
    • It stores mutable message history, abort controller, accumulated usage, permission denials, file-state cache, discovered skills, and loaded nested memory paths.
    • Why this class exists: headless callers often need several turns in one process without mounting the REPL.
    5. User input becomes query input
    • QueryEngine.submitMessage() still runs processUserInput() from utils/processUserInput/processUserInput.ts.
    • That means headless mode still gets slash-command parsing, hook execution, attachment handling, and model or tool overrides.
    6. The turn uses the same core query and tool machinery
    • QueryEngine calls query() from query.ts.
    • query.ts calls services/api/claude.ts.
    • Tool execution still flows through services/tools/*.
    • Permission checks still use the same permission context and baseline decision helpers.
    • The difference is output handling: instead of updating a visible REPL, messages and state changes are serialized to stdout and control channels.
    7. Control messages and permission prompts
    • SDK and stream-json mode can emit and consume SDKControl* request and response messages defined under entrypoints/sdk/*.
    • Permission prompts can be delegated to a permission prompt tool rather than a TUI dialog.
    • MCP elicitations can also round-trip through structured control flows.
    8. Session persistence and resume
    • cli/print.ts and utils/sessionStorage.ts cooperate to resume, fork, or rewind sessions in headless mode.
    • Headless mode also restores remote session metadata, agent selections, attribution snapshots, and file-history caches when resuming.

    Where Headless-Only Bugs Usually Hide

    • Output protocol formatting or stuck streams: cli/print.ts and cli/structuredIO.ts.
    • Session-state or control-message mismatches: entrypoints/sdk/controlTypes.ts and utils/sessionState.ts.
    • Differences from REPL behavior: QueryEngine.ts and the headless branches inside main.tsx.
    • Permission prompt tool issues: utils/permissions/PermissionPromptToolResultSchema.ts plus the headless permission handling in cli/print.ts.