Inspiration
Coding agents write code faster than you can read it. In Rust, where closures, iterator adapters, lifetimes and trait bounds are each a thing to learn, that leaves two bad options: accept code you do not understand, or tell the agent to avoid everything you have not learned and never learn it.
molt takes a third path. A crab grows by molting: it sheds a shell that has become too small and grows a larger one. molt treats what you can already write as your shell. It writes freely inside it, and every time the code needs something outside it, molt stops, explains, and lets the shell grow by one step. Grow your Rust, one shell at a time.
What it does
molt is a terminal coding agent for cargo projects, backed by three NVIDIA Nemotron 3 models on Nebius Token Factory.
- Profile.
molt initasks what Rust you have written (ten categories of syntax elements, plus the crates of a repository of yours with--repo). A small model judges the answers and saves a profile: each construct isknown,seenorunknown. - Main line. You type a request at
molt>. molt reads and writes files through tools, runscargo checkafter each turn, shows the diff, proposes a commit message, and commits only the files it changed, only when you approve. Code made ofknownconstructs is written in bulk and never stops. - Boundary. When the code needs a construct that is not
known, molt writes it as one small step (at most 3 such items and 30 changed lines), stops right after it, and opens a side line. A large reasoning model explains exactly those lines, shows how the same part looks with only your profile, and answers any questions. Then you choose:- Understood: keep it; the items become
known. - Without them: take it back and rewrite it within your profile.
- I'll write it: take it back; you write it, and molt checks and reviews what you wrote.
- Later: keep it, and explain again next time.
- Understood: keep it; the items become
- Guard rails. Every write goes through a static checker (
syn) before it lands, so the model cannot slip an unknown construct past the boundary. Writes are confined to the project root;.git/andtarget/are refused.cargoruns only from an allow-list, andcargo addneeds approval. The API key is read from an environment variable and never written to logs. - Session log. Everything molt did (tool calls, findings, choices, cargo results) is recorded as JSONL.
How we used NVIDIA Nemotron and Nebius Token Factory
molt sends each request to one of three roles, so that a request goes to a model of the size it needs. All three defaults are Nemotron 3 models served by Token Factory through its OpenAI-compatible API (https://api.tokenfactory.nebius.com/v1).
- light:
nvidia/Nemotron-3_5-Lightning(reasoning_effort: low). Judges themolt initanswers into the profile (one category per request, 3 in parallel) and writes the one-line policy after choice 2. - generate:
nvidia/nemotron-3-super-120b-a12b(medium). Writes the code through tools (read_file,write_file,edit_file,run_cargo, …), the rewrite after choice 2, the review for choice 3, and the commit message. - reason:
nvidia/Nemotron-3-Ultra-550b-a55b(high). Explains a step, shows the same part within your profile, guides choice 3 (where to write what), and answers side-line questions.
Token Factory features molt relies on, all confirmed by molt doctor for the three models: tool calls (tool_choice: required and auto), response_format: json_schema for the profile judgement (never prose to parse), reasoning_effort, and streaming, so a long explanation is not cut off by the request timeout. molt doctor records what each model supports, and molt sends only what was confirmed.
Measured on Token Factory in a fresh cargo init project: molt init with five categories answered took 19 s. A request that stopped at a boundary (numbers.iter().map(|&x| x * x).collect(), three unknown items), was explained by Nemotron 3 Ultra, kept with choice 1, passed cargo check and was committed took 29 s. A request with no boundary took 24 s.
How we built it
Rust (2024 edition), reqwest with rustls, syn for the checker, clap, crossterm and rustyline for the terminal UI. The design is written down in PRD.md (English, with a Japanese version), and the module dependency graph in the PRD is enforced by a test. Nearly 1,000 unit tests plus integration tests. A --fake mode replays scripted model responses, so the whole pass (request → boundary → choice → cargo check → commit) runs offline in CI. Real-API tests are #[ignore] and were run against Token Factory. CI runs fmt, clippy -D warnings and test on every PR, and a release workflow builds the macOS and static Linux binaries.
Challenges we ran into
- Making "stop after a small step" real, not a prompt wish. The checker inspects every write before it lands, counts the unknown items and changed lines, and rejects a write that exceeds the step. The model is told why and asked again; after two rejections molt stops at a boundary with what it has.
- Macros hide code from the checker. molt parses the arguments of the std macros that take expressions and patterns, and treats any other macro call as an item that must itself be
known. - Keeping the side line honest. Questions on the side line never enter the main line's message list, so the explanation cannot change what the agent writes next; only the choice does.
What's next
molt loginto keep the API key in the OS keychain instead of an environment variable.- A profile that decays: items you have not written for a while become
seenagain. - Richer boundaries for crates and lifetimes, and a
molt init --repothat also reads embedded and async code.
Built With
- clap
- crossterm
- nebius-token-factory
- nvidia-nemotron
- reqwest
- rust
- rustyline
- syn
Log in or sign up for Devpost to join the conversation.