| Crates.io | presenceforge |
| lib.rs | presenceforge |
| version | 0.1.0 |
| created_at | 2025-10-19 16:41:20.895312+00 |
| updated_at | 2025-10-24 17:42:25.457395+00 |
| description | A library for Discord Rich Presence (IPC) integration |
| homepage | |
| repository | https://github.com/Sreehari425/presenceforge |
| max_upload_size | |
| id | 1890606 |
| size | 441,770 |
A Rust library for Discord Rich Presence that actually works without the headaches. No more fighting with the Discord SDK or dealing with complex C bindings.
Note: This is currently in development (v0.1.0). Things might break. This is a learning/hobby project. Features and APIs may change in future versions.
Want to build your own RPC client?
Add PresenceForge to your Cargo.toml:
[dependencies]
presenceforge = "0.1.0"
For async support, add one of the runtime features:
[dependencies]
presenceforge = { version = "0.1.0", features = ["tokio-runtime"] }
# OR
presenceforge = { version = "0.1.0", features = ["async-std-runtime"] }
# OR
presenceforge = { version = "0.1.0", features = ["smol-runtime"] }
use presenceforge::ActivityBuilder;
use presenceforge::sync::DiscordIpcClient;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = DiscordIpcClient::new("your_client_id")?;
client.connect()?;
let activity = ActivityBuilder::new()
.state("Playing a game")
.details("In the menu")
.start_timestamp_now()
.large_image("game_logo")
.large_text("My Awesome Game")
.build();
client.set_activity(&activity)?;
// Keep the activity active
std::thread::sleep(std::time::Duration::from_secs(10));
client.clear_activity()?;
Ok(())
}
use presenceforge::{AsyncDiscordIpcClient, ActivityBuilder, Result};
#[tokio::main]
async fn main() -> Result {
let mut client = AsyncDiscordIpcClient::new("your_client_id").await?;
client.connect().await?;
let activity = ActivityBuilder::new()
.state("Playing a game")
.details("In the menu")
.start_timestamp_now()
.large_image("game_logo")
.large_text("My Awesome Game")
.build();
client.set_activity(&activity).await?;
tokio::time::sleep(tokio::time::Duration::from_secs(10)).await;
client.clear_activity().await?;
Ok(())
}
use presenceforge::{AsyncDiscordIpcClient, ActivityBuilder, Result};
use async_std::task;
use std::time::Duration;
#[async_std::main]
async fn main() -> Result {
let mut client = AsyncDiscordIpcClient::new("your_client_id").await?;
client.connect().await?;
let activity = ActivityBuilder::new()
.state("Playing a game")
.details("In the menu")
.start_timestamp_now()
.large_image("game_logo")
.large_text("My Awesome Game")
.build();
client.set_activity(&activity).await?;
task::sleep(Duration::from_secs(10)).await;
client.clear_activity().await?;
Ok(())
}
use presenceforge::{AsyncDiscordIpcClient, ActivityBuilder, Result};
use std::time::Duration;
fn main() -> Result {
smol::block_on(async {
let mut client = AsyncDiscordIpcClient::new("your_client_id").await?;
client.connect().await?;
let activity = ActivityBuilder::new()
.state("Playing a game")
.details("In the menu")
.start_timestamp_now()
.large_image("game_logo")
.large_text("My Awesome Game")
.build();
client.set_activity(&activity).await?;
smol::Timer::after(Duration::from_secs(10)).await;
client.clear_activity().await?;
Ok(())
})
}
All examples support three ways to provide your Discord Client ID:
cargo run --example basic -- --client-id YOUR_CLIENT_ID
DISCORD_CLIENT_ID=YOUR_CLIENT_ID cargo run --example basic
# Copy the example file
cp .env.example .env
# Edit .env and add your client ID
# DISCORD_CLIENT_ID=your_client_id_here
# Then run any example
cargo run --example basic
Priority Order: Command-line argument → Environment variable → .env file
| Platform | IPC Method | Status |
|---|---|---|
| Linux | Unix Domain Sockets | [x] |
| macOS | Unix Domain Sockets | [x] |
| Windows | Named Pipes | [x] |
DiscordIpcClient::new(client_id) - Create a new clientclient.connect() - Connect to Discordclient.set_activity(activity) - Set Rich Presence activityclient.clear_activity() - Clear current activityThe ActivityBuilder provides a fluent interface for creating activities:
ActivityBuilder::new()
.state("Custom state") // What the player is doing
.details("Custom details") // Additional context
.start_timestamp_now() // Start time (current)
.start_timestamp(timestamp) // Start time (custom)
.end_timestamp(timestamp) // End time
.large_image("image_key") // Large image asset
.large_text("Hover text") // Large image hover text
.small_image("image_key") // Small image asset
.small_text("Hover text") // Small image hover text
.button("Label", "https://url") // Clickable button (max 2)
.party("id",1, 4) // Party size (current, max)
.build()
For detailed information about all available examples and configuration options, see the Examples README.
Clone the repository and run the included examples:
git clone https://github.com/Sreehari425/presenceforge.git
cd presenceforge
# Basic example (synchronous)
cargo run --example basic -- --client-id YOUR_CLIENT_ID
# Game demo with dynamic status
cargo run --example game_demo -- --client-id YOUR_CLIENT_ID
# Developer coding status
cargo run --example coding_status -- --client-id YOUR_CLIENT_ID
# Custom activity without builder
cargo run --example custom_activity -- --client-id YOUR_CLIENT_ID
# Async example with Tokio
cargo run --example async_tokio --features tokio-runtime -- --client-id YOUR_CLIENT_ID
# Async example with async-std
cargo run --example async_std --features async-std-runtime -- --client-id YOUR_CLIENT_ID
# Async example with smol
cargo run --example async_smol --features smol-runtime -- --client-id YOUR_CLIENT_ID
# Complete builder reference - Shows ALL ActivityBuilder options
cargo run --example builder_all -- --client-id YOUR_CLIENT_ID
# Connection retry and error handling
cargo run --example connection_retry -- --client-id YOUR_CLIENT_ID
# Pipe selection and discovery
cargo run --example pipe_selection -- --client-id YOUR_CLIENT_ID
Or use the .env file method (recommended for development):
# Set up .env file once
cp .env.example .env
# Edit .env and add: DISCORD_CLIENT_ID=your_client_id_here
# Then run examples without specifying client ID
cargo run --example basic
cargo run --example game_demo
cargo run --example async_tokio --features tokio-runtime
Note: Replace YOUR_CLIENT_ID with your actual Discord application ID, or use the .env file method for convenience.
PresenceForge uses the Result type for error handling:
use presenceforge::DiscordIpcError;
use presenceforge::sync::DiscordIpcClient;
match client.connect() {
Ok(_) => println!("Connected successfully!"),
Err(DiscordIpcError::ConnectionFailed) => {
eprintln!("Failed to connect - is Discord running?");
}
Err(e) => eprintln!("Error: {}", e),
}
This project is licensed under either of
at your option.