Programs

FakeClients

A desktop app where AI plays the client: it drops a brief that matches conditions you set, negotiates changes over chat, and scores whatever you submit. I built it because portfolio practice needs the feel of a real client and I did not have one. 12 days in, so this is a running MVP, not a finished product.

2026In progressAI-assisted

Screenshots

3

Why I built it

The biggest gap in portfolio prep is not having a real client. You pick your own theme, satisfy only yourself, and never practice the actual freelance loop: requirements shifting, a deadline closing in, feedback landing on what you shipped.

Brief generators already exist, but what I wanted was not a single brief; it was everything that happens after you receive one. So I built my own version where an LLM generates a different brief for each condition you set, actually talks with you, and scores whatever you submit. It is completely free right now.

How a job runs

Pick a field (logo, web, illustration, UI/UX, dev, game, and others; 15 in total), industry, difficulty, budget, deadline, client personality, and country vibe (or leave everything random), and the LLM writes an email-style brief. A field or sub-task not on the list can be typed in directly, too; whatever you type is treated as data, never as an instruction, and the LLM is told to interpret it against how that kind of freelance work actually runs. From there you chat with the client in speech-bubble form, asking questions or getting event messages like "can you move the deadline up" depending on difficulty. Submit your work and it gets scored against field-specific criteria (brief fit, completeness, creativity, plus one criterion per field), then either approved or sent back for another round. Jobs pile up in an archive, and a stats screen shows completed count, average score, and completion trends by category.

CLI login instead of an API key

LLM access defaults to Claude Code CLI (subscription login), with Codex CLI (ChatGPT login) as an option; no API key required. With both connected, heavy calls (brief generation, feedback) and light calls (chat, summaries) can use different models, and if one side runs out of usage the other takes over automatically. The API-key path still exists in the code for a possible future public-service version, but it is unused today, which also means everything runs on subscription usage with no extra charge.

No server

Phase one is a pure local tool. There is no server: this PC talks directly to the LLM CLI and to an exchange-rate API (live lookup, falling back to the last cache on failure). User data (the archive, conversations, settings) lands as JSON in user_data/ next to the executable, and that path can be moved.

A privacy check before every release

I decided to ship only the executable and keep the source private. But a PyInstaller build can accidentally carry traces of the machine it was built on (account name, home path, git config) or stray personal files like user_data/ or settings.json. So before any release, a script unpacks the exe (down through the compiled bytecode archive) and checks for leftover source and personal identifiers; if anything turns up, the release stops. I did not want to repeat a mistake from another project (SteamAchieve) where a human eyeballing screenshots missed exactly this kind of thing.

Where it stands

Started 2026-09-17, so this is day twelve. Free-text field and sub-task entry (v0.3.0) is the newest addition; brief generation, chat, submission/feedback, the archive and stats screen, and settings all work end to end, but only the packaged executable is public and the source repository stays private. About 11,700 lines across 49 Python files, plus about 9,000 lines across 25 test files (585 passing).