Skip to content

Commit 214890c

Browse files
committed
Updated docs
1 parent 2c27c63 commit 214890c

5 files changed

Lines changed: 204 additions & 5 deletions

File tree

dirs_asked_architecture.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

docs/ARCHITECTURE_FILE.md

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
# ARCHITECTURE.md
2+
3+
zerostack supports an optional `ARCHITECTURE.md` file that gives both the main
4+
agent and exploration subagents high-level design context about your project.
5+
6+
## What It Does
7+
8+
When `ARCHITECTURE.md` files exist (at the project root and/or in parent
9+
directories), their content is appended to the agent's system prompt preamble
10+
— right after `AGENTS.md` context and before the custom prompt. This means
11+
every LLM call carries awareness of your project's architecture.
12+
13+
**All subagents also receive the same architecture context**, so they can
14+
explore the codebase with an understanding of the overall design.
15+
16+
## Why Use It
17+
18+
### For the Agent
19+
20+
Without `ARCHITECTURE.md`, an agent exploring a large codebase starts with
21+
zero architectural knowledge. It reads `AGENTS.md` for conventions, then
22+
begins probing files one by one. This works but costs tokens and turns as
23+
the agent builds a mental model from scratch.
24+
25+
With `ARCHITECTURE.md`, the agent enters the conversation already knowing:
26+
- How the project is organized (directory layout, module responsibilities)
27+
- Key types, traits, and data structures
28+
- Where control flow and data flow live
29+
- Design decisions and constraints
30+
- External dependencies and their roles
31+
- Entry points and how things boot
32+
33+
This front-loads understanding, reducing the number of read probes needed and
34+
making the agent's first responses more accurate.
35+
36+
### For the User
37+
38+
- **Consistency across sessions** — the agent stays aligned with your design
39+
intent across different conversations
40+
- **Better subagent delegation** — when using the `task` tool, subagents
41+
understand the architecture without querying the main agent
42+
- **Onboarding** — new contributors (human or AI) get a structured overview
43+
- **Living documentation** — the agent can (and is prompted to) update
44+
`ARCHITECTURE.md` when significant changes are made
45+
46+
## Discovery and Loading
47+
48+
zerostack loads `ARCHITECTURE.md` files using the same recursive upward search
49+
as `AGENTS.md`:
50+
51+
1. **Global**: `~/.local/share/zerostack/agent/ARCHITECTURE.md` (XDG data dir)
52+
2. **Project**: `ARCHITECTURE.md` in the current working directory and all
53+
parent directories up to the filesystem root
54+
55+
Files from all levels are concatenated, with source-path headers indicating
56+
where each block came from. This lets you define organization-wide conventions
57+
in the global file while having project-specific architecture in each repo.
58+
59+
At startup, if no `ARCHITECTURE.md` is found anywhere in the directory tree,
60+
zerostack offers to create one:
61+
62+
```
63+
No ARCHITECTURE.md found in /home/you/project. Create one? [y/N]
64+
```
65+
66+
If you answer yes, a template is written to the project root. The template
67+
includes sections for directory layout, key types/traits, control flow, data
68+
flow, design decisions, dependencies, and entry points.
69+
70+
When you accept and the template is created, zerostack automatically injects
71+
a system message instructing the agent to explore the codebase and populate
72+
the file with a thorough architectural overview.
73+
74+
### Template Contents
75+
76+
The generated template contains:
77+
78+
```markdown
79+
# Architecture Overview
80+
81+
## Directory Layout
82+
<!-- Describe the top-level directory structure and responsibilities -->
83+
84+
## Key Types / Traits
85+
<!-- List the primary data structures, traits, and their relationships -->
86+
87+
## Control Flow
88+
<!-- How does execution flow through the system? -->
89+
90+
## Data Flow
91+
<!-- How does data move through the system? -->
92+
93+
## Design Decisions
94+
<!-- Notable architectural choices and tradeoffs -->
95+
96+
## Dependencies
97+
<!-- Key external dependencies and their roles -->
98+
99+
## Entry Points
100+
<!-- How does the application start and accept input? -->
101+
```
102+
103+
## Disabling
104+
105+
Pass `--no-context-files` (or `-n`) to suppress loading of both `AGENTS.md`
106+
and `ARCHITECTURE.md`. You can also set `no_context_files = true` in your
107+
config file.
108+
109+
## How It Integrates
110+
111+
| Layer | Behavior |
112+
|---|---|
113+
| **System prompt** | Architecture content appended after `AGENTS.md`, before custom prompt |
114+
| **Subagents** | Each subagent receives the architecture context in its preamble |
115+
| **`task` tool** | Exploration subagents instructed to read `ARCHITECTURE.md` first |
116+
| **TUI status** | Displays `loaded ARCHITECTURE.md` when architecture content exists |
117+
| **Prompts** | Built-in prompts reference architecture-aware workflows |
118+
119+
## Writing a Good ARCHITECTURE.md
120+
121+
A well-written `ARCHITECTURE.md` should be **concise** (aim for 200-500 words
122+
for small projects, 500-2000 for larger ones) and **actionable** — think of it
123+
as a cheat sheet the agent can reference when making decisions. Avoid
124+
reproducing code; focus on structure, relationships, and rationale.
125+
126+
### Recommended Sections
127+
128+
1. **Directory Layout** — one-line summaries of each top-level directory
129+
2. **Key Types/Traits** — the 5-10 most important data structures
130+
3. **Control Flow** — request lifecycle, main loops, async boundaries
131+
4. **Data Flow** — how data enters, transforms, and exits the system
132+
5. **Design Decisions** — "why X instead of Y" for critical choices
133+
6. **Dependencies** — key libraries and what they're used for
134+
7. **Entry Points** — binary entry, API handlers, CLI parsing
135+
136+
### Example
137+
138+
```markdown
139+
# Architecture Overview
140+
141+
## Directory Layout
142+
- `src/agent/` — Agent building, prompt construction, tool execution
143+
- `src/ui/` — TUI event loop, renderer, input handling, slash commands
144+
- `src/provider/` — LLM provider abstraction (OpenAI, Anthropic, etc.)
145+
- `src/config/` — Config parsing, validation, resolution
146+
- `src/extras/` — Optional features gated behind Cargo features
147+
148+
## Key Types
149+
- `AnyAgent` / `AnyClient` — type-erased agent and LLM client
150+
- `Session` — conversation state, messages, tokens, compactions
151+
- `ContextFiles` — loaded AGENTS.md, ARCHITECTURE.md, prompts, themes
152+
153+
## Control Flow
154+
1. CLI args parsed → config loaded → context files discovered
155+
2. Agent built with system prompt (agents + architecture + prompt)
156+
3. TUI event loop: user input → agent runner → streaming events → renderer
157+
4. Slash commands intercept input starting with `/`
158+
159+
## Data Flow
160+
- User input → InputEditor → event loop → agent.spawn_runner()
161+
- Runner streams AgentEvent (Token, Reasoning, ToolCall, ToolResult, Done)
162+
- Events rendered incrementally via Renderer::write_line()
163+
164+
## Design Decisions
165+
- Type-erased client/agent via trait objects for provider flexibility
166+
- Tokio for async I/O; crossterm for TUI
167+
- mpsc channels for agent events, user events, and permission requests
168+
169+
## Dependencies
170+
- `rig` / `rig-core` — LLM client abstraction
171+
- `crossterm` — cross-platform terminal manipulation
172+
- `tokio` — async runtime
173+
- `serde` / `toml` — config parsing
174+
175+
## Entry Points
176+
- `main.rs` — binary entry, CLI parsing, session init
177+
- `run_interactive()` — TUI main loop
178+
```
179+
180+
## Comparison with AGENTS.md
181+
182+
| Aspect | AGENTS.md | ARCHITECTURE.md |
183+
|---|---|---|
184+
| **Purpose** | Coding conventions, instructions, project-specific procedures | High-level design: structure, relationships, rationale |
185+
| **Scope** | "How to work in this codebase" | "How this codebase is built" |
186+
| **Update frequency** | Rare (conventions change slowly) | With significant refactors or new modules |
187+
| **Typical length** | Short to medium | Medium (200-2000 words) |
188+
| **Loaded together** | Yes, both concatenated into system prompt preamble | |
189+
190+
Both files complement each other: `AGENTS.md` tells the agent how to operate;
191+
`ARCHITECTURE.md` tells it what it's operating on.

