Every morning I would open 4 terminal tabs, cd into different folders, and run some combination of npm run dev and cargo run. Then I'd forget which terminal crashed. Then I'd do it again.
So I built Chronicle to kill that habit.
What Is Chronicle?
Chronicle is a desktop app (built with Tauri) that does two things:
- One-click workspace launcher — press a button, fire up all your dev servers simultaneously, watch their output stream into a tabbed terminal dashboard in real-time
- Git history explorer — visualize your commit graph, click commits to read diffs, and use an AI (Gemini) to summarize what changed
The Stack
| Layer | Technology |
|---|---|
| App Shell | Tauri v2 |
| Frontend | React 19 + Vite 7 + TypeScript |
| Backend | Rust (async, via Tokio) |
| Styling | Tailwind CSS v4 |
| Animations | Framer Motion |
| AI | Google Gemini |
Why Tauri?
Tauri lets you write your UI in whatever web framework you want, then wraps it in a native OS window using Rust. The result is a .exe that's tiny, fast, and has full access to the OS. No Electron 300MB bloat. No compromises.
The Rust backend part is what made the launcher feature possible. Here's the core of how it works:
#[tauri::command]
async fn start_all_processes(
app: AppHandle,
state: tauri::State<'_, Arc<AppState>>,
project_path: String
) -> Result<(), String> {
// Spawn each process asynchronously
spawn_and_stream(app.clone(), state.clone(), "buildforge",
"npm", &["run", "dev"], &format!("{}\\BuildForge", project_path)).await?;
spawn_and_stream(app.clone(), state.clone(), "airwebreathe",
"npm", &["run", "dev"], &format!("{}\\AirWeBreathe", project_path)).await?;
Ok(())
}
The spawn_and_stream function uses Tokio to spawn processes async, reads their stdout/stderr line by line, and emits each line to the React frontend using Tauri's event system.
On the React side, listening for those events looks like:
const unlistenOutput = await listen<LogPayload>('process-output', (event) => {
setLogs(prev => ({
...prev,
[event.payload.id]: [...(prev[event.payload.id] || []), event.payload.line]
}));
});
That's it. Real-time streaming terminal output from Rust to React in so few lines.
The UI
The whole thing is themed after GitHub dark mode (#0d1117, subtle borders, green accents). The launcher screen has one big green button. The dashboard that opens shows tabbed terminal output for each running process, auto-scrolling, color-coded (green = success, red = error).
What I Learned
1. Tauri is genuinely underrated. The developer experience is excellent, the apps are fast, and the security model is much more sensible than Electron.
2. Tokio makes async process spawning a joy. tokio::process::Command + BufReader + lines() is all you need to stream terminal output.
3. Tauri's event system is a perfect bridge. app.emit("event-name", payload) from Rust, listen("event-name", handler) from TypeScript. Clean and simple.
Try It
git clone https://github.com/TROJANmocX/Chronicle.git
npm install
npm run tauri dev
If you're building dev tooling or have ever thought "I should automate my terminal workflow" — Tauri + Rust is a genuinely great choice. Feel free to drop questions in the comments.
Happy building! 🗡️
Top comments (0)