Skip to content

Commit 12020d9

Browse files
gmoonclaude
andcommitted
Add --compact flag for minimal JSON catalog output
lattice --json --compact outputs only command names and parameter specs (name, type, required, description) — no examples, descriptions, concepts, or workflows. ~50% smaller payload for LLMs that already know the domain. Bump version to v0.1.22 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b9fc228 commit 12020d9

3 files changed

Lines changed: 98 additions & 13 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "lattice"
3-
version = "0.1.21"
3+
version = "0.1.22"
44
edition = "2024"
55
description = "A knowledge coordination protocol for human-agent collaboration"
66
repository = "https://github.com/forkzero/lattice"

src/main.rs

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ struct Cli {
3131
#[arg(long)]
3232
json: bool,
3333

34+
/// With --json: output compact schema only (command signatures, no examples/descriptions)
35+
#[arg(long, requires = "json")]
36+
compact: bool,
37+
3438
#[command(subcommand)]
3539
command: Option<Commands>,
3640
}
@@ -449,6 +453,10 @@ enum Commands {
449453
#[arg(long)]
450454
json: bool,
451455

456+
/// With --json: output compact schema only (command signatures, no examples/descriptions)
457+
#[arg(long, requires = "json")]
458+
compact: bool,
459+
452460
/// Topic to show: concepts, workflows (omit for command list)
453461
topic: Option<String>,
454462
},
@@ -1560,13 +1568,15 @@ fn build_command_catalog() -> serde_json::Value {
15601568
"description": "Show available commands, or a specific topic (concepts, workflows). Use --json for the full machine-readable catalog (this output).",
15611569
"parameters": [
15621570
param("topic", "string", false, "Help topic: concepts, workflows (omit for command list)"),
1563-
param("--json", "bool", false, "Output as structured JSON for agent consumption")
1571+
param("--json", "bool", false, "Output as structured JSON for agent consumption"),
1572+
param("--compact", "bool", false, "With --json: output only command signatures (name + parameters), no examples/descriptions/concepts")
15641573
],
15651574
"examples": [
15661575
{"command": "lattice help", "explanation": "Show human-readable command list"},
15671576
{"command": "lattice help concepts", "explanation": "Learn about node types, edge semantics, versioning, and ID conventions"},
15681577
{"command": "lattice help workflows", "explanation": "See common task-oriented command sequences"},
1569-
{"command": "lattice help --json", "explanation": "Output the full command catalog as JSON for LLM consumption"}
1578+
{"command": "lattice help --json", "explanation": "Output the full command catalog as JSON for LLM consumption"},
1579+
{"command": "lattice help --json --compact", "explanation": "Output compact schema — just command names and parameter specs (~50% smaller)"}
15701580
],
15711581
"related_commands": []
15721582
}
@@ -1578,6 +1588,8 @@ fn build_command_catalog() -> serde_json::Value {
15781588
},
15791589
"global_flags": {
15801590
"--format json": "Available on all read and write commands for structured output",
1591+
"--json": "Output machine-readable command catalog (top-level flag)",
1592+
"--json --compact": "Output compact command catalog — signatures only, no examples/descriptions",
15811593
"--help": "Show help for any command",
15821594
"--version": "Show version"
15831595
}
@@ -1611,15 +1623,40 @@ fn command_to_name(cmd: &Commands) -> &'static str {
16111623
}
16121624
}
16131625

1626+
/// Strip a full catalog down to just command signatures (name + parameters).
1627+
fn compact_catalog(catalog: &serde_json::Value) -> serde_json::Value {
1628+
let commands = catalog["commands"]
1629+
.as_array()
1630+
.map(|cmds| {
1631+
cmds.iter()
1632+
.map(|cmd| {
1633+
json!({
1634+
"name": cmd["name"],
1635+
"parameters": cmd["parameters"],
1636+
})
1637+
})
1638+
.collect::<Vec<_>>()
1639+
})
1640+
.unwrap_or_default();
1641+
1642+
json!({
1643+
"version": catalog["version"],
1644+
"commands": commands,
1645+
})
1646+
}
1647+
16141648
fn main() {
16151649
let cli = Cli::parse();
16161650

16171651
// Handle top-level --json flag (outputs command catalog)
16181652
if cli.json {
1619-
println!(
1620-
"{}",
1621-
serde_json::to_string_pretty(&build_command_catalog()).unwrap()
1622-
);
1653+
let catalog = build_command_catalog();
1654+
let output = if cli.compact {
1655+
compact_catalog(&catalog)
1656+
} else {
1657+
catalog
1658+
};
1659+
println!("{}", serde_json::to_string_pretty(&output).unwrap());
16231660
return;
16241661
}
16251662

@@ -3666,12 +3703,19 @@ fn run_command(command: Commands) {
36663703
}
36673704
}
36683705

3669-
Commands::Help { json, topic } => {
3706+
Commands::Help {
3707+
json,
3708+
compact,
3709+
topic,
3710+
} => {
36703711
if json {
3671-
println!(
3672-
"{}",
3673-
serde_json::to_string_pretty(&build_command_catalog()).unwrap()
3674-
);
3712+
let catalog = build_command_catalog();
3713+
let output = if compact {
3714+
compact_catalog(&catalog)
3715+
} else {
3716+
catalog
3717+
};
3718+
println!("{}", serde_json::to_string_pretty(&output).unwrap());
36753719
} else if let Some(ref t) = topic {
36763720
let catalog = build_command_catalog();
36773721
match t.as_str() {
@@ -4041,4 +4085,45 @@ mod tests {
40414085
"Catalog should have a top-level description"
40424086
);
40434087
}
4088+
4089+
#[test]
4090+
fn test_compact_catalog_has_only_signatures() {
4091+
let full = build_command_catalog();
4092+
let compact = compact_catalog(&full);
4093+
4094+
// Has version and commands
4095+
assert!(compact["version"].is_string());
4096+
let commands = compact["commands"].as_array().unwrap();
4097+
assert!(!commands.is_empty());
4098+
4099+
// Each command has only name and parameters
4100+
for cmd in commands {
4101+
assert!(cmd["name"].is_string());
4102+
assert!(cmd["parameters"].is_array());
4103+
// Should NOT have description, examples, related_commands, output_schema_hint
4104+
assert!(
4105+
cmd["description"].is_null(),
4106+
"compact should omit description"
4107+
);
4108+
assert!(cmd["examples"].is_null(), "compact should omit examples");
4109+
assert!(
4110+
cmd["related_commands"].is_null(),
4111+
"compact should omit related_commands"
4112+
);
4113+
assert!(
4114+
cmd["output_schema_hint"].is_null(),
4115+
"compact should omit output_schema_hint"
4116+
);
4117+
}
4118+
4119+
// Should NOT have concepts, workflows, global_flags
4120+
assert!(
4121+
compact["concepts"].is_null(),
4122+
"compact should omit concepts"
4123+
);
4124+
assert!(
4125+
compact["workflows"].is_null(),
4126+
"compact should omit workflows"
4127+
);
4128+
}
40444129
}

0 commit comments

Comments
 (0)