Mateusz Śliwa

Data and AI engineer who ships mobile apps.

Zielona Góra, Poland. Open to remote or hybrid roles and to relocation. Available now.

MSc in Data Engineering, University of Zielona Góra, 2026. English C1, Cambridge C1 Advanced (2025).

I build with coding agents: Claude Code, Codex and Cursor.

This is my phone. Every app on it opens a working demo of the project. Drag the bar at the bottom up to flip through them as cards.

Download CVGitHubsliwa.mateo@gmail.com

On the App Store: EcoSort and TrueSky. EcoSort's website is ecosort.pl.

Jutro

Wystaw dziś: Odpady bio, Papier
Odpady bioPapier

Projects

Each card opens the full story: what the project does, what was hard and what I built.

EcoSort, on the App Store

A photo of a printed bin calendar, read one month at a time

EcoSortWaste collection dates for your street

EcoSort shows which bins go out on your street and when. It reminds you the evening before, and the widget and the lock screen show what is next.

The hard part is the data

Every municipality publishes its schedule differently. Many publish a scan or a phone photo of a printed calendar: twelve months on one page, colour-coded days and a legend in the corner.

The obvious approach is to give a model the whole page and ask for the dates. On six hard scans the best version of that prompt got 24.5% of the cells wrong. A page holds hundreds of similar numbers, and where the model can't see each day clearly it fills in a regular pattern. In Wiśniew bio waste goes out once a month. The whole-page prompt returned it every week.

How the pipeline reads it

  1. Cut the page into monthsThe model marks the month frames, code moves the borders into the empty space between them, and a crop is rejected if its last visible day is wrong.
  2. Read each piece twiceTwo prompts read every month, with the legend attached. Tables get a second image with the columns spread apart.
  3. Break ties by majorityWhen the two reads disagree, a third read decides.
  4. Let code check what is certainSundays, public holidays, gaps in the rhythm, row counts, and that every address in the national register falls into exactly one zone.
  5. Hold back instead of guessingDoubt that the reads can't settle holds the zone back. A missing schedule is safer than a wrong date.

Results

Six scans and photos with 2,190 cells. The pipeline read each of them in three full runs, 6,570 cell results in all. A cell is one place, one waste type and one month, and it only counts as right if every day matches the document.

One prompt75.5% right, 24.5% wrong
Pipeline82.2% right, 17.8% held back, 0% wrong

Green is right, red is wrong, grey is held back. The ground truth is 966 decisions I made by hand in the admin panel. The pipeline was tuned on these documents, so zero wrong dates is its best case, on documents it already knows. Documents it has not seen are the next test.

DocumentCellsPrompt wrongPipeline wrongHeld back
Gierałtów, photo12057.2%00%
Czerna, photo11286.9%00%
Wykroty, photo12076.7%00%
Wiśniew, scan14777.8%033.3%
Szprotawa, sideways scan2641.0%074.2%
Klimontów, three-page scan of tables1,42711.3%010.1%
All six2,19024.5%017.8%

It is not better everywhere: in Szprotawa the prompt was nearly right and the pipeline held three quarters back. It also costs more: one call and about 25 seconds per document for the prompt, against a median of 33 calls and 4.5 minutes.

Open the Report demo

What I built

  • The iPhone app in SwiftUI, with widgets, a Live Activity, reminders you can snooze or mark as done, and a schedule that works offline.
  • An Android app in Kotlin and Jetpack Compose. It is built and not yet on Google Play.
  • The backend in FastAPI and PostgreSQL: address search against the national TERYT register, schedules served as static JSON.
  • The reading pipeline in Python with OpenCV, Tesseract, PyMuPDF and Gemini, and an admin panel in React and TypeScript.
  • Sortuś, an assistant that answers questions using the resident's own schedule.

Six municipalities are published in the app. EcoSort on the App Store. The website is ecosort.pl.

App Store screenshot: your collection scheduleApp Store screenshot: a countdown to each collectionApp Store screenshot: a reminder the evening beforeApp Store screenshot: the month calendarApp Store screenshot: widgetsApp Store screenshot: Sortuś the assistant

Each project also has its own page: mateuszsliwa.dev/ecosort.

Keenwit, in development

A brain game where the server keeps the score

KeenwitTry two games: Equinox and Star Sectors

Keenwit is a daily brain workout: 43 short games for memory, maths, language and focus, with streaks, duels and leaderboards. Difficulty adapts to each player. The name is a working one.

