cd /news/artificial-intelligence/you-can-t-ask-the-dead-what-they-lef… · home › topics › artificial-intelligence › article
[ARTICLE · art-161115] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=↑ positive

You can't ask the dead what they left behind, so I built a way to find out

A developer built Ghost Money, an open-source tool that searches the State Bank of Pakistan's 782 published unclaimed-account lists — 14.3 million rows spanning 2003 to 2025 — for names of deceased account holders. The system normalizes variant spellings such as MUHAMMAD RASOOL, MOHD. RASUL and M. RASOOL into consonant-skeleton index shards so searches run client-side, scores candidate rows with TabPFN and a Gemma second opinion, and drafts a claim letter; after filtering duplicates, company accounts and unusable names, it indexes 12.6 million personal accounts holding Rs 50.7 billion.

by read8 min views1 publishedOct 30, 2026

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine I ran this on my late father's name, and it found his account.

When a bank account in Pakistan sits untouched for ten years (fifteen since 2024), the bank hands the money to the State Bank of Pakistan. The State Bank then publishes the account holders' names, one Excel file per bank per year, so that families can come and claim it. Most never do. The people in those files are mostly older, many of them have died, and their children don't know the account existed.

The lists are public, but they are hard to use. There are 782 files going back to 2003, with 14.3 million rows between them. One file alone has 530,000. The same man appears as MUHAMMAD RASOOL, MOHD. RASUL S/O ALLAH DITTA, and M. RASOOL, and the only search tool a family has is Ctrl+F, one file at a time.

Ghost Money is a page where you type the name of someone you've lost, in English or Urdu, and it searches every list at once:

My reading of the theme: Día de los Muertos is about remembering the people who came before you. Ghost Money is a small, practical version of that for Pakistani families. The ghost in the machine is the money still sitting in the State Bank's spreadsheets under the names of people who are gone.

Live: https://ghostmoney.onrender.com. Try "Ghulam Rasool" to see what happens with a common name, or describe someone in Roman Urdu on the second tab. The live demo holds the 2023 to 2025 lists so it fits a free server, so its counts are smaller than the full index described below. The README has the steps to build the full one. Every real row is blurred in these screenshots, because the people in the lists are real, even though the lists are public.

Find money your late relatives left behind in Pakistani banks.

When a bank account sits untouched for 10 years (15 since 2024), the bank hands the money to the State Bank of Pakistan, and the State Bank publishes the account holders' names in yearly Excel lists, one file per bank. Most families never look, and the ones who do get Ctrl+F on hundreds of files where one man is MUHAMMAD RASOOL, MOHD. RASUL S/O ALLAH DITTA and M. RASOOL.

Ghost Money searches every list from 2003 to 2025 at once, handles the spellings, scores each row with TabPFN, asks Gemma for a second opinion, and drafts the claim letter.

Python (FastAPI) on the server, plain JavaScript in the browser, MIT licensed. The README has the steps to rebuild the whole index from the State Bank's own files.

The data. I downloaded all 782 files from the State Bank's year-wise page: 756 came through. The other 26, all 2022 CSV files, are blocked by the State Bank's firewall even in a normal browser. Over 23 years the banks used different column names, sheet layouts and formats (xls, xlsx, csv, zip), so the parser finds each sheet's header row by keywords and maps it to one schema. In the end: 14,288,663 rows. I removed 59,209 repeats (the same account listed again in a later year), set aside 1,411,289 company accounts and 198,541 rows with no usable name, which left 12.6 million accounts in people's names, holding Rs 50.7 billion when they were listed. One download failed partway without saying so (HBL 2022, the biggest file of all), which I only caught when the parser choked on it.

Finding someone without seeing their name. The privacy idea is the core of the design. Every row is filed into one of 4,096 index pieces according to the consonant skeleton of its uncommon name parts, so RASOOL, RASUL and رسول all land in the RSL piece. Your browser works out those keys itself, downloads only the matching pieces (each holds thousands of names), and does all the comparing on your device. The server sees a piece number. CNICs aren't republished either: each row carries a salted hash, and the CNIC a family types is hashed and compared in the browser.

