Skip to content

Commit 919493a

Browse files
committed
Add built-in docs subcommand
1 parent c3b8086 commit 919493a

6 files changed

Lines changed: 73 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ All notable changes to `devloop` will be recorded in this file.
1414
`devloop` without polling.
1515
- Added dedicated security documentation for external events and the
1616
push-versus-polling tradeoffs in [`docs/security.md`](docs/security.md).
17+
- Added `devloop docs <topic>` so the configuration, behavior, and
18+
security references can be read directly from the CLI without
19+
duplicating the source material.
1720

1821
### Changed
1922
- Moved workflow progression into a pure state/effect core so ordered

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ The tool will:
6565
* watch configured paths
6666
* execute workflows on change
6767

68+
Built-in reference docs are also available from the CLI:
69+
70+
```bash
71+
devloop docs config
72+
devloop docs behavior
73+
devloop docs security
74+
```
75+
6876
## Design
6977

7078
The tool has three layers:

docs/behavior.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
This document describes how `devloop` behaves at runtime beyond the
44
schema in [`configuration.md`](configuration.md).
55

6+
This reference is also available in the CLI with:
7+
8+
```bash
9+
devloop docs behavior
10+
```
11+
612
## Core model
713

814
`devloop` is moving toward a pure core with an imperative shell.

docs/configuration.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
`devloop` is configured with a TOML file, typically `devloop.toml` in
44
the client repository root.
55

6+
This reference is also available in the CLI with:
7+
8+
```bash
9+
devloop docs config
10+
```
11+
612
## Top-level keys
713

814
```toml

docs/security.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
This document describes the trust model and security tradeoffs for
44
`devloop` features that accept input from outside the core watch loop.
55

6+
This reference is also available in the CLI with:
7+
8+
```bash
9+
devloop docs security
10+
```
11+
612
## Threat model
713

814
`devloop` supervises local processes, runs hooks, persists session

src/main.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod state;
99
use std::path::PathBuf;
1010

1111
use anyhow::{Result, anyhow};
12-
use clap::{Parser, Subcommand};
12+
use clap::{Parser, Subcommand, ValueEnum};
1313
use tracing::{Event, Subscriber};
1414
use tracing_subscriber::EnvFilter;
1515
use tracing_subscriber::fmt::FmtContext;
@@ -47,6 +47,18 @@ enum Command {
4747
#[arg(long)]
4848
config: Option<PathBuf>,
4949
},
50+
/// Print built-in reference documentation.
51+
Docs {
52+
#[arg(value_enum)]
53+
topic: DocsTopic,
54+
},
55+
}
56+
57+
#[derive(Debug, Clone, Copy, ValueEnum)]
58+
enum DocsTopic {
59+
Config,
60+
Behavior,
61+
Security,
5062
}
5163

5264
#[tokio::main]
@@ -70,6 +82,9 @@ async fn main() -> Result<()> {
7082
config.validate()?;
7183
Engine::new(config).run().await?;
7284
}
85+
Command::Docs { topic } => {
86+
print!("{}", docs_text(topic));
87+
}
7388
}
7489
Ok(())
7590
}
@@ -128,12 +143,21 @@ fn resolve_config_path(config: Option<PathBuf>) -> Result<PathBuf> {
128143
}
129144
}
130145

146+
fn docs_text(topic: DocsTopic) -> &'static str {
147+
match topic {
148+
DocsTopic::Config => include_str!("../docs/configuration.md"),
149+
DocsTopic::Behavior => include_str!("../docs/behavior.md"),
150+
DocsTopic::Security => include_str!("../docs/security.md"),
151+
}
152+
}
153+
131154
#[cfg(test)]
132155
mod tests {
133-
use super::{default_rust_log, format_tracing_prefix};
156+
use super::{Cli, DocsTopic, default_rust_log, docs_text, format_tracing_prefix};
134157
use crate::output::{
135158
format_output_prefix, normalize_internal_log_label, normalize_source_label,
136159
};
160+
use clap::Parser;
137161
use std::sync::{Mutex, OnceLock};
138162

139163
fn rust_log_lock() -> &'static Mutex<()> {
@@ -198,4 +222,22 @@ mod tests {
198222
assert!(rendered.starts_with("\u{1b}[1;"));
199223
assert!(rendered.ends_with(" "));
200224
}
225+
226+
#[test]
227+
fn docs_text_uses_embedded_configuration_reference() {
228+
let rendered = docs_text(DocsTopic::Config);
229+
230+
assert!(rendered.starts_with("# Configuration Reference"));
231+
assert!(rendered.contains("startup_workflows"));
232+
}
233+
234+
#[test]
235+
fn cli_parses_docs_subcommand() {
236+
let cli = Cli::try_parse_from(["devloop", "docs", "security"]).expect("parse cli");
237+
238+
match cli.command {
239+
super::Command::Docs { topic } => assert!(matches!(topic, DocsTopic::Security)),
240+
_ => panic!("expected docs subcommand"),
241+
}
242+
}
201243
}

0 commit comments

Comments
 (0)