Why the server keeps the score

You can play offline, so the phone can't be the judge. A finished game waits in an outbox on the phone, and nothing moves XP, a streak or a ranking until the server has checked it.

  1. One-time seedSeeded games get a seed from the server. A replayed, expired or mismatched seed is rejected.
  2. Time windowThe result may be at most 5 minutes in the future and 30 days old, so games played offline still count.
  3. Rate limitPer client.
  4. Score normalised on the serverVery high scores need extra proof.
  5. A verdictAccepted, held for checking, or rejected. Only accepted results earn XP.

Prime Check: the server holds the answers

For this game the server goes one step further. It generates the questions, keeps the answers and sends the phone only the numbers. The phone plays them offline and sends back what you tapped. The server recomputes the score from its own copy and ignores the score the phone claims. This is the only game with that check so far.

The demo: two games

The phone has two of the 43 games. In Equinox you fill a grid with planets and comets: never three alike in a line, half of each, and the = and × links must hold. Star Sectors is the Queens kind of puzzle: one star in every row, column and colour sector, and stars never touch. Both use the app's own rules, boards and scoring. Each tutorial starts with the app's steps, then moves to a bigger board for the techniques that solve it: a sector stuck in one row, a gap between two alike, a full count.

Play them in the phone

How it is built

React Native with Expo, TypeScript and Skia, on a Fastify and PostgreSQL backend with JWT auth and an OpenAPI spec.

Keenwit home screenA logic game in KeenwitDuels in KeenwitThe game catalogue

Each project also has its own page: mateuszsliwa.dev/keenwit.

TrueSky, on the App Store

Weather you read from a painting

TrueSkyPainted weather, free with a Pro plan

TrueSky draws the weather as a painted landscape. The hourly forecast from Open-Meteo sets the light, the clouds, the wind and the rain, and the scene plays the matching sound.

How the scene works

Each landscape is a stack of painted layers: mountains, water, the shore, a cabin, a birch and a boat. Skia shaders light them for the hour, from first light to a quiet night with lit windows, drift the clouds with the wind and add rain, snow, fog or a storm. I kept it at 120 Hz by cutting the work done on every frame.

Try the fjord in the phone

The business side

The app is free. TrueSky Pro adds landscapes and details for 21.99 zł a month ($7.99) or 55 zł once ($19.99), sold through RevenueCat. It is translated into 32 languages and sends weather alerts in the background. It has been on the App Store since 9 October 2026.

Expo, React Native, Skia, Reanimated, RevenueCat, Playwright for the web build.

TrueSky, the meadowTrueSky, the fjord at nightTrueSky, Paris rooftopsTrueSky, the forecast details

Each project also has its own page: mateuszsliwa.dev/truesky.

wwxd, open source

What would X do? Answers in that person's own words

wwxd answers "what would X do?" from one person's own words. It ingests their public captions, podcast transcripts and articles, turns them into a wiki of their positions, and an agent answers with timestamped quotes from those sources.

Every quote is checked

A model can misquote someone, so a script looks up every quote in the transcript it came from. In the benchmark it found 158 of 160 cited quotes word for word. The two it missed were video titles.

Does it beat plain Claude?

On 40 questions over two wikis, a blind judge compared each wwxd answer with an answer from plain Claude. The judge came from another lab, Google, and had no access to the transcripts. It preferred wwxd on 34 of 40. Judges from three more labs, Anthropic among them, scored the same pairs and preferred wwxd at least as often. Claude with web search did no better: the judge from Google again preferred wwxd on 34 of 40.

On 24 opinion questions, a prompt that told the model to answer as the person contradicted that person 8 times. The wwxd answers contradicted them 0 times.

Ask a panel

Panel mode asks several people at once. Each answers from their own wiki. wwxd then maps where they agree, where they split and why, runs a debate round labelled as inferred, and ends with a synthesis. Answers read as prose, with the sources listed underneath.

What it can't do

It does not predict opinions a person hasn't voiced yet. I held back positions people took in 2026, and wwxd guessed them no better than plain Claude. It knows what someone has said, not what they will say next.

wwxd on GitHubOpen the demo

How it's built

A Python command-line tool and a Claude Code plugin, built in October 2026 under the MIT licence. The design follows Andrej Karpathy's "LLM wiki" idea. It can transcribe audio locally with faster-whisper and check by voice who is speaking. On 12 October 2026 it had 135 tests, which run in CI on Linux, macOS and Windows.

