Crabrix blog
Rust coding interviews: a shared Playground for people and agents
Run a practical Rust interview in a temporary encrypted Playground: clear tasks, live agent handoff, ownership questions and browser-local Debug.
· 10 min read
Crabrix blog
Run a practical Rust interview in a temporary encrypted Playground: clear tasks, live agent handoff, ownership questions and browser-local Debug.
· 10 min read
A useful Rust interview needs a problem small enough to understand and rich enough to expose reasoning. Asking someone to type a familiar algorithm as quickly as possible mostly measures rehearsal. A better session makes the contract visible, allows the candidate to question ambiguous requirements, and follows one implementation through examples, compiler feedback and a small change. The shared editor should support that conversation without becoming another system everyone must learn first.
Crabrix now offers a standalone SDK and MCP server under the npm name crabrix. An interviewer, a candidate and an explicitly invited agent can work in one temporary Rust Playground. The phone app is optional: participants can open the same link in a browser. Code and named selections are shared, while compilation happens only in the browser or app that starts it. That separation makes it possible to discuss the same source without silently starting programs on everyone’s computer.
Before sending a link, agree on the role of AI. Perhaps an agent may suggest edge cases but not implement the answer; perhaps this is an exercise in reviewing agent code. State that rule in the task itself. A productive interview then evaluates whether the person can explain a decision, reject an unsuitable suggestion and verify the final behavior. The presence of an assistant does not remove the need to establish who is responsible for the answer.

Explore in Crabrix: Open the web Playground · Interview Prep course
Use a room lifetime that matches the session. The default is one hour, and the maximum is 24 hours. Expiry is fixed when the room is created; reconnecting does not renew it. The editor displays its remaining lifetime. For a short interview, creating a room just before the call gives a clearer deadline than preparing one the previous evening and discovering that it expires during the discussion.
A room supports four connected participants. Count the assistant’s MCP bridge or SDK process as a participant, just as you count a browser or native app. For example, an interviewer’s browser, the candidate’s browser and two agents already fill the room. Do not open the same room in several unnecessary tabs and then interpret a participant-limit error as a compiler problem. Close unused connections when the working arrangement changes.
Share the complete capability link only with intended participants. Everything after # is part of the link, including the decryption key and access information. An edit link permits source changes; a separate view link permits reading. A view participant cannot turn its link into an edit capability merely by changing a label. Treat these links as access, rather than publishing one in a permanent public issue or pasting it into source that someone might later commit.

