notes for agents#
hey future me (or other agent),
this file tracks what we're learning and building together. oskar is mentoring, we're building from scratch.
context restoration#
when starting a new session, follow this path:
AGENTS.md (this file) → project status, decisions, workflow
↓
todo.txt → what's next, suggest one
↓
docs/iced.txt → framework knowledge
↓
CHANGELOG.md → what we've done (narrative style)
project status#
phase: initialization repo: jujutsu (jj) goal: radio4000 desktop browser - all data local (1k radios, ~60k tracks) - fast search/filter/browse - native performance
style preferences#
✓ ascii and plain text ✓ small diagrams, symbols ✓ whitespace and casing over bold ✓ organic, readable ✓ occasional wit (cleese, attenborough, dfw sensibilities) ✓ favor precision over enthusiasm
key decisions#
2025-10-25: chose iced why: - TRUE native rendering (no DOM/webview) - elm architecture (clean patterns) - handles 60k items natively - system76 backing (cosmic desktop) - actual GPU performance rejected tauri, dioxus, egui, leptos
2025-10-25: data pipeline with compressed sources - see docs/data.txt for full details
architecture notes#
tech stack: - iced (native GPU rendering) - rust for data handling - radio4000 API for data source
structure: src/main.rs → iced app (elm architecture) Cargo.toml → dependencies
workflow#
completing tasks:
- do the work
- update CHANGELOG.md with what changed
- jj describe -m "message"
- jj new
- update AGENTS.md if decisions made
starting session:
- read this file (AGENTS.md)
- read todo.txt
- suggest next task (don't ask what to do)
jj basics: jj describe -m "msg" → label current change jj new → start new change see ~/Notes/jj.md for more
development tools#
cli interface (for debugging/testing): - shares exact same code as GUI (DataStore, search, filters) - test operations without launching full GUI - faster iteration when developing filters
commands:
r4 stats # dataset statistics
r4 search "query" --target tracks --limit 5 # search channels or tracks
r4 filter --tag ambient --limit 10 # filter by tag
r4 filter --channel oskar # filter by channel slug
r4 stats --format json | jq # JSON output for scripting
useful for:
- debugging filter logic without GUI rebuild
- benchmarking search/filter performance
- verifying data operations programmatically
- scripting data verification tasks
implementation: src/cli.rs, src/main.rs:26
things to remember#
- docs folder is for MY notes, to build efficiently
- oskar will guide what we're actually building
- this is an experiment, enjoy the process
- CHANGELOG.md links to jj history (describe after updating it)
reference docs#
- iced framework → docs/iced.txt
- iced patterns → docs/halloy-patterns.txt (real-world iced app structure from halloy irc client)
- data pipeline → docs/data.txt (import process, file structure, deduplication logic)
rust coding guidelines#
Rust coding guidelines#
- Prioritize code correctness and clarity. Speed and efficiency are secondary priorities unless otherwise specified.
- Do not write organizational or comments that summarize the code. Comments should only be written in order to explain "why" the code is written in some way in the case there is a reason that is tricky / non-obvious.
- Prefer implementing functionality in existing files unless it is a new logical component. Avoid creating many small files.
- Avoid using functions that panic like
unwrap(), instead use mechanisms like?to propagate errors. - Be careful with operations like indexing which may panic if the indexes are out of bounds.
- Never silently discard errors with
let _ =on fallible operations. Always handle errors appropriately:- Propagate errors with
?when the calling function should handle them - Use
.log_err()or similar when you need to ignore errors but want visibility - Use explicit error handling with
matchorif let Err(...)when you need custom logic - Example: avoid
let _ = client.request(...).await?;- useclient.request(...).await?;instead
- Propagate errors with
- When implementing async operations that may fail, ensure errors propagate to the UI layer so users get meaningful feedback.
- Never create files with
mod.rspaths - prefersrc/some_module.rsinstead ofsrc/some_module/mod.rs. - When creating new crates, prefer specifying the library root path in
Cargo.tomlusing[lib] path = "...rs"instead of the defaultlib.rs, to maintain consistent and descriptive naming (e.g.,gpui.rsormain.rs). - Avoid creative additions unless explicitly requested
- Use full words for variable names (no abbreviations like "q" for "queue")
- Use variable shadowing to scope clones in async contexts for clarity, minimizing the lifetime of borrowed references.
Example:
executor.spawn({ let task_ran = task_ran.clone(); async move { *task_ran.borrow_mut() = true; } });