Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 42 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,50 @@

[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/13620/badge)](https://www.bestpractices.dev/projects/13620)

Rust CLI for TeaQL code generation workflows.
Rust CLI for evaluating TeaQL semantic models, generating language-native
libraries and workspaces, and discovering generated APIs through model-aware
Assist.

## Commands

```bash
cargo-teaql <target-service> <model-path>

# Examples:
cargo-teaql java-app-console ./model
cargo-teaql rust-lib-core ./model
cargo-teaql services
cargo-teaql version
cargo-teaql show-config
cargo-teaql config
cargo-teaql install-links
# Discover the targets currently offered by the service.
cargo teaql services

# Evaluate before generation.
cargo teaql evaluate --input models/

# Generate a library or runnable workspace.
cargo teaql rust-lib-core --input models/ --output build/
cargo teaql java-app-console --input models/ --output build/

# Discover the generated API progressively.
cargo teaql rust-assist-query/school --input models/
cargo teaql rust-assist-query/school.established_date --input models/

# Local maintenance commands.
cargo teaql show-config
cargo teaql config
cargo teaql ping
cargo teaql check --tests
```

The CLI supports dynamic command routing. If the target service is not a built-in command, the CLI will automatically forward the request to the backend. If an input path is provided, it acts as a code generation target (e.g. `java-app-console`). If no input path is provided, it acts as a general GET request (e.g. `services`).
Generation and Assist targets are provided dynamically by the TeaQL service,
so the fixed `Commands` list in `--help` is not their complete inventory. Run
`cargo teaql services` to discover the current targets and `cargo teaql version`
to inspect their versions.

Use `--input` for the KSML model file or directory. A dynamic target with model
input performs evaluation, generation, or Assist; a remote information target
such as `services` or `version` performs a GET request.

If no arguments are provided at all, it automatically defaults to `cargo-teaql services`.
If no command is provided, the CLI defaults to `cargo teaql services`.
`cargo-teaql` is an equivalent direct invocation.

### CLI flags

```bash
cargo-teaql java-app-console <model-path> \
cargo teaql java-app-console --input models/ \
--endpoint-prefix https://api.teaql.io/latest/ \
--api-key ******** \
--output ./build \
Expand All @@ -43,7 +62,7 @@ However, if a directory is provided but it **does not contain a `main.xml`**, th
If you create symlink aliases to the same binary, these names also work:

```bash
cargo teaql-java-app-console <model-path>
cargo teaql-java-app-console --input models/
cargo teaql-services
cargo teaql-version
cargo teaql-show-config
Expand All @@ -62,8 +81,11 @@ You can also target a custom directory with `cargo-teaql install-links --dir /so

TeaQL provides specialized assist commands designed to help AI coding agents (and developers) quickly generate safe, compliant boilerplate templates for various business scenarios.

The command format is:
`cargo-teaql <lang>-assist-<action>/<entity> --input <model_file>`
The entity-level command format is:
`cargo teaql <lang>-assist-<action>/<entity> --input <model>`

For field-specific help, append the KSML field name:
`cargo teaql <lang>-assist-<action>/<entity>.<field> --input <model>`

Currently supported `rust-assist-*` targets:
- `rust-assist-query`: Generate a comprehensive query template with field selections and mandatory `.purpose()`/`.comment()` cascades.
Expand All @@ -77,8 +99,9 @@ Currently supported `rust-assist-*` targets:

**Example Usage:**
```bash
cargo-teaql rust-assist-query/book --input modeling/bookstore.xml
cargo-teaql java-assist-create/customer --input modeling/bookstore.xml
cargo teaql rust-assist-query/book --input modeling/bookstore.xml
cargo teaql rust-assist-query/book.published_at --input modeling/bookstore.xml
cargo teaql java-assist-create/customer --input modeling/bookstore.xml
```

## Configuration
Expand Down
70 changes: 65 additions & 5 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,72 @@ use std::path::PathBuf;

use clap::{Args, Parser, Subcommand};

const ROOT_USAGE: &str = "cargo teaql [OPTIONS] [COMMAND]\n cargo teaql [OPTIONS] <TARGET> --input <MODEL> [--output <DIR>]\n cargo teaql [OPTIONS] <LANG>-assist-<ACTION>/<ENTITY>[.<FIELD>] --input <MODEL>";

const ROOT_EXAMPLES: &str = r#"REMOTE WORKFLOWS (dynamic commands):
Discover the targets and versions currently provided by the TeaQL service:
cargo teaql services
cargo teaql version

Evaluate a KSML model before generation:
cargo teaql evaluate --input models/

Generate a typed library or runnable workspace:
cargo teaql rust-lib-core --input models/ --output build/
cargo teaql typescript-app-console --input models/ --output build/

Ask model-aware Assist about an entity or one field:
cargo teaql rust-assist-query/school --input models/
cargo teaql rust-assist-query/school.established_date --input models/

Run `cargo teaql services` for the current remote target inventory.
With no command, TeaQL runs `services`. `cargo-teaql` is an equivalent invocation."#;

#[derive(Debug, Parser)]
#[command(
name = "teaql",
version,
about = "TeaQL toolchain",
about = "Evaluate TeaQL models, generate typed applications, and discover model-aware APIs",
long_about = "TeaQL turns a KSML semantic model into evaluated, language-native libraries and runnable workspaces. It also provides progressive, model-aware Assist for discovering the generated API without reading generated source.",
override_usage = ROOT_USAGE,
after_help = ROOT_EXAMPLES,
disable_help_subcommand = true
)]
pub struct Cli {
/// Workspace directory used by local commands and relative output paths.
#[arg(long, global = true, default_value = ".")]
pub cwd: PathBuf,

/// Show configuration sources and request progress.
#[arg(long, short, global = true)]
pub verbose: bool,

/// Show additional diagnostic details.
#[arg(long, global = true)]
pub debug: bool,

/// KSML model file or directory; multi-file models use the directory containing main.xml.
#[arg(long, global = true)]
pub input: Option<PathBuf>,

/// TeaQL service endpoint prefix, for example https://api.teaql.io/latest/.
#[arg(long, global = true)]
pub endpoint_prefix: Option<String>,

/// Deprecated alias for --endpoint-prefix.
#[arg(long, global = true)]
#[arg(hide = true)]
pub service_url: Option<String>,

/// TeaQL API key; the built-in free-tier key is used by default.
#[arg(long, global = true)]
pub api_key: Option<String>,

/// Generated output directory; relative paths are resolved from --cwd.
#[arg(long, global = true)]
pub output: Option<PathBuf>,

/// Remote request timeout in seconds.
#[arg(long, global = true)]
pub timeout_seconds: Option<u64>,

Expand All @@ -44,13 +78,13 @@ pub struct Cli {

#[derive(Debug, Subcommand)]
pub enum Commands {
/// Show effective local config.
/// Show the saved workspace configuration and its file path.
ShowConfig,
/// Configure TeaQL in the current workspace.
/// Interactively configure TeaQL for the current workspace.
Config,
/// Ping the TeaQL service.
/// Verify service connectivity with a built-in model round trip.
Ping(ServiceArgs),
/// Install symlink aliases for cargo-style command names.
/// Install executable aliases used by cargo-style invocation.
InstallLinks(InstallLinksArgs),
/// Run cargo check and map any compiler errors back to the source KSML (XML) file.
Check(CheckArgs),
Expand Down Expand Up @@ -167,3 +201,29 @@ pub struct InstallLinksArgs {
#[arg(long)]
pub force: bool,
}

#[cfg(test)]
mod tests {
use clap::CommandFactory;

use super::Cli;

#[test]
fn root_help_exposes_primary_workflows() {
let help = Cli::command().render_long_help().to_string();

assert!(help.contains("cargo teaql evaluate --input models/"));
assert!(help.contains("cargo teaql rust-lib-core --input models/"));
assert!(help.contains("rust-assist-query/school.established_date"));
assert!(help.contains("cargo teaql services"));
}

#[test]
fn root_help_explains_global_options_without_deprecated_alias() {
let help = Cli::command().render_long_help().to_string();

assert!(help.contains("KSML model file or directory"));
assert!(help.contains("relative paths are resolved from --cwd"));
assert!(!help.contains("--service-url"));
}
}