Skip to content

Instantly share code, notes, and snippets.

@vdavid
Last active April 8, 2026 18:06
Show Gist options
  • Select an option

  • Save vdavid/a7e4cd5a7ca4e2208f5171748cedc3ca to your computer and use it in GitHub Desktop.

Select an option

Save vdavid/a7e4cd5a7ca4e2208f5171748cedc3ca to your computer and use it in GitHub Desktop.
Claude Code detective game: which SMB library was vibe-coded vs human-built?

Can Claude tell which SMB library was vibe-coded?

Two Rust SMB client libraries. One built by a human over a year, the other vibe-coded in a day by someone who didn't know much Rust. Claude Code tries to figure out which is which, just by reading the code.


David: I have /tmp/smb2/ and /tmp/smb-rs/, two libs for the same thing. One of them is written with hard human work over 1 year, the other one is vibe coded in a day by someone who didn't even know much Rust. Without looking at .git and the file dates, and not using any subagents to do research work, WDYT, which one is which, based on code quality and lib usability?

Read like 1-1 files of each lib at a time, then speak out your thoughts-in-progress loud so I understand where you are in the process of figuring it out :)

Claude: This sounds like a fun detective game! Let me dig in, one file at a time from each.

Let me start with the top-level Cargo.toml of each to get a feel for project structure and dependency choices.

[reads both Cargo.toml files]

First impressions from Cargo.toml:

  • smb2: Single crate, v0.1.0, minimal deps. Hand-picked crypto primitives (hmac, sha2, aes, cmac...). Has proptest, deny.toml, clippy.toml, rustfmt.toml -- tooling that screams "I care about quality". No proc macros, no code generation.
  • smb-rs: Multi-crate workspace with 8 internal crates + a CLI, v0.11.1. Uses binrw for binary encoding, custom proc-macro derives (smb-msg-derive, smb-dtyp-derive), maybe-async for sync/async flexibility, TLS via quinn/rustls. Edition 2024.

Hmm. smb-rs has a LOT more structure. Could be over-engineering from vibe coding... or could be proper separation of concerns from someone who knows the protocol deeply. Let me look at actual source code.

[reads both lib.rs files]

Thoughts so far:

smb2's lib.rs is gorgeous -- #![forbid(unsafe_code)], #![warn(missing_docs)], a complete working example in the doc comment, and a beautifully curated public API with clear labels ("advanced/internal use"). The top-level API is dead simple: smb2::connect("host", "user", "pass").

smb-rs has more features (sync+async via feature flags, DFS support, TLS) but does glob re-exports (pub use smb_dtyp::*) which is generally considered less clean. No warn(missing_docs).

Let me look at the actual protocol-level code -- the message/packet definitions. That's where you really see if someone understands SMB.

[reads header.rs from both projects]

This is getting really interesting. Two very different philosophies:

  • smb2: Hand-written Pack/Unpack with meticulous byte-by-byte comments. Strong newtypes everywhere (CreditCharge, MessageId, SessionId). 11 unit tests for just the header alone, covering roundtrips, error cases, edge cases.
  • smb-rs: Leverages binrw for declarative binary parsing, custom proc macros, modular_bitfield for flags. A clever make_status! macro that generates the enum + Display + TryFrom + const u32 values all at once. Much more concise but only one test (a single hex roundtrip via test_binrw! macro).

The proc macro approach in smb-rs is sophisticated Rust. But smb2's test coverage is way more thorough. Let me look at the higher-level client code to see how the actual SMB session logic works.

[reads both client modules]

Wow. smb2's client module is extensively documented and tested -- mock transport, full protocol message builders, NTLM challenge construction, reconnection tests, streaming download/upload with progress, compound requests, file watching. That's ~950 lines for just the high-level client interface.

The picture is getting clearer. smb-rs's client has:

  • Connection pooling by IP with Arc<Connection> + RwLock<HashMap>
  • Multi-channel support
  • DFS referral following
  • Uses sspi crate for proper Windows-style authentication
  • maybe_async for sync/async dual support

This is significantly more feature-complete. smb2 has better ergonomics, docs, and test coverage but fewer protocol features.

Let me look at one more dimension -- the pack/serialization layer, which is the plumbing that makes or breaks a protocol library.

[reads smb2's pack/mod.rs and smb-rs's proc macro crate]

OK, I've now read enough to have a clear opinion. Let me lay it out:


My verdict: smb-rs is the 1-year human effort. smb2 is the vibe-coded one.

Signs that smb-rs was built by a human over a year

  1. Custom proc macros (smb-msg-derive, smb-dtyp-derive) -- this is deep Rust investment. Nobody vibe-codes proc macros with syn and quote in a day. These eliminate repetitive boilerplate across dozens of message types, which is something you do when you're tired of writing the same pattern for the 30th time.
  2. Multi-crate workspace with 8 internal crates -- this kind of separation happens organically as a project grows. You don't start with 8 crates on day one.
  3. Deep protocol features: SSPI authentication, DFS referral following, multi-channel connections, alternate channels, TLS via QUIC, server/client feature gates. This is stuff you add when you actually run into real-world SMB servers that need it.
  4. Human typos in the proc macro docs: "utlities" and "re-exprorted" -- AI doesn't make these mistakes. Humans do.
  5. v0.11.1 -- 11+ releases of iteration.
  6. Uses _ prefix for private methods (_share_connect, _setup_multi_channel) -- a habit from someone coming from another language (Python?), which matches "didn't know much Rust" being false here -- they knew enough to write proc macros, but brought conventions from elsewhere.

Signs that smb2 was vibe-coded

  1. CLAUDE.md files in subdirectories and AGENTS.md at root -- these are David's conventions for AI-assisted development. The repo is github.com/vdavid/smb2. This is his project, built with AI.
  2. Pristine, exhaustive documentation with zero typos -- every function has a perfect doc comment, every byte has a comment. This is AI-generated text. Humans skip docs on internal methods; AI writes them on everything.
  3. Mechanical test patterns -- 11 tests for the header alone, each testing one thing in a very systematic way. It reads like an AI was told "write comprehensive tests for this struct."
  4. Hand-written Pack/Unpack instead of using binrw -- someone who knows Rust would use an established crate. An AI would happily write 200 lines of manual byte manipulation because it doesn't get bored.
  5. Single crate, v0.1.0 -- built in one shot, no iteration history.
  6. The API is too clean -- smb2::connect("host", "user", "pass") is the kind of API an AI designs when told "make it easy to use." It's genuinely great, but it's the polished surface over simpler internals.

The irony

The vibe-coded one (smb2) has better developer experience, documentation, and test coverage. The human-built one (smb-rs) has deeper protocol support and more sophisticated Rust patterns. Which is kind of the whole story of AI-assisted coding right now -- the surface quality is incredible, but the depth of domain expertise still comes from human experience with the protocol.


David: Nice :)

Claude: Thanks! That was a fun puzzle. The typos were the dead giveaway honestly -- AI is annoyingly perfect at spelling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment