# iFlow CLI SDK for Rust
A powerful Rust SDK for interacting with iFlow using the Agent Communication Protocol (ACP). This SDK provides both simple query functions and full bidirectional client for complex interactions.
[](https://codecov.io/gh/vibe-ideas/iflow-cli-sdk-rust) [](https://crates.io/crates/iflow-cli-sdk-rust) [](https://deepwiki.com/vibe-ideas/iflow-cli-sdk-rust)
<!-- DeepWiki badge generated by https://deepwiki.ryoppippi.com/ -->
## Features
- 🚀 **Automatic Process Management** - SDK automatically starts and manages iFlow process
- 🔌 **Stdio Communication** - Communicate with iFlow via stdio
- 🔌 **WebSocket Communication** - Communicate with iFlow via WebSocket for better performance and reliability
- 🔄 **Bidirectional Communication** - Real-time streaming messages and responses
- 🛠️ **Tool Call Management** - Fine-grained permission control for tool execution
- 📋 **Task Planning** - Receive and process structured task plans
- 🔍 **Raw Data Access** - Debug and inspect protocol-level messages
- ⚡ **Async/Await Support** - Modern async Rust with full type safety
## TODO
- [ ] 🤖 **Sub-agent Support** - Track and manage multiple AI agents via `agent_id`
[ROADMAP.md](ROADMAP.md)
## Installation
Add this to your `Cargo.toml`:
```toml
[dependencies]
iflow-cli-sdk-rust = "0.1.0"
```
Or install directly from the repository:
```bash
cargo add --git https://github.com/vibe-ideas/iflow-cli-sdk-rust
```
## Quick Start
### Simple Query
```rust
use iflow_cli_sdk_rust::query;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let response = query("What is 2 + 2?").await?;
println!("{}", response); // "4"
Ok(())
}
```
### MCP Server Configuration
The SDK supports configuring MCP (Modular Command Protocol) servers for extended capabilities such as filesystem access, command execution, and more. You can configure MCP servers using the `McpServer` type:
```rust
use iflow_cli_sdk_rust::{IFlowClient, IFlowOptions, McpServer, EnvVariable};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure MCP servers for extended capabilities
let mcp_servers = vec![
McpServer {
name: "filesystem".to_string(),
command: "mcp-server-filesystem".to_string(),
args: vec!["--allowed-dirs".to_string(), "/workspace".to_string()],
env: vec![
EnvVariable {
name: "DEBUG".to_string(),
value: "1".to_string(),
}
],
}
];
// Create options with MCP server configuration
let options = IFlowOptions::new()
.with_mcp_servers(mcp_servers);
// Create client with options
let mut client = IFlowClient::new(Some(options));
// Connect and use the client as usual
client.connect().await?;
// ...
Ok(())
}
```
### Simple Query with Custom Configuration
```rust
use iflow_cli_sdk_rust::{query_with_config, IFlowOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = IFlowOptions::new()
.with_timeout(60.0); // 60 second timeout
let response = query_with_config("What is 2 + 2?", options).await?;
println!("{}", response); // "4"
Ok(())
}
```
### Interactive Session
```rust
use iflow_cli_sdk_rust::{IFlowClient, IFlowOptions, Message};
use futures::stream::StreamExt;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = IFlowOptions::new()
.with_auto_start_process(true);
let mut client = IFlowClient::new(Some(options));
client.connect().await?;
client.send_message("Hello, iFlow!", None).await?;
let mut message_stream = client.messages();
while let Some(message) = message_stream.next().await {
match message {
Message::Assistant { content } => {
print!("{}", content);
std::io::stdout().flush()?;
}
Message::TaskFinish { .. } => {
break;
}
_ => {
// Handle other message types
}
}
}
client.disconnect().await?;
Ok(())
}
```
### Streaming Responses
```rust
use iflow_cli_sdk_rust::query_stream;
use futures::stream::StreamExt;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut stream = query_stream("Tell me a story").await?;
while let Some(chunk) = stream.next().await {
print!("{}", chunk);
std::io::stdout().flush()?;
}
Ok(())
}
```
### Streaming Responses with Custom Configuration
```rust
use iflow_cli_sdk_rust::{query_stream_with_config, IFlowOptions};
use futures::stream::StreamExt;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let options = IFlowOptions::new()
.with_timeout(60.0); // 60 second timeout
let mut stream = query_stream_with_config("Tell me a story", options).await?;
while let Some(chunk) = stream.next().await {
print!("{}", chunk);
std::io::stdout().flush()?;
}
Ok(())
}
```
## Configuration
### Client Options
```rust
use iflow_cli_sdk_rust::IFlowOptions;
let options = IFlowOptions::new()
.with_timeout(60.0)
.with_file_access(true)
.with_auto_start_process(true);
```
### WebSocket Communication
The SDK supports WebSocket communication with iFlow for better performance and reliability. To use WebSocket, specify the WebSocket configuration in the options:
```rust
use iflow_cli_sdk_rust::{IFlowOptions, types::WebSocketConfig};
// Simple configuration with default reconnect settings
let options = IFlowOptions::new()
.with_websocket_config(WebSocketConfig::new("ws://localhost:8090/acp?peer=iflow".to_string()));
// Or use the default configuration
let options = IFlowOptions::new()
.with_websocket_config(WebSocketConfig::default());
// Or configure with custom reconnect settings
let options = IFlowOptions::new()
.with_websocket_config(WebSocketConfig::with_reconnect_settings(
"ws://localhost:8090/acp?peer=iflow".to_string(),
5, // reconnect attempts
std::time::Duration::from_secs(10) // reconnect interval
));
// In auto-start mode, you can omit the URL entirely
let options = IFlowOptions::new()
.with_websocket_config(WebSocketConfig::auto_start());
// Or configure auto-start mode with custom reconnect settings
let options = IFlowOptions::new()
.with_websocket_config(WebSocketConfig::auto_start_with_reconnect_settings(
5, // reconnect attempts
std::time::Duration::from_secs(10) // reconnect interval
));
```
If you enable auto-start process with a WebSocket URL pointing to localhost, the SDK will automatically start the iFlow process if it's not already running. In auto-start mode, you can omit the URL entirely and let the SDK generate it automatically.
## Message Types
The SDK handles various message types from iFlow:
- `Message::Assistant { content }` - AI assistant responses
- `Message::ToolCall { id, name, status }` - Tool execution requests
- `Message::Plan { entries }` - Structured task plans
- `Message::TaskFinish { reason }` - Task completion signals
- `Message::Error { code, message }` - Error notifications
- `Message::User { content }` - User message echoes
## Examples
Run the examples:
```bash
# Simple query example
cargo run --example query
# Interactive client example
cargo run --example basic_client
# Test response handling
cargo run --example test_response
# Explore API capabilities
cargo run --example explore_api
# Logging example
cargo run --example logging_example
```
## Architecture
The SDK is organized into several modules:
- `client` - Main IFlowClient implementation with stdio communication
- `types` - Type definitions and message structures
- `process_manager` - iFlow process lifecycle management
- `query` - Convenience functions for simple queries
- `error` - Error types and handling
- `logger` - Message logging functionality
## Requirements
- Rust 1.70+
- iFlow CLI installed with `--experimental-acp` support (or use auto-start feature)
## Development
### Building
```bash
cargo build
```
### Testing
```bash
cargo test
# Run specific test suites
cargo test --test websocket_config_tests
cargo test --test websocket_integration_tests
# e2e tests
cargo test --test e2e_tests -- --nocapture
```
### Running with logging
```bash
RUST_LOG=debug cargo run --example basic_client
```
## License
MIT License - see LICENSE file for details.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.