Explore in Crabrix: Sharing and expiry guide · MCP setup
Here is a compact task: inspect a list of labels, ignore blank labels after trimming, count accepted labels, keep the first longest label, and report the original one-based line numbers of rejected inputs. Define “longest” as the number of Unicode scalar values. That definition is deliberately different from UTF-8 byte length and from the number of user-perceived grapheme clusters. A candidate who asks about this distinction is clarifying the problem, not avoiding it.
The complete program below fits the browser’s standard-library profile and needs no external crates. It borrows the input slices, owns the selected output string and stores rejected line numbers in a vector. Notice that it creates an owned string only when a new longest label is found. The input is available for the entire call; returning a separate owned result avoids requiring the caller to keep that borrowed input alive merely to retain the summary.
The sample includes two crab characters, whose UTF-8 byte count exceeds the byte count of several short ASCII labels. Nevertheless, they contain only two scalar values. With the stated contract, the first four-character label wins the tie. Run this version before changing the task. Its assertions establish a small reproducible baseline that everyone in the room can inspect and discuss.
#[derive(Debug)]
struct Summary {
accepted: usize,
longest: String,
rejected_lines: Vec<usize>,
}
fn summarize(lines: &[&str]) -> Summary {
let mut result = Summary {
accepted: 0,
longest: String::new(),
rejected_lines: Vec::new(),
};
let mut longest_len = 0;
for (index, line) in lines.iter().enumerate() {
let label = line.trim();
if label.is_empty() {
result.rejected_lines.push(index + 1);
continue;
}
result.accepted += 1;
let length = label.chars().count();
if length > longest_len {
result.longest = label.to_owned();
longest_len = length;
}
}
result
}
fn main() {
let result = summarize(&[" crab ", "", " ", "🦀🦀", "rust"]);
assert_eq!(result.accepted, 3);
assert_eq!(result.longest, "crab");
assert_eq!(result.rejected_lines, vec![2, 3]);
let empty = summarize(&[]);
assert_eq!(empty.accepted, 0);
assert!(empty.longest.is_empty());
assert!(empty.rejected_lines.is_empty());
println!("interview summary: {result:?}");
}Sources: Rust Book: ownership · Rust str documentation
Explore in Crabrix: Rust strings and UTF-8
Ask what an empty input should produce, whether whitespace-only labels count as rejected, and how ties should be resolved. These are small questions with visible consequences. If one person expects the last longest label and another expects the first, a failing assertion may simply expose an unspecified requirement. Writing down the expected answer before editing prevents the interview from turning into a guessing game about the interviewer’s private intent.
Separate examples into categories: ordinary labels, blank input, a single accepted item, tied lengths and multibyte text. Explain why each category matters. Adding ten nearly identical ASCII strings creates less evidence than one carefully chosen crab example. The program uses one-based rejected line numbers because that is what the task asks for; array indices remain zero-based internally. That boundary is an excellent place to ask for a deliberate off-by-one check.
Discuss cost using the actual representation. The implementation walks the input text to trim and count scalar values, and retains only the current longest string plus rejected positions. A useful analysis identifies work in terms of total input text and retained output, rather than declaring the function “fast” because it contains one visible loop. If the requirements change to grapheme clusters, say that the current standard-library-only exercise does not implement that new definition.
Explore in Crabrix: Testing useful boundaries
The SDK and MCP tools read a current revision along with the source. An agent should prepare its change from that revision and submit it as the expected base. If another participant changes the project first, the conditional edit is rejected. The assistant must read again and reconsider its proposal. Retrying the same replacement against a newly read revision without inspecting the intervening edit would defeat the point of the conflict guard.
This is particularly useful when the candidate is explaining a line while an agent prepares tests. Ask the assistant to highlight its proposed area and make one bounded change. Named selections let the other participants see what is being discussed, including Unicode text. Selection offsets use UTF-16 coordinates; they are not UTF-8 byte indices. The SDK refuses an offset that splits a surrogate pair, which matters for the crab characters used in this exercise.
A practical instruction is: read the task and entry source, propose one additional boundary case, apply only that case against the exact revision, then select it and explain the expected outcome. Do not ask the agent to “fix everything” while a human is halfway through a different edit. Smaller, intentional changes are easier to review and make it clearer whether the candidate understands the final program.
Explore in Crabrix: Standalone SDK integration
A successful Check establishes that the selected source passed compiler analysis. Build compiles without executing main. Run produces execution output. These are different results, and an interview should not collapse them into one green success label. Ask the candidate what evidence a given action actually provides. An assertion failing during Run is useful information even when the source was perfectly well typed.
The extended MCP flow can ask a connected browser or app to execute selected operations. A human must explicitly allow those operations on that one client, after comparing the controller and client fingerprints. The browser user first prepares its verified compiler through Check. Merely joining the room, receiving an edit or opening a handoff link cannot start a compiler on another participant’s device. Keep the browser tab foreground while using its execution grant.
For Debug, inspect the real Summary value after the loop has processed a few items. String and Vec previews, concrete local structures, source stepping and owned Stop make this an exercise in prediction: what changes on the blank line, and what stays unchanged on a shorter label? Values are bounded previews from the executing Rust program. They are not arbitrary watch expressions or a replacement for understanding ownership.
Explore in Crabrix: Local Debug guide
Why does the function accept &[&str] rather than take a vector of owned strings? Which value owns each accepted label, and when is that owner needed? Why is to_owned used at the point where the longest output changes? A good answer relates the function’s input and output lifetimes to the caller’s needs. Naming ownership vocabulary without explaining the particular values in this program is much weaker evidence.
Then change one requirement. Suppose the result must retain every accepted label, not only the longest. Would the output own strings or borrow slices, and how would that affect the function signature? Either design can be reasonable under a clear caller contract. Ask the candidate to describe the tradeoff before coding it. This makes lifetimes and allocation decisions concrete rather than treating them as a puzzle about compiler syntax.
Another useful variation is to return a borrowed longest label while still owning the rejected line numbers. Ask what information a lifetime annotation would communicate and what it would not do. It does not keep an already destroyed input alive or turn a temporary string into permanent storage. A short explanation connected to this specific task is more revealing than a memorized slogan about the borrow checker.

