I build systems that find the right companies, reach out to them, and keep the data clean. Startups get more pipeline, clearer signals, and more closed deals without hiring more people.I build systems that find the right companies, reach out, and keep the data clean. More pipeline, without more hires.
A client had no list of who to sell to. The audit told the story: a CRM with no scoring and no tiering, an ICP field empty on every record, and 0.19% of contacts in a sequence.
I rebuilt the targeting from their own wins. I studied their nine closed deals, worked out what a good customer looks like, then found every company like that in the market. Leads scanned at events now flow into the same system, no hands needed.
Every account in the market that could match the profile from the nine deals
Enriched
14,800
97.8% fully enriched, so the tiering ran on real data instead of blanks
Qualified
12,538
Sorted into three tiers by fit and priority
Disqualified
2,598
Out of market or too small
Contacts
11,560
Each with a verified email, sorted by tier and loaded into the CRM
The same build now tracks buying signals on every account and routes them to the right rep as tasks and Slack alerts.
Website visitorRB2BTask + Slack alert
Sales call insightsClayTask for the owner
Awareness score changeHubSpotTask + Slack alert
Champion trackingClayTask + Slack alert
LinkedIn engagementJunglerTask + Slack alert
Personal connectionsCSVTask, Tier 1 only
Customer alumniClayTask + Slack alert
Ad insightsFibblerCRM property
Three months in, every account carries a tier and eight live signals, and the rep who owns it hears about buying moments the day they happen.
S/002
Full GTM rebuild: TAM, signals, sequences
Clinical AI18 reps3 offices
A clinical-AI company had 18 reps in three offices selling on a platform that fought them: no parallel dialer, emails dying in a broken integration, and a target list nobody trusted. I had to rebuild the whole engine in parallel while the team kept selling on the original.
S/002fig. 002-amigration, zero downtime
The history came out first: years of call recordings were trapped inside with no export button, so I found a hidden way in and pulled about 9,000 files with one command. Along the way I caught a cleanup step that was about to rename real drug companies to Spotify. The rebuild took three months and runs nine systems deep:
fig. 002-bThe rebuild, in order
System
Value
What I built
Migration
0 days down
SalesLoft to Apollo through internal APIs; sequences, calls and tasks moved, history backdated
Recordings
~9,000
Every call the platform wouldn’t export, pulled out through a hidden route with one command
Target market
8,314
Every pharma, biotech and CRO that fits the ICP, mapped and scored
Tiering
3 tiers
Qualified on funding, size, geography and trial activity, then re-qualified after enrichment
Cleanup
7,835
AI agents verified every name and domain; dupes merged across the list, the CRM and the platform
Trial intel
CT.gov
New trials, phase 2/3 starts, IND filings and amendments, tracked per account
Each signal gets its own sequence, so the opener matches the trigger
Routing
automatic
A firing signal enrolls the account and pings the right rep in Slack
Now a new trial registration becomes a Slack ping, a sequence enrollment and a rep task before anyone has read the news. Clay, Apollo and Zapier carry the admin; the reps just sell.
S/003
New target list after a $72M pivot
Post-pivot$72M raised
A company had just raised $72M and changed direction. They needed new customers, fast. I rebuilt their target list from the deals they had already won, sorted 27,881 companies, and wrote first to the people already following the founder. Warm beats clever: 16 positive replies in the first week.
The tiering formula got the same treatment as production code: a test harness runs the real formula text through Node against 22 gate cases written from the business rules, and nothing ships until all 22 pass. It paid for itself early, catching hiring data that arrived as a raw object, printed as “[object Object]”, and silently under-tiered companies that were actively hiring.
S/003fig. 003-are-sort and test loop
16positive replies, week one
12meetings in one week
fig. 003-bThe retargeting, piece by piece
Piece
Value
What happened
Re-sort
27,881
Every company in the export re-scored against the profile from won deals
Tiering
3 tiers
835 Tier 1, 2,826 Tier 2, 6,249 Tier 3; 17,971 disqualified instead of padding the list
Formula harness
22/22
The real formula text runs through Node against gate cases from the business rules before anything ships
Warm audience
6,955
Contacts already following the founder got the first sends
Best variant
5 opps
The single best variant produced 5 opportunities from 10 replies
The whole build ran on one idea: put the right 835 companies at the top of the list, and prove the formula that put them there. 12 meetings in one week says the sorting held.
S/004
CRM forensics: three automations fighting over one field
4,964 companies12,709 contacts
S/004fig. 004-aone field, three writers
One account’s tier changed eight times in a single afternoon, and nobody had touched it. The CRM held 4,964 companies and 12,709 contacts across 237 company properties and 349 contact properties, and automations were overwriting each other inside it. I read the property history like a log file: three writers were hitting the same tier field, so I made the workflow the boss and stripped tier writes out of every enrichment action.
8tier flips in one afternoon
Then I went after the duplicates. A tool flagged thousands of duplicate people who were really coworkers sharing one office phone number; merging them would have welded 18,583 real people together. I blocked that, merged the true dupes at the company level, linked subsidiaries as parent and child, and killed the setting that was breeding shell companies from email domains.
fig. 004-bThe forensics, fix by fix
Fix
Value
What happened
Tier writes
3 to 1
Enrichment tables, a workflow and merges all wrote the tier field; now the workflow is the only writer
Dedup scan
12,190
Company records checked: 115 domain-duplicate clusters and 198 exact-name clusters found
False merges
18,583
Coworkers sharing an office phone had been flagged as duplicates; blocked before a single bad merge ran
Shell companies
4,090
Auto-created from email domains in one day; the setting responsible is dead
Junk contacts
~7,837
Blank records with no email and no company removed, every real lead kept
Create gates
117
Enrichment tables that can no longer create records on their own
Every fix deleted a whole class of errors instead of chasing single cases. Merges need real evidence now, and nothing gets created without a rule behind it.
S/005
Ads and outbound on the same accounts
Paid-media agencyABM ads plus outbound
A B2B paid-media agency runs one-to-one ABM ads: each target account gets its own campaign, so the account list behind the ads has to be right. I built the account layer both motions share and ran the outbound side. Every record carries its ad score and predominant ad platform, and a daily sync keeps the channels from colliding when someone replies.
21.7%reply rate, top segment
The campaigns seeded from the founder’s follower and connection exports, and the top segment replied at 21.7% with 5 positive replies. One bug almost undid it: the email platform’s API was silently dropping first names over payload casing. I caught it and fixed 138 of 139 leads.
S/005fig. 005-atwo motions, one account list
fig. 005-bThe shared account layer
Piece
Value
What happened
Ad-fit scoring
21,735
Every company scored and tiered: 471 Tier 1, 1,370 Tier 2, 19,894 Tier 3
Ads targets
score 8+
Accounts above the line feed the one-to-one ads; each record carries its ad score and predominant platform
Outbound
2,317
Leads from the founder’s follower and connection exports, split into three segments
Channel sync
daily
A LinkedIn reply exits the lead from email; an email reply queues the LinkedIn removal worklist
Name fix
138/139
A payload-casing bug dropped first names in the email platform’s API; coverage went from 0% to 99.3%
The ads warm an account, the sequences work the people inside it, and both motions aim at the same well-chosen accounts.
S/006
Context engineering: a self-maintaining system for AI agents
Not client work, my own system
Sessions are disposable, files are the memory. I got tired of re-explaining the same client to an AI agent every morning, so I wrote the context down instead. Every client gets two files: one durable with the IDs, the architecture and the known traps, one volatile with what’s in flight, date-stamped. A session starts by reading both, and I explain nothing.
S/006fig. 006-awhat a session loads before it works
89files, no framework
8client contexts, 5 live
Anyone can gather open tasks. The hard part is knowing which ones are already done: two older routines skipped that check and kept handing me back work I had already finished, plus a client that wasn’t mine. Both are off. The one I replaced them with won’t put a task in front of me until it has checked the task is still open, and it still stages every action for my okay until I have watched it long enough.
fig. 006-bThe context layer, 89 files in all
Piece
Count
What it holds
Skills
25
Named procedures the agents load on demand, from campaign preflight to weekly client updates
Sub-agents
6
Separate workers with their own context window, for work that runs in parallel or writes to something
Memory files
56
Durable rules, how each tool actually behaves, and feedback that survived contact with real work
Session hooks
2
Fire on the session lifecycle, so setup never depends on me remembering it
There is no framework under any of this and no database, just plain markdown and two shell scripts. Writing to those files is destructive on purpose. A fact that gets contradicted is deleted, not appended under the old one, closed loops get cut, and every file has a line ceiling that pushes the overflow into a topic file beside it. One fact lives in exactly one place. Above all of it sit rules the agents can’t argue their way out of: nothing sends, posts, writes to a CRM or pushes to git without me saying so, campaigns never go live on their own, and credentials can’t be staged into a commit.
fig. 006-cWhat runs while I’m not there
Job
Runs
What happens
Cloud twin
4-core
An ARM box with 24 GB of RAM, reachable only over my own private network, so nothing waits for my laptop to be awake
Brain sync
every 10 min
Notes travel over git, skills and agents and live memory over a file sync, so an edit on either machine lands on the other
Auth keep-alive
every 6 h
Refreshes the session cookies the headless jobs need, so a 5 AM run doesn’t wake up logged out
Morning operator
daily, 5 AM
Sweeps open work across clients, personal projects and content, checks it against what’s already finished, then leaves one message or none
Content ideas
weekly
Turns the week’s shipped work into a short list of things worth writing about
Self-audits
3 monthly
One prunes and merges the memory files, one prices what each skill costs in context because every description loads into every session, one health-checks the machine. Each snapshots first, auto-fixes only what’s reversible, and stages the rest for me
What I get out of it is plain: I can hand an agent a client it has never seen and the work comes back the way I would have done it myself. Three of these skills I adapted into my team’s shared repo, along with the headless runner that executes them on a schedule, and the team uses them now.
Toolsthree
built for myself
T/02
Preflight for cold email
Before a campaign goes out, this tool renders every single message exactly as each person would get it, and flags the errors before shipping. One pass over 22,700 messages caught broken tags nobody had spotted.
T/02fig. t02-apreflight output, three verdicts
AI hallucinations in Clay tables
Pleasantries left behind by AI enrichments
Missing or blank variables
Emojis in names and titles
Company names not normalized (parentheses, Inc., etc.)
The skill has been trained on 150k+ real emails and 30+ sent campaigns, and it updates itself automatically. Every campaign it grades makes the next verdict sharper.
T/01
Handover generator
One Slack command produces a two-page brief that lets a teammate cover any account. About 26 minutes later, two linked Google Docs land in your DMs: a 5-minute brief and a deep-reference companion. No human touches anything in between.
~26 minautonomous run
9systems pulled
0humans in the loop
T/01fig. t01-ahandover run, end to end
Under the hood it’s a headless AI runner on a job queue behind a Slack bot. Long agent runs die on context limits, so I split the gathering from the writing: a cheaper model reads each source and writes notes to disk, and a stronger model synthesizes them into the brief.
T/03
Cold email rebuilder
A writer drafts. A separate evaluator grades it against a locked voice file. The writer never grades its own homework.
T/03fig. t03-athree campaigns, draft above and rebuild below
Every cold email I ship goes through that critique loop. The split matters because a model grading its own homework passes everything. The evaluator cites the exact rule a line breaks, the writer fixes only that line, and lines that already work are protected from rewrites.
The voice file is the law, and it learns. When real replies validate a rule, or kill one, the file updates itself, so every campaign makes the next one sharper. Trained across 30+ sent campaigns.
Notes
contact
Client names hidden here; happy to share details in conversation. All numbers from real client work, 2026.
claude codepythonhubspotclayn8napolloinstantlyheyreachreact