TabPFN scores the match. For each candidate row the browser computes twelve numbers (how many name parts agree, whether the first name matches, how similar the letters are, whether the father's name and province agree, how common the name is in the lists) and sends only those numbers to TabPFN. TabPFN learns in context from 3,000 labelled pairs, so there is no training run to maintain.

The labels come from the lists themselves. When two rows share a 13-digit CNIC they are the same person, however the clerk spelled the name. Two thirds of rows (8.4 million) carry a CNIC, and tens of thousands of CNICs appear under two or more spellings. For the "different person" side I used two kinds of look-alikes: rows that share a spelling key, and "name twins" with the identical name but a different CNIC.

Gemma runs on your machine. On the live site, Gemma 4 E2B runs inside the browser tab through WebLLM. When you run Ghost Money on your own PC, it uses Gemma 4 E4B through Ollama. Gemma has three jobs, and code checks each one:

Gemma's job What code checks
Turn a description into search fields Names must look like names. A CNIC is kept only if those digits appear in what you typed. Provinces come from a fixed list.
Second opinion on the top matches Only rows it was shown, only "likely / maybe / unlikely". It is shown separately from TabPFN's score, never instead of it.
The personal paragraph of the claim letter Any digits are stripped. Every name, amount, date and account number in the letter is filled in from the list row by code.

Code checks the model too. If the family gives a father's name and the row shows a clearly different one, the row is set aside whatever the score says. If the CNIC hash matches, the row goes to the top.

All numbers below are from the held-out test set: 11,036 pairs, split by CNIC so no person appears in both training and test.

Is the right account ranked first? Each test search has one true row and up to four look-alikes.

Method Right account first When the father's name is on both records
Ctrl+F (what families do today) 51% 62%
Fuzzy text match 62% 73%
TabPFN on 12 numbers 77% 99% (85 searches)

Does Ctrl+F find the person at all when the clerk spelled the name differently? (1,488 such pairs)

Method Found Of its hits, really the person
Ctrl+F 30% 24%
Fuzzy match (80% similar) 71% 26%
TabPFN 50% 57%

When TabPFN says it's sure, is it?

TabPFN score Pairs Really the same person
0.9 or more 373 96%
0.7 to 0.9 442 79%
0.5 to 0.7 1,041 58%
below 0.3 7,736 6%

How long does a search take? These are the page's own timers from one recorded search for Ghulam Rasool, son of Allah Ditta, on my PC with the full index. The times are what each step reports on screen.

Step Where it runs Work Time
Work out the spellings Browser RSL, 1 index piece 0.0 s
Download the piece Browser 51,122 rows 0.3 s
Compare every row Browser 51,098 share a spelling, closest 250 kept 1.3 s
Score the candidates TabPFN 250 rows, 106 set aside because the father's name differs 1.7 s
Second opinion Gemma, on my PC Top 5 sent, 1 verdict came back 3.6 s

Gemma is the slowest step and the least reliable: in this run it gave a verdict on only one of the five rows it was shown. That is why its opinion is shown beside TabPFN's score and never replaces it. If Gemma isn't loaded, the page skips the step and the search still works. Describing someone in Roman Urdu on the second tab is slower, because Gemma has to read the description first: one run took 75 seconds from clicking search to seeing results, with the name and father's name filled in correctly.

The tables above come from pairs of rows. The test I cared about was simpler. I searched for one person I actually know to be gone, my late father, and it found his account. The name, amount, CNIC and letter are blurred below because they are his.

This is one search by one family, so it says nothing about how often the page works for anyone else. It only says the money is really there to find, and that the page found it for someone who wasn't testing a sample name.

These are the known limitations, and the page doesn't hide them:

The people using this are searching for a dead parent's name and CNIC, often alongside a story about them. That shouldn't go to anyone's API. With open models it doesn't have to: Gemma runs in the browser tab or on the family's own PC, TabPFN sees twelve numbers per row, and the search runs on pieces of a public index. A closed model would have meant sending the most private part of the search to a third party.

It also lasts. The State Bank's lists are public, and so are the parser, the index builder and the models' weights. If my server goes away, anyone can rebuild the whole thing from the README.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @state bank of pakistan 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/you-can-t-ask-the-de…] indexed:0 read:8min 2026-10-30 · —