docs/CONFIG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ Accepted top-level keys:
149149
| `keep_recent_tokens` | integer | Approximate recent-token budget kept verbatim during compaction. Default: `20000`. |
150150
| `max_text_file_size` | integer | Maximum allowed file size in bytes for read/write tool operations. Default: `1048576` (1 MB). |
151151
| `compact_enabled` | boolean | Enable automatic conversation compaction. Default: `true`. |
152+
| `always_show_welcome` | boolean | Always show the welcome banner on startup, bypassing the one-shot marker file. Default: `false`. |
152153
| `edit_system` | string | Edit system mode: `"similarity"` (SEARCH/REPLACE with fuzzy matching, default) or `"hashedit"` (CRC-32 tag-based CAS edits). See Edit System Modes below. |
153154
| `custom_providers` | object | Map of provider aliases to `{ "provider_type", "base_url", "api_key_env", "api_style", "headers", "danger_accept_invalid_certs", "timeout_secs" }`. `provider_type` must resolve to a built-in provider type; `api_key_env` is optional. For OpenAI providers, `api_style` selects `"responses"` or `"completions"`, `headers` sets custom HTTP headers (values support `${ENV_VAR}` expansion), and `timeout_secs` overrides the HTTP timeout. `danger_accept_invalid_certs` disables TLS verification. See the OpenAI API styles section below. |
154155
| `permission` | object | Permission rules using glob patterns; see the permission config notes below. |