Python, Typer, yt-dlp, trafilatura, rapidfuzz, faster-whisper, Claude Code.

Each project also has its own page: mateuszsliwa.dev/wwxd.

unslop, in development

Posters for small businesses, made without image generation

unslop (working name) makes posters and social media graphics for small businesses without image generation. Every letter is set in a real font, and every photo is real: the owner's own or licensed stock. It is in development, and the code is private.

Before and after

Each "before" below is a flyer a small business posted, made with an image generator. The generator draws letters as pixels, and one headline came out as "AMAZINIG". Each "after" is the same message made with the tool, where the text is typed copy set in a font.

Route 88 Grill and Bar, a grand opening flyer: the AI-generated original and the Instagram post made with the toolBlackpool Rocks party weekends: the AI-generated original and the Instagram post made with the toolA village hall summer fair: the AI-generated original and the Instagram post made with the toolThe Kings Head Summer Vibes line-up: the AI-generated original and the Instagram post made with the toolA Polish infographic about compromises between children: the AI-generated original and a six-slide carousel made with the tool

The "before" posters are real AI-generated flyers posted by small businesses; they belong to their owners and I'll remove any on request.

Compare them in the phone

How it works

  1. The agent writes a specA small JSON file with the layout, the brand colours, the copy and a real photo, the client's own or licensed stock.
  2. A renderer draws itHTML and CSS in Chromium through Playwright. The same spec always gives the same image.
  3. A linter checks the pixelsIt measures the rendered image: text that doesn't fit, overlaps, contrast against the real background, text hidden behind the subject, a price that doesn't show, the parts of a Story that Instagram's buttons cover, upscaled photos and missing glyphs.
  4. The agent fixes what it reportsIt changes the spec, and the renderer draws it again.

What it makes

In October 2026 it has 20 layouts and 15 visual directions. It exports Instagram posts in 4:5 and 1:1, Stories in 9:16, and A4, A3 and B2 print PDFs with bleed and embedded fonts. Stock photo search covers Unsplash, Pexels, Pixabay and Openverse and keeps the credits. Background removal runs locally, on the CPU.

An editor for the owner

The shop owner clicks any text to change it. Four big buttons change the layout, the colours, the photo and the copy, and one click downloads every format. An optional assistant runs on the Anthropic API with streaming and a cached system prompt, and every answer shows what it cost.

How I work

I build with coding agents, and I know how to set them up

Claude CodeCodexCursorMCPskillssubagentsprompt caching

Most of these projects were built with coding agents. I use Claude Code, Codex and Cursor side by side, follow new models and features as they come out, and try them on my own projects before I rely on them. Most of my commits since September 2026 name Claude as co-author.

Context the agent reads first

  • A global policy for every agent: find the existing pattern before adding code, keep one source of truth, fix root causes, report only checks that actually ran. The card above quotes it.
  • Repository instructions in AGENTS.md and CLAUDE.md with each project's commands and pitfalls, in Keenwit and the EcoSort pipeline.
  • Skills for repeatable jobs, in one folder that Claude Code and Codex share. Two are mine: mac-ios for building and testing iOS apps from Linux, and store-screenshots for storeshots.
  • Subagents for work that splits well: parallel searches, implementation, an independent review and a final check.

Cost, caching and limits

Stable instructions go first and stay unchanged, so prompt caching can reuse them, and the parts that change go last. I watch token use and rate limits. Sortuś, the EcoSort assistant, runs on a pool of API keys with daily quotas, per-user limits and a Gemma fallback.

Tools I build for agents

  • storeshots prints JSON for every command, and its errors say what broke, how to fix it and which command to run next. Both tools ship with an agent skill.
  • macsim gives an agent on my Linux PC a real iOS Simulator on a Mac: it builds the app, taps through it and takes screenshots. Open source, like storeshots.

Checking what comes back

An answer from a model is a draft until something checks it. In EcoSort that means two reads, a third when they disagree, code checks and an evaluation against 966 decisions I made by hand. In Keenwit the server checks every result before it counts. Code from an agent gets the same treatment: tests and review before it ships.

Models inside my apps

  • EcoSort's reading pipeline uses a small Gemini model on one month or one table section at a time. The accuracy comes from the pipeline around it.
  • Sortuś answers from the resident's own schedule on Gemini, with personal data scrubbed from the conversation.

