chore(git): ignore custom documentation files

Add AGENTS.md and CLAUDE.md to .gitignore to exclude project-specific documentation files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-01 18:49:44 +01:00
parent 7f39bf1eca
commit d21945dbc0
9 changed files with 7 additions and 3 deletions

105
crates/app/cli/src/main.rs Normal file
View File

@@ -0,0 +1,105 @@
use clap::Parser;
use color_eyre::eyre::Result;
use config_agent::load_settings;
use futures_util::TryStreamExt;
use llm_ollama::{OllamaClient, OllamaOptions, types::ChatMessage};
use std::io::{self, Write};
#[derive(clap::Subcommand, Debug)]
enum Cmd {
Read {path: String},
Glob {pattern: String},
Grep {root: String, pattern: String},
}
#[derive(Parser, Debug)]
#[command(name = "code", version)]
struct Args {
#[arg(long)]
ollama_url: Option<String>,
#[arg(long)]
model: Option<String>,
#[arg(long)]
api_key: Option<String>,
#[arg(long)]
print: bool,
#[arg()]
prompt: Vec<String>,
#[command(subcommand)]
cmd: Option<Cmd>,
}
#[tokio::main]
async fn main() -> Result<()> {
color_eyre::install()?;
let args = Args::parse();
let settings = load_settings(None).unwrap_or_default();
if let Some(cmd) = args.cmd {
match cmd {
Cmd::Read { path } => {
let s = tools_fs::read_file(&path)?;
println!("{}", s);
return Ok(());
}
Cmd::Glob { pattern } => {
for p in tools_fs::glob_list(&pattern)? {
println!("{}", p);
}
return Ok(());
}
Cmd::Grep { root, pattern } => {
for (path, line_number, text) in tools_fs::grep(&root, &pattern)? {
println!("{path}:{line_number}:{text}")
}
return Ok(());
}
}
}
let prompt = if args.prompt.is_empty() {
"Say hello".to_string()
} else {
args.prompt.join(" ")
};
let model = args.model.unwrap_or(settings.model);
let api_key = args.api_key.or(settings.api_key);
// Use Ollama Cloud when model has "-cloud" suffix AND API key is set
let use_cloud = model.ends_with("-cloud") && api_key.is_some();
let client = if use_cloud {
OllamaClient::with_cloud().with_api_key(api_key.unwrap())
} else {
let base_url = args.ollama_url.unwrap_or(settings.ollama_url);
let mut client = OllamaClient::new(base_url);
if let Some(key) = api_key {
client = client.with_api_key(key);
}
client
};
let opts = OllamaOptions {
model,
stream: true,
};
let msgs = vec![ChatMessage {
role: "user".into(),
content: prompt,
}];
let mut stream = client.chat_stream(&msgs, &opts).await?;
while let Some(chunk) = stream.try_next().await? {
if let Some(m) = chunk.message {
if let Some(c) = m.content {
print!("{c}");
io::stdout().flush()?;
}
}
if matches!(chunk.done, Some(true)) {
break;
}
}
println!(); // Newline after response
Ok(())
}