A Rust library that lets you use t3.chat from your terminal and integrate it into your programs.
I pay for t3.chat every month because it gives me access to all the best AI models in one place - Claude, GPT-4, Gemini, and many others. But I spend most of my time in the terminal, and I wanted to use these models directly from my command line without opening a browser.
So I built this library. It uses your t3.chat cookies to authenticate and lets you chat with any model, manage conversations, track credits, and even generate images - all from your Rust programs.
Important: This only works if you have a paid t3.chat account. It won't work with free accounts.
send_with_credits() measures exact credits deducted per requestwreq to bypass TLS fingerprintingsend_stream() and send_with_credits_stream() for token-by-token streaming via SSE~/.t3router/session.jsoncargo run --bin t3chat for a terminal REPL with /help, /new, /resume, /save, /model, /credits, /quitT3_MODEL, T3_SYSTEM_PROMPT, T3_TRACK_CREDITS, T3_TIMEZONE, T3_LOCALEFrom crates.io:
[dependencies]
t3router = "0.1.1"
tokio = { version = "1.52", features = ["full"] }
dotenv = "0.15"
Or from Git:
[dependencies]
t3router = { git = "https://github.com/vibheksoni/t3router" }
tokio = { version = "1.52", features = ["full"] }
dotenv = "0.15"
convex-session-id valueCopy .env.example to .env and fill in your credentials:
cp .env.example .env
COOKIES="your_full_cookie_string_here"
CONVEX_SESSION_ID="your_session_id_here"
T3_MODEL="kimi-k2.5"
T3_SYSTEM_PROMPT="optional system prompt for the session"
T3_TIMEZONE="America/New_York"
T3_LOCALE="en-US"
Interactive chat with streaming output, session auto-save, and credit tracking:
cargo run --bin t3chat
Or via the example target:
cargo run --example chat
Chat commands: /help, /new, /resume, /save, /model <id>, /credits, /quit
Sessions are auto-saved to ~/.t3router/session.json after each message and restored on startup.
Streaming: responses stream token-by-token. Library methods: send_stream() and send_with_credits_stream().
use t3router::t3::{client::Client, config::Config, message::{Message, Type}};
use dotenv::dotenv;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv().ok();
let cookies = std::env::var("COOKIES")?;
let session_id = std::env::var("CONVEX_SESSION_ID")?;
let mut client = Client::new(cookies, session_id);
client.init().await?;
let response = client.send(
"gemini-2.5-flash-lite",
Some(Message::new(Type::User, "What is the capital of France?".to_string())),
Some(Config::new()),
).await?;
println!("{}", response.content);
Ok(())
}
let response = client.send_with_credits(
"claude-fable-5",
Some(Message::new(Type::User, "Write a haiku about Rust.".to_string())),
None,
).await?;
println!("Assistant: {}", response.message.content);
if let Some(deducted) = response.credits_deducted {
println!("Credits deducted: {:.5}", deducted);
}
client.new_conversation();
client.append_message(Message::new(Type::User, "Let's talk about Rust".to_string()));
client.append_message(Message::new(Type::Assistant, "Sure! I'd love to discuss Rust.".to_string()));
let response = client.send(
"gemini-2.5-flash-lite",
Some(Message::new(Type::User, "What makes Rust memory safe?".to_string())),
Some(Config::new()),
).await?;
println!("Total messages: {}", client.get_messages().len());
use std::path::Path;
let save_path = Path::new("output/image.png");
let response = client.send_with_image_download(
"gpt-image-1",
Some(Message::new(Type::User, "A sunset over mountains".to_string())),
Some(Config::new()),
Some(save_path),
).await?;
match response.content_type {
ContentType::Image => {
println!("Image saved to {:?}", save_path);
if let Some(b64) = response.base64_data {
println!("Base64 data: {} bytes", b64.len());
}
}
ContentType::Text => println!("Got text: {}", response.content),
}
use t3router::t3::usage::UsageClient;
let client = UsageClient::new(cookies);
let data = client.get_customer_data().await?;
println!("Balance: {:.2} credits", data.balance);
println!("Monthly Usage: {:.2}%", data.usage_month_percentage);
use t3router::t3::models::ModelsClient;
let models_client = ModelsClient::new(cookies, session_id);
let models = models_client.get_models().await?;
let statuses = models_client.get_model_statuses_trpc().await?;
let benchmarks = models_client.get_model_benchmarks().await?;
println!("Found {} models", models.len());
for model in &models[..5] {
println!(" {} ({}) - ${:.2}/M input", model.name, model.provider, model.cost.input * 1_000_000.0);
}
use t3router::t3::{client::Client, config::Config, message::{Message, Type}};
let mut client = Client::new(cookies, session_id);
let response = client.send_stream(
"gemini-2.5-flash-lite",
Some(Message::new(Type::User, "Tell me a story".to_string())),
Some(Config::new()),
|delta| {
print!("{delta}");
use std::io::Write;
std::io::stdout().flush().unwrap();
},
).await?;
println!("\nFull response: {}", response.content);
use t3router::t3::{client::Client, message::{Message, Type}, session::{SavedSession, save_session, load_session}};
let session = SavedSession::from_client(
client.get_thread_id().unwrap(),
"gemini-2.5-flash-lite",
client.get_messages(),
);
save_session(&session)?;
let saved = load_session()?.unwrap();
client.resume_conversation(saved.thread_id, saved.into_messages());
use t3router::t3::history::HistoryClient;
let client = HistoryClient::new(cookies, session_id);
// Export sessionStorage["ephemeral-chat-data"] from browser devtools
let threads = client.parse_ephemeral_threads(&storage_json);
for t in &threads {
println!(" {} | {} | model={}", t.id, t.title, t.model);
}
use t3router::t3::config::{Config, ReasoningEffort};
let mut config = Config::new();
config.reasoning_effort = ReasoningEffort::High;
config.include_search = true;
config.system_prompt = Some("You are a helpful assistant".to_string());
config.timezone = "America/New_York".to_string();
config.locale = "en-US".to_string();
config.track_credits = false; // skip balance API calls for lower latency
Or load from environment variables:
let config = Config::from_env(); // reads T3_SYSTEM_PROMPT, T3_TRACK_CREDITS, T3_TIMEZONE, T3_LOCALE
t3router/
src/
lib.rs # Library entry point
bin/
t3chat.rs # Binary entry point for the CLI
t3/
mod.rs # Module declarations
client.rs # Client, SseAccumulator, send(), send_stream(), send_with_credits(),
# send_with_credits_stream(), send_with_image_download(), poll_credit_delta()
config.rs # Config struct, Config::from_env(), ReasoningEffort enum
message.rs # Message types (User/Assistant, Text/Image)
models.rs # Model discovery, statuses, benchmarks via tRPC
repl.rs # Interactive terminal REPL with streaming and session persistence
session.rs # SavedSession, save/load to ~/.t3router/session.json
usage.rs # Usage & billing via tRPC
history.rs # Conversation history parser
examples/
chat.rs # Interactive terminal chat (use `cargo run --bin t3chat`)
basic_usage.rs # Simple chat + credit tracking
multi_message.rs # Multi-turn conversations
image_generation.rs # Image generation with download
list_models.rs # All models + statuses + benchmarks
check_usage.rs # Balance, subscription, pricing, sessions
fable5_credits.rs # Credit deduction with claude-fable-5
list_history.rs # Browser storage history parser
Cargo.toml
wreq with Chrome 136 emulation to bypass TLS fingerprinting/api/chat, parses SSE stream responses/api/trpc/*poll_credit_delta() polls balance (8 attempts × 200ms) instead of fixed 2s sleepsend_stream() uses response.bytes_stream() for real-time SSE parsing via SseAccumulator~/.t3router/session.json and can be resumed with Client::resume_conversation()This project is not intended for abusing t3.chat or any related services; it is simply a technical demonstration and a cool tool for experimentation. We do not promote or support any misuse of this library. The author(s) take no responsibility for any actions taken against your account. In principle, this should not happen, as the library only functions with paid subscription accounts; however, t3.chat may introduce countermeasures in the future. Use at your own risk.
Built on top of t3router, pi-t3chat is a Pi coding agent extension that brings all 50+ t3.chat models into Pi's OpenAI-compatible interface — with full tool calling support, MCP wrapper tools, and token usage reporting.
pi install git:github.com/vibheksoni/pi-t3chat
Features beyond t3router:
list_mcps, list_mcp_tools, call_mcp discovery for mcp__-prefixed toolsprompt_tokens, completion_tokens, total_tokens with cache/reasoning detailscompat flags, developer role handling, stream_options, max_tokens fieldIf you find a bug or want to add something:
MIT License - see LICENSE file
Built for everyone who loves using the terminal and wants to access great AI models without leaving it.
If this helps you, please star the repository on GitHub!
No reviews yet. Be the first to rate this tool.
Sign in to leave a review.