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
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ fgp-workflow = { git = "https://github.com/fast-gateway-protocol/workflow.git" }
# Serialization
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_yaml = "0.9"

# Error handling
anyhow = "1"
Expand All @@ -51,6 +52,12 @@ crossterm = "0.28"
# Async runtime for TUI events
tokio = { version = "1", features = ["sync", "time", "rt-multi-thread"] }

# Date/time
chrono = "0.4"

# Home directory
dirs = "5"

[dev-dependencies]
assert_cmd = "2"
predicates = "3"
Expand Down
144 changes: 144 additions & 0 deletions logs/user_prompt_submit.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,149 @@
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "Create GitHub repos for dashboard and workflow crates"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "test the dashboard locally"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "Create a pull request for the TUI changes and then set a reminder for 10 minutes to check back."
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "check if CI passed on PR 2"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "merge the TUI PR"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "How do I launch the terminal UI?"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "Last login: Wed Jan 14 19:47:20 on ttys023\nwolfgangschoenberger@Wolfgangs-MacBook-Pro fgp % fgp tui\nzsh: command not found: fgp\nwolfgangschoenberger@Wolfgangs-MacBook-Pro fgp % cd cli\nwolfgangschoenberger@Wolfgangs-MacBook-Pro cli % fgp tui\nzsh: command not found: fgp\nwolfgangschoenberger@Wolfgangs-MacBook-Pro cli %\n\n"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "install fgp globally"
},
{
"session_id": "b084daa3-6131-406b-a78c-8246feeb00fe",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/b084daa3-6131-406b-a78c-8246feeb00fe.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "<task-notification>\n<task-id>b0027bc</task-id>\n<output-file>/tmp/claude/-Users-wolfgangschoenberger-Projects-fgp/tasks/b0027bc.output</output-file>\n<status>completed</status>\n<summary>Background command \"Wait and check release workflows\" completed (exit code 0)</summary>\n</task-notification>\nRead the output file to retrieve the result: /tmp/claude/-Users-wolfgangschoenberger-Projects-fgp/tasks/b0027bc.output"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "start a service to test the tui"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "This is what I see. This is what I see. Does this look correct?"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "Okay, I pasted a screenshot of what it actually looks like as well as what I see when I try to start the browser via the TUI."
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "test the tui fix now"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "it works, what should we build next"
},
{
"session_id": "0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/0c6dbfa3-3098-4071-8a4e-c5dd9f1118ae.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "plan",
"hook_event_name": "UserPromptSubmit",
"prompt": "I want to eventually add pretty much all of these (except remote daemons), let's start going through the list - Let's plan out T0 and T1 first. I think we can do that all in one go. Please create a comprehensive plan. Once that's done, we can plan out service metrics and lastly, the plugin registry."
},
{
"session_id": "6be261ac-4a50-4c29-b5e1-a1edb3ce813d",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/6be261ac-4a50-4c29-b5e1-a1edb3ce813d.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "commit the codex detection fix"
},
{
"session_id": "6be261ac-4a50-4c29-b5e1-a1edb3ce813d",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/6be261ac-4a50-4c29-b5e1-a1edb3ce813d.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "plan",
"hook_event_name": "UserPromptSubmit",
"prompt": "what about google's antigravity, as well as the gemini CLI? can we configure those too?"
},
{
"session_id": "c696a6ba-089c-47d9-95c7-3ba087b1e3a7",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/c696a6ba-089c-47d9-95c7-3ba087b1e3a7.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "commit these changes and push"
},
{
"session_id": "c696a6ba-089c-47d9-95c7-3ba087b1e3a7",
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/c696a6ba-089c-47d9-95c7-3ba087b1e3a7.jsonl",
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/cli",
"permission_mode": "bypassPermissions",
"hook_event_name": "UserPromptSubmit",
"prompt": "create a PR for these changes and set a reminder for me to check back in in 10 minutes"
}
]
14 changes: 14 additions & 0 deletions src/commands/agents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ use std::path::Path;
/// Known AI agent configurations.
const AGENT_PATHS: &[(&str, &str, &str)] = &[
("Claude Code", "~/.claude/skills", "SKILL.md files"),
("Codex", "~/.codex/skills", "SKILL.md files"),
(
"Gemini CLI",
"~/.gemini/extensions",
"Extension directories",
),
("Antigravity", "~/.gemini/antigravity", "MCP config"),
("Cursor", "~/.cursor", ".mdc rules"),
("Windsurf", "~/.windsurf", "Workflow files"),
(
Expand All @@ -15,6 +22,13 @@ const AGENT_PATHS: &[(&str, &str, &str)] = &[
"MCP config",
),
("Continue", "~/.continue", "YAML config"),
// Additional AI coding tools
("Aider", "~/.aider.conf.yml", "YAML config"),
("Zed AI", "~/.config/zed", "JSON settings"),
("GitHub Copilot", "~/.config/github-copilot", "JSON config"),
("Sourcegraph Cody", "~/.sourcegraph", "JSON config"),
("Amazon Q", "~/.aws/amazonq", "YAML/JSON config"),
("Opencode", "~/.config/opencode", "JSON config"),
];

pub fn run() -> Result<()> {
Expand Down
131 changes: 131 additions & 0 deletions src/commands/generate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//! Generate command - scaffolds new FGP daemons from templates.
//!
//! Uses the Python generator script from the generator/ directory.

use anyhow::{bail, Context, Result};
use colored::Colorize;
use std::path::PathBuf;
use std::process::Command;

/// Get the path to the generator script.
fn generator_script_path() -> Result<PathBuf> {
// Try relative to the CLI binary first (installed location)
let exe_path = std::env::current_exe().context("Failed to get executable path")?;
let exe_dir = exe_path.parent().unwrap();

// Check various possible locations
let candidates = [
// Relative to binary (installed)
exe_dir.join("../lib/fgp/generator/generate.py"),
exe_dir.join("../../generator/generate.py"),
// Development location
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../generator/generate.py"),
// Absolute fallback
PathBuf::from(shellexpand::tilde("~/.fgp/generator/generate.py").as_ref()),
];

for path in &candidates {
if path.exists() {
return Ok(path.canonicalize().unwrap_or_else(|_| path.clone()));
}
}

bail!(
"Generator script not found. Looked in:\n{}",
candidates
.iter()
.map(|p| format!(" - {}", p.display()))
.collect::<Vec<_>>()
.join("\n")
)
}

/// List all available service presets.
pub fn list() -> Result<()> {
let script_path = generator_script_path()?;

let output = Command::new("python3")
.arg(&script_path)
.arg("--list-presets")
.output()
.context("Failed to run generator script")?;

if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
bail!("Generator failed:\n{}", stderr);
}

// Print the output directly
print!("{}", String::from_utf8_lossy(&output.stdout));

Ok(())
}

/// Generate a new daemon from a service preset.
pub fn new_daemon(
service: &str,
preset: bool,
display_name: Option<&str>,
api_url: Option<&str>,
env_token: Option<&str>,
output_dir: Option<&str>,
author: &str,
) -> Result<()> {
let script_path = generator_script_path()?;

println!();
println!(
"{} Generating FGP daemon: {}",
"→".blue(),
service.bold()
);

// Build command arguments
let mut args = vec![script_path.to_string_lossy().to_string(), service.to_string()];

if preset {
args.push("--preset".to_string());
}

if let Some(name) = display_name {
args.push("--display-name".to_string());
args.push(name.to_string());
}

if let Some(url) = api_url {
args.push("--api-url".to_string());
args.push(url.to_string());
}

if let Some(token) = env_token {
args.push("--env-token".to_string());
args.push(token.to_string());
}

if let Some(dir) = output_dir {
args.push("--output-dir".to_string());
args.push(dir.to_string());
}

args.push("--author".to_string());
args.push(author.to_string());

let output = Command::new("python3")
.args(&args[..])
.output()
.context("Failed to run generator script")?;

if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
if !stdout.is_empty() {
print!("{}", stdout);
}
bail!("Generator failed:\n{}", stderr);
}

// Print the output directly
print!("{}", String::from_utf8_lossy(&output.stdout));

Ok(())
}
5 changes: 5 additions & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
pub mod agents;
pub mod call;
pub mod dashboard;
pub mod generate;
pub mod health;
pub mod install;
pub mod methods;
pub mod new;
pub mod skill;
pub mod skill_export;
pub mod skill_tap;
pub mod skill_validate;
pub mod start;
pub mod status;
pub mod stop;
Expand Down
Loading
Loading