Claude Code, Codex, Cursor, MCP, skills, subagents, Gemini, Gemma.

University of Zielona Góra

Who wins this round? My MSc thesis, and a skin lesion classifier

MSc in Data Engineering, specialising in data mining systems (2025–2026), after a BA in Economics (2021–2024), both at the University of Zielona Góra.

Thesis: win probability in Counter-Strike 2

A model that gives the probability of winning a round, second by second. I downloaded professional match recordings with Selenium, parsed them with demoparser2 and built the features in pandas: 9,196 maps, 187,361 rounds and 16.8 million game states.

I compared nine models, validated by match groups and walk-forward by quarter, with bootstrap tests, ablations, calibration and SHAP. Gradient boosting came out best: LightGBM log loss 0.527, ROC-AUC about 0.81–0.82 in the quarterly walk-forward tests, and an expected calibration error (ECE) of 0.0086 for the production XGBoost model. Predictions are served by FastAPI to a React app.

All nine models, five-fold cross-validation grouped by match, so rounds from one match never land on both sides. Lower log loss and Brier are better.
ModelLog lossROC-AUCBrier
LightGBM0.52670.80360.1790
CatBoost0.52720.80590.1786
XGBoost (production)0.52890.80170.1800
Random forest0.52950.80350.1797
MLP0.53230.80160.1807
Extra trees0.53320.80430.1805
Logistic regression0.55180.79180.1858
Linear regression baseline0.59190.78890.1891
Ridge classifier0.60440.78890.2074
Walk-forward by quarter: train on every earlier quarter, test on the next one. With little history, in 2024 Q1 and Q2, the model is weaker; from 2024 Q3 on, XGBoost stays at 0.81–0.82. Here XGBoost has fixed settings (300 trees).
Test quarterTraining mapsLogistic AUCXGBoost AUC
2024 Q18440.73020.6498
2024 Q21,4480.79730.8049
2024 Q33,5190.80050.8140
2024 Q45,3150.80320.8183
2025 Q15,9990.80510.8217
2025 Q26,4570.80380.8190
2025 Q37,1720.79800.8119
2025 Q47,8280.80160.8142
2026 Q18,7700.79560.8094

Read the thesis in 5 minutes

The thesis app replaying a round on Mirage with the win probability bar and its curve over time
The thesis app replays a round on the map radar, with the win probability over time.

Skin lesion classifier

A machine learning course project on the HAM10000 images: malignant or benign. A custom CNN against a fine-tuned EfficientNet-B0 in PyTorch, with Optuna, focal loss, a weighted sampler, MixUp and test-time augmentation, plus Grad-CAM to show where the model looks. On 1,002 test images EfficientNet reached an AUC of about 0.93 and a malignant recall of 0.95; the custom CNN reached an AUC of 0.755. Tracked in MLflow, served in Streamlit.

Open the classifier demo

Each project also has its own page: mateuszsliwa.dev/thesis, mateuszsliwa.dev/skin.

Tools I built for my own releases

storeshots and macsim, both open source

Two tools that came out of shipping apps alone, from a Linux PC, with coding agents doing a lot of the typing.

storeshots

An open-source command-line tool that makes App Store screenshots from the running app. It captures the app in the iOS Simulator, lays the screens out as slides in HTML and CSS, renders them at the exact sizes Apple asks for, checks them on the rendered pixels (sizes, alpha, text size, cut-offs, contrast) and uploads them through the App Store Connect API. Every command prints JSON, so an agent can drive it. The EcoSort screenshots above and on the App Store were made with it.

storeshots on GitHubOpen the demo

macsim

I write code on a Linux PC, and iOS builds need a Mac. macsim turns a Mac on the network into a remote build server and iPhone Simulator. One command syncs the project over SSH, builds it with xcodebuild or Expo, installs it and launches it, while Metro keeps running on the PC with hot reload. An agent on the PC can tap, type and take screenshots in the Simulator, and I can watch it live in a browser. It ships with an agent skill for Claude Code and Codex, and I used it for the TrueSky and Keenwit builds.

macsim on GitHubOpen the demo

Each project also has its own page: mateuszsliwa.dev/storeshots, mateuszsliwa.dev/macsim.

Write to me

sliwa.mateo@gmail.com. CV in English or Polish.