Explore in Crabrix: Ownership Mastery course · Ownership in a real program
Not every Rust interview needs Tokio. A small synchronous task can reveal careful API design, text handling and error reasoning without spending the meeting preparing a dependency graph. The web Playground and shared MCP execution currently accept standard-library Rust and local source modules. They do not resolve arbitrary Cargo dependencies, run host procedural macros or turn a shared source room into a general server environment.
If the role requires async Rust, use the task to discuss cancellation, ownership across suspension and lock scope, then choose the appropriate environment for a separate executable exercise. The native Crabrix app has its own supported offline Cargo and current-thread Tokio profiles. That is a different project mode from the small shared execution snapshot. Do not infer that a browser can execute any Tokio repository merely because all the source is written in Rust.
Make the boundary part of the evaluation: ask the candidate what a test proves and which assumptions remain untested. Handling a request inside a router is different from opening a TCP listener. A successful program on one target is different from a guarantee about native threads or operating-system services. These distinctions are useful engineering judgment, and a reliable interview environment should help explain them rather than hiding them behind a vague Run button.
Explore in Crabrix: Concurrency and Async course · Cancellation and timeouts
A final output line is only one part of the assessment. Ask the candidate to predict the state before running, identify the input that would disprove a claim, and explain a chosen representation. If an assistant wrote part of the function, have the candidate describe that part without asking the assistant again. This distinguishes productive collaboration from unexamined acceptance of generated code.
Keep a short review checklist tied to the task: stated Unicode unit, stable tie rule, correct blank-line handling, deliberate one-based reporting, ownership of the output, and meaningful boundary cases. The checklist should support consistent assessment, not become a secret scoring rubric that changes after the candidate has committed to an approach. It is reasonable to accept a different implementation when it satisfies the same contract and the candidate can justify it.
When a failure occurs, preserve its context. Was it a compiler diagnostic, a runtime assertion, an expired room, a full participant list or an execution permission that was never granted? Those causes require different next actions. A candidate who reads the actual stage and asks the right question is demonstrating more useful skill than someone who repeatedly restarts the same operation and hopes the status changes.
Before the room expires, save a source ZIP or a local Crabrix project. A temporary room is not repository hosting, an account project or a durable backup. Its relay stores bounded ciphertext in process memory, and a restart can end the room earlier than the chosen deadline. Keeping an independent copy is part of closing the exercise, especially when the final source includes notes that participants want to revisit.
If another agent will review the result later, explicitly request a handoff link while the room is still live. Include its expiry and the current revision in the surrounding explanation, but do not put the capability in the source itself. An ordinary joined edit participant is not the room owner; creator-only closure is retained. An agent leaving the room releases its own connection without automatically removing the candidate’s or interviewer’s access.
End the session with a brief account of what was verified and what was only discussed. For this example, that might mean the standard-library program ran with the stated assertions, the candidate explained its allocation boundary, and a borrowed-output variant was considered but not implemented. That is a useful result someone else can understand. The shared editor has done its job when it makes the reasoning and evidence easier to inspect.
Explore in Crabrix: Save and recover projects · Browse Rust lessons