src/config/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub struct Config {
4545
#[serde(skip_serializing_if = "Option::is_none")]
4646
pub compact_enabled: Option<bool>,
4747
#[serde(skip_serializing_if = "Option::is_none")]
48+
pub always_show_welcome: Option<bool>,
49+
#[serde(skip_serializing_if = "Option::is_none")]
4850
pub custom_providers: Option<HashMap<String, types::CustomProviderConfig>>,
4951
#[serde(skip_serializing_if = "Option::is_none")]
5052
pub permission: Option<serde_json::Value>,
@@ -141,6 +143,10 @@ impl Config {
141143
self.compact_enabled.unwrap_or(true)
142144
}
143145

146+
pub fn resolve_always_show_welcome(&self) -> bool {
147+
self.always_show_welcome.unwrap_or(false)
148+
}
149+
144150
pub fn build_permission_config(&self) -> PermissionConfigs {
145151
let glob: PermissionConfig = self
146152
.permission

src/ui/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ pub async fn run_interactive(
238238

239239
render_session(&mut renderer, session, cli, cfg, context)?;
240240
let marker_path = crate::session::storage::data_dir().join("shown_welcome_msg");
241-
if !marker_path.exists() {
241+
if cfg.resolve_always_show_welcome() || !marker_path.exists() {
242242
renderer.write_line("──────────────────────────────────────────", Color::Cyan)?;
243243
renderer.write_line(" zerostack Quickstart", Color::Cyan)?;
244244
renderer.write_line("──────────────────────────────────────────", Color::Cyan)?;
@@ -282,10 +282,12 @@ pub async fn run_interactive(
282282
renderer.write_line("", Color::White)?;
283283
renderer.write_line("──────────────────────────────────────────", Color::Cyan)?;
284284
renderer.write_line("", Color::White)?;
285-
if let Some(dir) = marker_path.parent() {
286-
let _ = std::fs::create_dir_all(dir);
285+
if !cfg.resolve_always_show_welcome() {
286+
if let Some(dir) = marker_path.parent() {
287+
let _ = std::fs::create_dir_all(dir);
288+
}
289+
let _ = std::fs::write(&marker_path, "");
287290
}
288-
let _ = std::fs::write(&marker_path, "");
289291
}
290292
refresh_display(
291293
&mut renderer,

0 commit comments

Comments
 (0)