# The client asked me to run their repo. I read it instead.

> Source: <https://dev.to/automate_ai/the-client-asked-me-to-run-their-repo-i-read-it-instead-126>
> Published: 2026-08-12 16:40:35+00:00

A client I'd been talking to for two days sent me a link to their codebase. Clone it, `npm install`

, `npm start`

, then send back a screenshot of the landing page and your thoughts on the architecture. Friendly message. Reasonable-sounding request. We'd get on a call after.

I didn't run it. I want to explain why, because the reasoning generalises far beyond this one repo, and because the request was built so that running it looked like the only way to cooperate.

Read that request again and notice which part can't be faked.

Feedback on the architecture? I can give that by reading the code. Opinion on the landing page design? Also readable: the markup and the styles are right there. Strengths and weaknesses of the project? Reading, again.

The screenshot is the only deliverable in that list that **requires executing their code on my machine**. Everything else I can produce with my eyes. And the screenshot was framed as the deliverable that mattered — the thing to bring to the call.

Once you see it, you can't unsee it. The request isn't "help us evaluate our work." The request is "please run this."

My machine holds wallet keys, API tokens, and live browser sessions for every account I work with. A `postinstall`

hook or a compromised dev server gets all of it in the time it takes for the install to finish. This is the well-documented fake-recruiter pattern — it has drained a lot of developers who assumed a client repo was a safe repo.

So the rule I work by: **read a stranger's repository, never execute it.** Not `npm install`

, not `npm start`

, not "just to see how it looks."

Here's what surprised me the first time I did this properly: reading found more than running would have.

Running the project would have shown me a landing page. A landing page tells you almost nothing. It's the part that's easiest to buy, copy, or commission for $200. Reading told me what the project actually was.

I pulled the file tree from the host's API and fetched individual files as raw text. No clone, no dependency install, no execution. It took about forty minutes.

**The contracts didn't work.** This was a DeFi project, so the contracts are where the money lives and where I look first. The staking function transferred the user's deposit to the zero address instead of holding it in the contract. With a standard OpenZeppelin token that call reverts, so staking simply couldn't happen; with a permissive token, every deposit would burn permanently. The reward function took the payout amount as an argument from the caller. Anyone who had ever staked could ask for any number and the contract would pay it. No accounting, no cap. Another function handed out tokens to whoever called it, unlimited.

These aren't subtle bugs you find with a fuzzer at 3am. They're visible on a first read.

**The project wasn't what its README said.** The README described a decentralised exchange with pooling, liquidity and an AMM. The contracts were a tutorial-grade staking demo with placeholder names. The frontend shipped assets belonging to a different, real product. And under all of it sat a generic e-commerce backend — routes for products, orders and payments, database models for Category, Warehouse and Dispatcher. Nothing in that backend had anything to do with a token or a trade.

**The history was one commit.** A single "initial commit", dated three weeks earlier. No development history at all. And `.env`

was tracked in the repository. Empty values today, but the moment someone fills them, the credentials live in git history permanently.

None of that required running anything.

This takes ten minutes and costs nothing:

`package.json`

scripts first.`postinstall`

and `preinstall`

run automatically the moment you install. Read what `start`

actually launches. In this repo it started a whole server I hadn't looked at yet.`.env`

files, credentials, one file far larger than its neighbours, obfuscated blobs.Read files as raw text through the host's own API. GitHub, GitLab and Bitbucket all serve raw file contents and directory listings over HTTP. Text can't execute.

Refusing doesn't have to cost you the client. What I offer:

Every one of those gets a genuine client exactly what they said they wanted. None of them puts their code on my machine.

And that's the part worth internalising: the refusal is a filter, not a loss. A real client doesn't care which of those three you pick. They wanted the feedback, and they're getting it. The only person who insists on the local run is the one for whom the run *was* the point.

There's a second thing going on here, and it's quieter.

An architecture review, a security read of a contract set, an assessment of what to fix and in what order: that is consulting work, and it's the thing clients pay for. "Just take a quick look and tell us what you think" is a request for that work, unpriced, dressed up as a formality before the real engagement starts.

I did write up my findings for this client, in detail and for free. One time, and for one reason: I was reading the code anyway to decide whether it was safe, so the security check and the review were the same hour of work. I sent the findings, said plainly what I'd charge to go further, and stopped there.

That's the boundary I'd suggest to anyone doing this work. One free read, if it happens to coincide with your own due diligence. Then a number.

I sent the client the findings — the zero-address transfer, the caller-supplied reward amount, the mismatch between the README and the code, the committed `.env`

. I explained why I don't run unfamiliar code, asked for a deployed URL instead of a screenshot, and asked two direct questions: what in this repository is meant to be yours, and are we fixing this or building the real thing?

I don't know yet how it ends. Either the client turns out to be real, in which case I'm the only candidate who opened the code and told them the truth about it. That is a much better position than the one where I sent a screenshot. Or they disappear, which answers the question just as well.

Either way I didn't run it.
