Every change you'd actually notice, dated from the app's own commit history — and an honest note about which of them are in the installer today.
This list is generated from the build's commit log, so the dates are the days the work landed in the app's source, not marketing dates. Internal things — unit tests, build tooling, the admin panel — are left out. It starts on 22 July 2026, which is where the history stops being about a different product.
The installer was rebuilt on 13 August 2026 and it is version 2.5.0. It carries everything on this page down to and including the two entries dated 13 August. The last change in it landed at 17:58 UTC on the 13th and the file was packaged four minutes later — by four minutes and thirteen seconds, which is the whole margin that change made its build by. Checked rather than assumed: Last-Modified is 13 Aug 2026 18:02:28 GMT, the file is 53,665,832 bytes, and the MSI's own ProductVersion — read out of the downloaded file — reads 2.5.0.0.
The WhatsNot live-auction work is in it now. Around thirty-four changes landed between 00:06 UTC on 7 August and that afternoon — the whole 6–7 August group below, which this note used to warn was missing because the previous installer had been packaged before it. The nine changes from the afternoon of 29 July that had missed their build are in the download too, and each is marked in place below.
What is not in it: the 14 August changes. Five landed between 13:04 and 14:39 UTC on the 14th, the day after this installer was packaged. Three of them are written up — the eBay condition fix, the live-video read, and the sign-up changes on the browser version — and they are the top three entries below, each marked in place. The 13 August work that this note used to say was still owed is written up now. The app puts up a banner of its own when a newer release is published.
Six changes over two days. The one from the 13th made the 2.5.0 build by four minutes; the five from the 14th did not, and are marked. Two of those five were the owner's own sign-up alerts — admin plumbing, left out under the rule at the top of this page rather than dressed up as a feature.
Sign-up took an address and a ten-character password, and the app then had nothing to call anybody by — the only place a signed-in seller appeared anywhere was a tooltip reading Signed in as seller@example.com.
A name is asked for at sign-up now, trimmed, capped at 100 characters, whitespace-only refused, and it shows on the topbar beside the sign-out button. Accounts created before this keep working and fall back to the email address, so an older account shows what it always showed rather than a blank.
The password minimum is twelve characters, not ten — and there is deliberately no uppercase-digit-symbol rule. That rule reliably produces Passw0rd!, which is in every dictionary an attacker owns. Length plus a blocklist is stronger and it doesn't push anyone towards a sticky note. Also refused: a password equal to your own email address, and about eighty of the ones that get tried first — matched in full rather than as substrings, so my password is a boat is still a perfectly good passphrase. The rule lives in one place and is enforced on the server; the box's own minlength saves a round trip and decides nothing.
The hashing did not change and did not need to: PBKDF2-HMAC-SHA256, 210,000 iterations, a fresh 16-byte salt per account, constant-time compare. Nothing to rehash.
What the browser version is, and how it differs from the download →The provided condition id is invalid for the selected primary category id, this is that.eBay's graded used conditions — Very Good, Good, Acceptable, IDs 4000, 5000 and 6000 — exist only in the media categories: Books, Movies, Music, Video Games. Every other category refuses them, Business & Industrial included. The AI graded a Fanuc servo amplifier USED_GOOD, the publish sent condition 5000, and eBay bounced the entire listing. The grade was not wrong. The ID simply does not exist where that item was going.
Condition is category-aware now. Outside media, every used grade collapses to plain Used (3000), which every category accepts — and the grade the AI actually saw still reaches the buyer in the condition description, so nothing is lost. It just stops being sent as a field eBay was never going to take. Media categories keep the graded IDs, because that is where they are valid.
The same fix caught LIKE_NEW, which had been mapping to 2000 — Certified Refurbished. That one is eligibility-gated on eBay's side and gets refused about as widely, which is a listing rejected for a reason nobody would guess from the words "like new". It is 3000 now too.
The show-page read added on the 7th answers from the listing text. This answers from the picture — what the host is physically holding up, which the page and the camera do not always agree on. When they disagree, the page is usually the one that is out of date.
There is no clever way to get at the video: Whatnot refuses to be embedded, and a browser cannot see inside a cross-origin frame. So the seller shares their own Whatnot tab, the app samples a frame roughly every 20 seconds, runs the same identification the photo check already uses, and the name it comes back with goes down the same pricing path a typed one does. The sold-comps route is not duplicated — there is one way this app prices a thing, and this is a new way of naming it, not a second way of pricing it.
It spends one AI read per frame, so it is off until you press it, and it stops itself. On the read cap, when you end the share, when you type over the item box, and when you leave the screen. A watcher you forgot about is a bill, and this one is looking at a live stream that could run for hours. The status line is visual only rather than a second live region, because a screen reader announcing a fresh reading every twenty seconds during a live sale is unusable.
What a Whatnot lot actually costs to win →Every board in this app that decides where money goes was pricing against a stored corpus of sold comps. That is fast and it is fine until it isn't: a figure that was right for a miner in June is not what the same miner fetches in August, and nothing on screen told you which one you were looking at.
Live sold-comps lookups now run in the three places money is actually decided — the Opportunity Finder, the eBay Scanner, and pricing an item you are about to list. Each gets a three-minute budget and a progress bar that says what the wait is for, because an unexplained thirty-second pause on a pricing screen reads as a hang and gets clicked again.
A lookup you waited for used to be able to finish and move nothing. Scraped rows landed in one comps database while the board read the other, so the wait was real and the price did not budge. Both are read as one set now.
Age decays both sources on the same curve. Before, only the freshly fetched one aged, so a large stale local corpus could outvote a live lookup on row count alone — more rows, all older, winning. And the hardcoded 60/40 blend on the sold-comps endpoint is gone; it uses the same adaptive weights every other board already used, so there is one answer to "what is this worth" rather than one per screen.
What the Opportunity Finder does with sold comps →A listing that says For Fanuc … is an accessory for the machine, not the machine. The matcher read the model number out of the title and priced the accessory against the machine's sold comps, so a $38 anti-static wrist strap for a $1,000 teach pendant arrived at the top of the board reporting 2589% ROI. Compatibility listings are detected and refused now rather than priced off the thing they fit.
That is the same shape as the part-number bug from July, and it is worth saying why this keeps happening: the highest-ROI row on a sourcing board is, more often than not, a matching error rather than a bargain. A wrong comp is worse than no comp. No comp shows as "no sold data" and gets checked by hand; a wrong one gets bought.
The arbitrage board also stopped quietly widening its own criteria. When a thin comps corpus would leave one row on screen, it relaxes its default filters — which is the right call, an empty board helps nobody — but it now says plainly which filter it loosened. A board that changes what it is searching for and does not mention it is lying about what it found.
And a cost you typed against a sale survives a re-import. Re-importing your earnings used to overwrite a seller-entered cost with whatever the import knew, which was usually nothing.
Around thirty-four changes over two days, nearly all of them one new thing: working out what to bid on a lot while it is still on the block. It missed the 6 August installer by hours, which is what this page used to warn about; the 2.5.0 build carries the whole group.
A live-selling stream puts a lot up every four minutes and gives you seconds to decide. Every screen this app already had answers what is this worth; none of them answer it fast enough to be any use while an auctioneer is talking over you.
The live card takes the lot on screen and works backwards to the highest bid that still leaves a profit when the thing is resold on eBay. The buyer's premium is divided back out of the ceiling rather than added on top of it — a 20% premium on a $100 hammer is $120 landed, so the bid that lands you at break-even is not your break-even. Under it sit the sold comps the price came from, the middle half of them, sell-through, how fast the item moves, and a sentence on every card saying how old that evidence is.
Typing the lot name was the slow step — a lot is on the block for under a minute and eight of those seconds went on spelling a model number into the box every number is derived from. The show's own page is read instead, because a live show's current lot is structured data rather than a picture. One press fills the item and price boxes and prices the card down the same path a typed lot takes; against a between-lots answer it leaves the boxes exactly as they were and makes no eBay lookup at all.
The lot's photograph is the only thing on screen that can argue with its name, and "MYSTERY MINER LOT" answers at random and answers confidently. Check the photo looks at it and says one of five things: it agrees, it sharpens the name with a model number the name lacked, it differs, it is not sure, or there was nothing typed to agree with. A better name arrives as a button and is never substituted. It prices nothing — the look carries no price on it at all — and it only claims a disagreement when two model numbers actually contradict each other, because a panel that cries wolf costs you the lot and the panel.
Sixteen sessions of this card answered "what is this worth" and quietly assumed you could pay it. A run of changes over one day added the costs that were missing. Every one of them moves the ceiling in the same direction.
Sales tax. A US live marketplace is a facilitator, so it collects your combined state and local sales tax at checkout and nobody declines it. It averages 7.5% and passes 10% in places — about the size of the buyer's premium. So every ceiling this screen had ever produced was too high by roughly the size of the largest cost it did charge, in the one direction that costs money: a ceiling that is too high says bid on a lot that then loses. An empty box charges nothing and says how big that silence is, a ticked resale certificate charges nothing and says why, and the certificate is judged first so it outranks the rate box — most resellers file one, and a ceiling cut for a cost you do not pay loses you lots.
Freight, charged as a share. A live seller posts one box per show: a first-item rate plus a much smaller rate for each extra thing in it. Charging the full first-item rate to every lot of the night costed a seller who won six lots at "$12 shipping" — and paid $17 — as though they had paid $72. The error ran one way, and the lots it made look worst were the cheap ones, where eleven dollars is most of the margin; that is backwards, because the second lot from a show you are already buying from is the cheapest thing on the screen. This is the only read on the card that can raise a ceiling, so it is gated on three facts you can see: the show is named, its extra-item rate is entered, and tonight's sheet already holds a lot from that same show.
What is actually left in the account. A defensible lot every four minutes and a green badge on all of them is a night's cash flow committed to stock that becomes cash in forty days. The app knew what had gone — tonight's buy sheet is the figure the bank statement agrees with — and only ever read it after the hammer. With room, nothing is cut. With less left than the item is worth, the ceiling becomes what that cash lands. With nothing left the card stops, and the badge reads OUT OF CASH rather than DON'T BID: a seller told the market refused a lot they merely cannot afford learns the wrong thing and walks past the next one. It is a cut and not a haircut — the resale price, median, spread, sell-through and comps are identical with and without a budget.
What the room actually pays. A seller prices thirty lots and wins four, and the hammer prices of the other twenty-six are the only direct measurement of the room there is. They were being thrown away every night. Losses are recorded beside wins now, off the same held comps, so the ceiling written next to a hammer price is the one that was on screen. The wins count on equal terms, because a seller wins the lots that go cheap and a rate built off the losses alone calls every room hot. It moves no figure on the card: a room that outbids a correct ceiling has not made the object worth less.
And how many presses are left. Comparing the bid on screen against the ceiling answers whether the last bid was all right. Nobody buys at that price — pressing bid commits you to the next increment, so $3.10 of room under a $73.10 ceiling can mean there is no press left that stays inside it. It counts presses instead: "6 more bids", "Last bid", "Don't press". The increment is an assumption, so it is stated back in dollars on every card with a box to overrule it, and a step you typed is held flat rather than talked upwards by the ladder — you are watching the show and this app is not.
Whatnot shipping and sales tax, on a real lot →Four reads that all correct the same failure: a median across everything matching a name is the right price for nothing in particular.
Condition. Nine sold at $200 marked New and three at $100 marked Pre-Owned makes RESELLS FOR $200, which is the right price for neither. The sold rows already in hand are split by the condition they stated, shown as bars on the card, and the ceiling is cut to the lot's own band when there is enough of it to price against. A worse condition cuts and a better one never raises. Half the comps have to state a condition, the lot's own band needs three sales, and the cut stops at 50%. Silence in a lot's name is never read as evidence — an unstated lot is priced exactly as before and the card asks, naming both ends in dollars. The sharpest state is the one where nothing can be cut: the lot is used, the comps are mostly new, and the card says outright that the badge is a new-item price.
Lot size. Sold comps are per unit everywhere in this app, and a live show is full of "3x Antminer S9" and "LOT OF 5 GPU RISERS". One hammer buys all of them, and the card was saying BID UP TO $73 on three $200 miners with the same green badge it uses on one. The count is read off the lot's own name now, and only ever from wording that states one — "bundle", "mystery lot" and "pair" ask instead, because reading a count that is not there makes you overpay while missing one only makes you pass. It is deliberately stricter than the liquidation parser: on a live show "pack", "box" and "case" name the products, so a 36-pack booster box stays one box. The break-even multiplies; the $100 cash floor does not, because the packing, label and handling happen once for the lot — which is why three cheap miners are worth more than three times one of them.
Which way the price is going. The card had always said how old its comps were and never which way they were moving, and a median across two months is the right price for an item holding it and an overstatement for one that has slid since — paid in cash, in eight seconds, on a purchase with no undo. A confirmed material slide now cuts the resale the ceiling is built from. A confirmed climb never raises it: refusing a good lot is invisible and there is another along in four minutes, while overpaying is real cash found weeks later. A cut needs the window medians and the trend line to agree and is floored at 35%, and comps whose newest sale predates the window are refused outright — from one lookup, an item that stopped selling and a stalled comps database look identical, so neither is claimed.
How many of these you would then own. A host with a pallet of one product puts one up every four minutes, and the app says yes six times because six times it is true. Six of them is not six times the profit — they queue behind each other in the same demand. The card adds up what the shelf holds, what tonight's sheet holds and what is in this lot, and measures the total against the clearance rate it already knew; the middle count is the one nothing else on the card can see, because those lots are still in their boxes and have never touched the deal pipeline. It moves no price, because saturation is a claim about a calendar rather than about what the object fetches: the fourth one still resells for what the comps say, it just sells in April. So April is priced — never a haircut for the pile, only a charge for the measured slide across the wait the pile causes. Twelve of something whose price is flat is priced identically to the first one.
Where the sold-comp numbers come from →The comp lookup behind every number on the card is a boolean AND: every word in the query has to appear in a sold listing's title. What you type is what a host just said — "3x Bitmain Antminer S9 13.5TH – NO RESERVE!! ships free" — and no eBay listing in history contains all of those words. So the search returned nothing and the card said CAN'T PRICE IT about an item with a perfectly good market, with eight seconds to read it and no way to tell that apart from "this has no market".
The query now takes out the words that describe the sale and keeps every word that describes the item, and the card shows the query it sent, every dropped word with its reason, and a button that searches your typed name verbatim instead. It only ever removes — no word can appear in the query that you did not type — and it drops conservatively, because a word dropped wrongly makes the price quietly wrong while a word kept wrongly makes the card visibly say nothing. Condition, completeness and authenticity are never touched. "Hot" and "fire" came back out of the hype list once somebody asked what a live feed actually sells: Hot Wheels and Amazon Fire. Where the cleaned name still matches nothing, it widens once to the first three identifying words, keeps that only if it found more, and says so as the first warning on the card — it trades precision for evidence, and that changes what every number under it means.
Separately: nothing on this card had ever asked whether the listing it is pricing is allowed to exist. A replica bag, loose ammunition or swatched makeup all price like a spectacular flip against genuine sold comps. The lot's name is now read against eBay's own selling policies, and a lot eBay will not take overrules the call to CAN'T LIST IT — while moving not one figure, because the ceiling and the comps still say what the allowed article fetches, which is what made the lot tempting in the first place. An Authenticity Guarantee category over its bar says so and charges nothing, because its cost is days and the calendar is already priced. The vocabulary is tuned to the card's own asymmetry — a rule that fires wrongly costs a lot somebody else wins, a rule that stays quiet costs the purchase — so "fake" and "dupe" are absent, ammo excludes the empty can, and scotch excludes the tape.
One more that counts and never charges: the sold rows the price came out of are counted against the one figure that decides the win — what a unit has to fetch to break even at the bid on screen. It is the only figure on the card that falls every time somebody else raises. Half the sales came in under the middle, and you are buying one object out of that spread, once, in the next eleven seconds. A percentage is refused under five sales, and only the state where most of the evidence sits under the line reaches the warning list.
Buy or pass, decided from a photo or a link →The embedded feed panel opens a live-selling site inside the app. Whatnot sends X-Frame-Options: DENY, so every open pointed the frame at it and held a black rectangle until a header check came back and said what it had said the night before. The verdict is kept per host now: the second visit answers from memory with no network in it, and the frame is never pointed at a page that was never going to render. Only what the site actually said is remembered — a refusal from headers is filed and a timeout is not, because a remembered timeout would turn one bad minute into a week of a feed the panel quietly declines to load. It expires after seven days, is re-checked in the background behind every remembered refusal, and "Try it anyway" overrules it — offered only against a verdict that might be stale, never against a header read a second ago. A confirmed refusal also blanks the frame, so somebody's live stream stops being fetched for a rectangle nobody can see. And the refusal is a doorway rather than a dead end: Read this show instead hands the panel's address to the reader, which fetches the page through the app and fills the box the ceiling is priced from.
At the other end of the night, what it cost. The buy sheet is the figure the bank statement agrees with — every lot won, what was paid, and the ceiling that was on screen when it was won, which is the column the discipline is measured against. It is shown while there is still time to change it rather than as a post-mortem. A won lot becomes a draft listing in one press, and the cost follows the item onto eBay instead of being retyped, so the night's spend arrives in the earnings screen as a real cost basis rather than as nothing. Winning a lot also records the marginal freight, so the night's spend stopped double-counting shipping across a show. And before you bid, the card shows what you got for the last one of these — the one comp nobody else has.
Two small ones that only matter live: the card is rebuilt with one write every time the bid moves, every two or three seconds, and that used to destroy keyboard focus and any open comp table underneath it. A seller tabbed to the hammer button and waiting for the auctioneer lost it silently, and the Enter they pressed when the lot sold went nowhere — so the lot they bought was not on the sheet. Both are taken before the redraw and put back after, keyed by name rather than by position. And the screen keeps its meaning when the colour goes: forced-colours mode was flattening the meter fill, the odds bar and the condition band, all of which were read at a glance and carried by colour alone.
What a night of live-auction lots actually costs →The dashboard checklist stopped at "connected", which is not an achievement — it is a configured app that has shown you nothing. It runs past setup into the flip now: price one item against real sold comps, let the AI write a listing, publish it. Each step is ticked from evidence the server watched happen — a comp lookup that returned comps, an analysis that produced a draft, a publish eBay confirmed — never from opening a screen or from you saying so.
Two of the steps had been lying outright. Step 1 ticked when a Claude key was saved, and saving a key is not evidence of anything: a key that lost a character in the paste, one that has been revoked, and — much the likeliest on day one — a valid key on an account with no credit all save exactly as cleanly as a working one. You got the tick, spent five minutes on the next four steps, and met the real failure at the first analysis, three screens from the field that caused it. The app asks Anthropic now; one Haiku token, a fraction of a cent, settles all three at once, because to Anthropic they are one question. Step 2 was doing the same thing one step along, with a worse ending. "Connect eBay" ticked on any install merely holding a token, and a grant revoked in your account, a refresh token past its eighteen months, a sign-in that came back on the wrong port and a consent screen where the selling permissions were never granted all leave something on disk. The row went green, and the failure waited at the publish — the last step of the path and the most expensive one to reach. Nothing new had to be built for it: the connection check has done this properly for far longer than onboarding has existed, it just had nowhere to report to.
The load-bearing part of both is which answers are allowed to count. Only a rejection, a billing refusal, an expired or absent session may take a tick off and redden a row; a rate limit, an outage, a timeout or anything unrecognised is discarded, because none of them say a word about your account and a tester on a train must not be told their key is wrong. An install that never runs either check behaves exactly as it did before. The same claim was being made in one last place — the top bar badge, which said "Connected to eBay" whatever eBay thought.
Each step also says what to do and what will tick it, on the screen where the doing happens rather than on the page you left. All five are earned from evidence, which is the right rule and is only a virtue if you can find out what the app is watching for — otherwise a row still unticked after you did the thing reads as a broken checklist. And a first-run screen opens once on a genuinely untouched install saying what the app does, what it will need (a Claude key, about $5 of credit, an eBay login, five minutes) and that it is free. Naming that before asking for anything is the difference between honest free software and a paywall in waiting.
What connecting a real store gets you →All of this is in the installer you can download today.
Three numbers have to agree for an update to work end to end: the version the running app compares, the release tag it compares itself against, and the MSI's own ProductVersion, which is what Windows reads to decide whether this is an upgrade or a fresh install. They had been disagreeing in both directions.
The published v2.4.0 release and the in-app update banner both pointed at a 2.4.0 that was never set in code — the version was still 2.3.0 — so nobody who downloaded could ever satisfy the "update to 2.4.0" prompt they were being shown. And the packaging still declared 2.3.0.0, which with the upgrade rule in place means Windows treats installing over 2.3.0 as a reinstall rather than an upgrade: the new files land beside the old install instead of replacing it, and nothing looks obviously wrong anywhere.
Both are 2.4.0 now, and the file on this site reports ProductVersion 2.4.0.0. That closes the wrinkle in the note at the top of this page, which had said since 29 July that the packaging and the application disagreed and that the file's date was the only marker worth trusting.
The panel that chases missing costs checked whether a cost existed, and $0.00 exists. eBay imports arrive at $0.00 for anything that shipped free, so those sales answered the question the moment they landed: they left the panel, stopped being asked about, and were booked as pure profit. On this account that is 19 of 60 sales — a panel showing nothing to do, while nineteen power cords and hashboards counted at 100% margin.
The list asks "does this still need a cost" now, rather than "is there a number here". A zero counts as an answer only once you give it yourself: saving a cost, including a deliberate $0.00, stamps the row as confirmed, so a genuinely free item — a bundled accessory, something thrown in with a lot — stops asking and never comes back. And the two kinds of row are no longer described in one sentence, because they are not the same claim. A sale with no cost at all is missing from the totals. A sale at $0.00 is in them, inflating them. Calling both "isn't counted above" was false for nineteen of the nineteen rows in there.
There was also nowhere else to fix one. The only cost box in the app was on that panel, and that panel lists sales whose cost is unset — so the moment a sale had any cost at all it dropped off and became uneditable, and a cost typed wrong once was just as stuck. The "You paid" cell in the every-sale table is the input now. It takes a dollar amount, or a percentage like 40% for dropship splits, in one box rather than a second column across sixty rows, and it is styled to read as a number until you hover or focus it — that column is scanned far more often than it is typed into.
What you owe on what you made →Pricing a specific model was the slowest thing this app did. Every comps lookup builds a LIKE '%word%', and a leading wildcard defeats the index, so each search scanned the whole sold-listings table. Common words hid it — the row limit fills early and returns in 0.04s — but a rare term scanned all 900k rows: 3.50s for s21e xp hydro, 4.05s for whatsminer m66s. Rare is what a model number is, so the slow path was the one that mattered, and it was the path used to price the highest-value items in the catalogue. There is a full-text index over the titles now and the same searches come back in under a millisecond. Each word keeps a prefix wildcard so s19 still finds S19j, which the old substring match caught and plain word matching would have dropped. Where the index is absent — an older comps file, or the hosted copy — the previous query runs exactly as before, which is the reason this was safe to add at all.
Less happily: eBay has stopped accepting the saved Terapeak research session, and reconnecting does not bring it back — the login lands on a bot check rather than a sign-in. The app went on showing four Connect buttons for it anyway: a numbered step in the setup wizard, a card in Settings, a strip across the Opportunity Finder, and a prompt inside the listing editor. Every one of them started a login that could only fail, and the copy beside them told you your sold-comp data depended on finishing it.
It does not, and that is the part worth saying plainly. A failed Terapeak lookup returns nothing and takes 0% weight in the blend, so prices have been coming from the sold-comps database alone for weeks — the buttons were the only part still claiming otherwise. They are gone, along with the "Open in Terapeak" button and the help text about prices being "blended with Terapeak where both have data". The server side is untouched and nothing in the interface reaches it.
Why the Terapeak buttons went, and what prices things now →Every pricing screen here runs on sold comps, which say what buyers have paid. None of them can see what a buyer is looking at right now, so a listing priced perfectly against sixty days of sold history can sit for ninety days behind eight cheaper copies of itself and nothing in the app says so.
Price Position reads the shelf. For each live listing it pulls what is competing with it at this moment and ranks it on delivered price — item plus postage, the way eBay's cheapest-first sort does — and then names which of three things is actually in the way: the price, the supply, or the fact that nobody is reaching the listing at all. That third answer is why this is not just a repricer. A listing that is already the cheapest and has had six views in seventy-one days does not need a markdown, it needs a title.
Most of the work in it is refusals. It will not count a repair service, an auction mid-bid, a lot of ten, a for-parts unit, a freight listing with no stated shipping, or the one broken one priced at a fifth of the rest. Each of those, counted, is a price cut recommended on a listing that never needed one. It will not cross the floor the net-proceeds calculator draws, and it writes nothing to eBay.
Why a cross-lister structurally cannot do this →Every fixed-price listing renews every 30 days, and each renewal spends one of that month's zero-insertion-fee listings — so the number of listings an account keeps live is its monthly insertion bill. The app already reads that number off eBay. Nothing was doing anything with it.
Nine hundred live listings with no Store subscription is 650 × $0.35 = $227.50 a month, against a $21.95 Basic Store that covers a thousand — $2,466.60 a year for one click on eBay. It runs the other way too: 214 listings on a Basic Store bought years ago is $21.95 a month for an allotment the free 250 already covers. So the screen costs all six tiers against the live count, reports the band of listing counts each tier is cheapest over, and reports annual billing separately, so a seller already on the right tier is not told "nothing to do" while $72 a year is still on the table. The Starter Store is never cheapest at any count — its allotment is the same 250 everybody already gets.
It is deliberately narrow and says so on screen: it compares the subscription, the allotment and the insertion fee. Final value fees are set per category with no per-account rate published, and a guess at them would move the answer on a figure you cannot check. That does bias it, and the bias is worth knowing: eBay quotes Store tiers from Basic upward a lower final-value rate than a no-store seller, so a low-listing, high-revenue seller can be told to stay put when they should not be. It is a fault in our own product rather than a rounding note. The rate card is served in full so every figure above it is checkable against eBay's own fee page, and the screen changes nothing on eBay.
Four changes to the editor in one day, all the same complaint: the app had the answer and asked anyway.
The words your title is missing. Every title tool in this app works from your own listing, and rearranging words that are already there cannot fix a listing whose problem is a word that was never in it. This reads the market instead — eBay's own Best Match results for the search the item sits in, and the titles that sold, counted. Terms come back with their evidence ("10 of 10 top results, 3 of 3 sold"), appended to your title inside eBay's 80 characters, with the empty item specifics answered from those same titles and checked against eBay's published list of legal values for the field. Three rules keep the counts honest, because eBay's top results for one item are near-copies of each other and every window of a common title otherwise scores 100%: one seller relisting six times is deduplicated to one vote, a phrase offered as an addition must be entirely new rather than half words you already wrote, and no two reported terms may share a word. Without them the answer was one sentence sliced four ways, and applying it wrote the same word into the title twice. Nothing is written without a click — the app does not know what the item is, it knows what the item's neighbours are called, and a word ticked onto a title for a thing that does not have it is a not-as-described case you pay for.
The category. The pre-publish checklist could fill brand, part number, ZIP and the packed box from one button, and could never fill the category — the field that costs the most to leave blank, because eBay will not publish without one and required item specifics are defined per category, so until it is answered the app cannot say what else the listing needs either. One empty box was holding up the entire rest of the check. It was also pure retyping: a seller who has listed forty Antminers has made this exact decision forty times, and the forty-first listing still opened on an empty search box. Every successful publish now records the title and the category eBay took it under, and a new title is read back against that record — cut into significant words, with filler dropped and model numbers counting for more than adjectives. The blocker reads "Use Miners — where you put 6 listings like this", quoting one of your own past titles back at you. Where history has nothing, eBay's taxonomy answers instead, never at full confidence and marked as an estimate. One word in common is not evidence; two categories you have filed similar items under both ways is a coin flip, not an answer, and returns nothing; and a category you have already picked is never suggested over.
Photos that belonged to a different machine. The service behind reusing one photo shoot across identical used units had no tests. Writing 33 turned up two ways it handed a listing the wrong model's photos, under a disclosure line promising they represent the unit being shipped. The match was a substring test, so an S19_95TH folder scored a hit on an Antminer S19j Pro title; and an exact tie was broken by folder name, so a listing saying only Antminer S19 silently got S19_110TH because 1 sorts before 9. Whole tokens now, and two models fitting equally well is no match at all — the app already knows how to ask you for photos.
Ten collapsed panels that all looked the same. The edit drawer is ten collapsible panels tall, and closed, all ten were the same grey bar: the only way to find out whether a listing had photos was to open Photos, and the only way to save was to scroll past all ten. Every summary carries the state of its own panel now — 67 / 80, 6 photos, $1,249.99 · qty 2, 31 lb 4 oz · 89101 — so closing everything gives you a one-screen summary of the listing instead of a wall of headings. The action bar is pinned to the foot of whatever pane scrolls it and carries what is still missing, printed as buttons that open the panel, scroll to it and focus the field. It says "the four things eBay requires are filled" and never "ready to publish", because the server check reads eBay's required item specifics and this one cannot. Nothing in it writes to a field.
Fixing titles, specifics and descriptions across a whole account →Every sourcing board in this app starts at the market and asks "is this worth buying". None of them answered the question a reseller actually asks on a Saturday morning with cash in hand: what do I go looking for.
The Restock List reads completed sales — eBay's own fee, your own cost — groups them into products and ranks them by what each earns a month, not by total profit. Total profit ranks the one lucky pallet flip above the part that sells twice a month, and sends you after another pallet. Underneath it, return on the cash as a yearly rate, wherever a purchase date was recorded. Four refusals keep it honest: a sale with no recorded cost is never profit, not even zero; one sale is never ranked and carries no rate at all; a rate is never measured over less than a month; and being sold out is never held against a product, because a listing nobody buys is evidence and an empty shelf is not. The stop list — what sold at a loss, and what keeps coming back — is second on the page rather than last, and every other row hands its search term to the Opportunity Finder in one click.
Two smaller ones the same day. Roll the Dice can keep a play. Its most common verdict is "nothing is for sale right now — buy under $396.34 and it clears the bar", and the footnote said those targets were worth watching for while offering no way to watch for one; rolling again threw the whole board away. A play has a keyword, a price ceiling and a profit bar, and a Deal Radar watch takes exactly those three — so "watch for one" is that mapping and nothing more, with no new scanning and no second definition of a good buy. The ceiling is the target price and never the break-even, because paying break-even earns nothing, and thin evidence never becomes a 2am notification.
And the chips above the sourcing board say what became of each site's listings: how many were priced, how many are worth buying, what they are worth, and whether the cap cut that site short. "Craigslist 48 · Facebook 6" over a table of eleven said nothing about which site the eleven came from or where the money was — and the expensive guess is the one where you untick the site that was paying. The cap itself was being spent on the wrong axis: it rationed listings, while every expensive thing downstream is spent per product, so thirty posts of the cheapest phone took thirty of thirty slots and the $400 one that flips for $900 was never looked at.
The Supplier File Analyzer and the rest of the sourcing board →Autosave marked its payload clean before the request had left the browser, so a save that failed was never sent again. The unload beacon's rejection was never read, and it rejects exactly the longest listings. An autosave racing a publish could reset the row and take the duplicate brake with it. And a publish whose draft never reached the app was journalled nowhere at all. Every one of those failures is silent, and the screen went on saying your work was stored.
A payload is clean only once the app confirms it, and is retried until then. A copy is kept on the device and replayed on the next launch. The publish journals itself with its title whether or not a draft exists. And the screen tells you whether your work is actually stored rather than assuming it.
Two pricing faults the same day. The Terapeak price cache stored the median and nothing about the sample behind it, so a cache hit came back with a comp count of zero — and the blend gives a source with no sample size a weight of zero. A figure the app had paid a real browser scrape for was looked up, carried the length of the pipeline, and then multiplied by nothing. That was not the rare path: the cache exists so a scan answers from it rather than driving a browser, so it was nearly every priced row, and the same zero flowed into the row's comp count, its evidence tier, its source label and the confidence score's agreement term. Old rows read back as zero and keep behaving as they did — an unrecorded sample size is not one to invent — and heal on their next scrape. And the spelling retry only fired on zero rows, but a typo does not reliably return nothing: facuc (for fanuc) came back with two listings, both priced as estimates because no sold comp matched them, so the correction never ran and you were told there was nothing worth buying. A scan where every row is the lowest evidence tier has found nothing the board will stand behind, which is the same dead end as no rows at all. Both get the second look now, and the retry only replaces your search when it comes back with something actually better.
How a listing gets built here →Also the day the installer stopped carrying the seller's own photographs to everyone who downloaded it.
There is a folder where the app writes its working images at runtime: AI photo generation leaves files in it, background removal leaves files in it, and the generated-photos folder inside it is excluded from source control precisely because none of it is source. The build's default content rule copied every one of them into the published output — so an installer built on a machine that had actually been used carried that seller's own listing photographs to everyone who downloaded it.
Measured on the build machine: the folder held 307 files, of which 7 are real interface files tracked in source. The other 300 were 60 MB of working images, and they were 60 MB of an 83 MB installer. Excluding them took the distribution from 727 files and 217 MB to 427 files and 156 MB, and the MSI from 83.21 MB to 50.84 MB. They are excluded from packaging rather than deleted — the app still reads and writes them at runtime, and all 7 real interface files are embedded in the executable rather than copied beside it.
Two release fixes went with it. The installer's version number was aligned to the application's, because three numbers have to agree for an update to work end to end and two of them disagreeing is how "I installed it but it still says the old version" happens. And ingmining.com offers the installer now too — as a 302 to the one real file on this site, not a second copy. One binary, not two: a second 50 MB file on another docroot is a second thing to keep in sync and the failure is silent, which is the bug that had already happened here when the button served a four-day-old installer for 58 commits and nothing said so. A redirect cannot go stale. The release script checks the redirect, the bytes behind it and the button in the served HTML on every release, and compares a full SHA-256 of the downloaded file rather than trusting a HEAD request, because on this host a HEAD can answer 200 while the body is an error page.
What this site will not do →Every money column on a deal row comes off one figure — the expected sale price — and that figure is a weighted blend of two sources whose own numbers were overwritten the moment they were combined. The board could say "63% local / 37% Terapeak" and had no way to say 63% and 37% of what. The confidence score beside it was worse: seven weighted terms computed, summed, reported as a bare "62", and the reasons thrown away.
Both are reconstructable now. The two pre-blend medians and the local weighted median are kept, and the trail's stated rule is that the price reproduces from its sources: multiply by the weights it carries, add, and the number on screen comes back out — carried at full precision for exactly that reason and rounded only for display. That rule is the test, and it is pinned on every shape the pipeline produces: two sources, either one alone, an awkward unrounded weight, a median with no expected sale, and a row nothing priced. A breakdown that does not reconcile is worse than none, because it invites you to trust a figure on the strength of working that is wrong.
The confidence score emits its seven terms as rows — points earned out of points possible, this row's own numbers in words, and what would earn the rest — plus the single biggest gap, ranked by points lost rather than by how red a term looks, so a seller missing 20 identifier points is not sent to go and fix a 5-point one. The score arithmetic itself is unchanged; nothing moves. One panel renders it on both the deals board and the Opportunity Finder, so the two screens cannot start explaining the same pipeline differently.
Two things from the same work worth saying. The local row has to quote the weighted median rather than the plain one, because the weighted one is what the blend multiplied — a test drives real comps through the estimator with the dearest sales as the closest matches, so the two genuinely differ and quoting the wrong one fails. And the guard that is allowed to say there is no resale price for a row got 30 tests, because the database behind it will answer "what does a 2011 Tundra sell for" with the median of four tow hitches.
Money Made reports the money. Nothing said how much of it was never yours, and that gap costs real cash in three places.
A sale with no recorded cost contributes nothing to profit on the earnings screen, on purpose — claiming profit that might not exist is the one direction that screen must never be wrong in. The IRS applies the opposite rule to the same sale: with no cost on record the whole of the proceeds is taxable, as though the goods were free. So the figure that is honestly cautious in one place is the one that costs you money on a return, and the block at the top of the Tax Pack is that number with a dollar sign on it. On this account one such sale is $212 of avoidable tax. Second, eBay reports gross payments on a 1099-K — here $12,701, against $4,192 of taxable profit — and a seller who does not know why assumes they owe tax on the larger figure. Third, the estimated-tax windows are 3, 2, 3 and 4 months long, so four equal quarters put June's sales in the wrong payment, which is how you earn a penalty in a year you had the cash for.
So: a Schedule C by line number with the arithmetic printed next to each one, a set-aside rather than a bill — because a set-aside is something you can do today — the cost-basis gap leading the page because it is the one thing there that makes the total go down, real IRS payment dates whose four amounts add up to the year's bill, a 1099-K reconciliation, and two CSVs: the summary an accountant reads and the ledger they check it against. The tax calculation deliberately disagrees with the earnings screen about the same year, and the screen reconciles the two in words rather than leaving one of them looking like a bug. Labour is charged against every forecast in the app and added back here, because you cannot pay yourself a wage and deduct it.
Two faults the live data caught. A fully refunded sale was deducting the cost of goods for an item that had come back — a $180 loss claimed on a unit sitting on the shelf — so a full refund now voids the sale but not the stock, while a partial refund is a price cut and its cost still counts. And Q4's payment date rendered a day early, because a January due date stamped in July's UTC offset crosses midnight once standard time applies. No 1099-K threshold figure is printed anywhere: the federal one has moved three times since 2022 and states set their own, and telling a seller they are not being reported on when they are is worse than sending them to go and look. Read-only throughout — nothing lists, files or leaves the machine except a CSV you asked for.
The miner-specific half of this, worked through →The pre-publish checklist could say a field was empty and nothing else. Every finding ended at "Go to it" — told what eBay wanted, scroll, type. For most of them the answer was already in the room: the brand is in the title the app just wrote, the ZIP is in Settings, and what a packed miner weighs is the entire reason the package estimator exists. That estimator prices every sourcing board in the app and the listing form had never once called it, so shipping got one global default weight for a trading card and a lawn mower alike — or a blank, which quotes nothing at all.
A finding carries the value that resolves it now, and one button applies all of them: brand and part number read out of the title, the saved ZIP, and the packed weight, size and package class from the estimator. Three rules make it safe to press. It never writes over a fact — an offer only attaches to a finding the check itself raised, and the browser refuses again on the way in, because a result rendered a moment before you typed is stale by the time the button is pressed. It never passes a guess off as a reading — anything inferred carries the estimator's own basis on the button that accepts it, because this number prices a shipping label. And an item the estimator did not recognise is offered at low confidence, so it has to be read and clicked on its own rather than swept in by a count.
Package type is the one field here that was never blank, which is exactly what made it dangerous: every listing opens on your default, so a 44 lb miner inherited "Thick Envelope" in silence and eBay quoted the buyer from it. It is only ever corrected upward — you may know something packs flatter than the estimate expects, but nobody benefits from a parcel booked smaller than it is. The button sits above the collapsed fix list rather than inside it, and its label counts what pressing it will actually do, so the promise and the action cannot drift apart. Verified against the running app: six fields in one click.
What the AI fills in, field by field →Settings was the last screen that had never had a design pass: six subjects in one 3,000px scroll, with no way to reach any of them except by scrolling past the other five. It has a sticky, scroll-spied rail now — built from buttons rather than links, because this app routes on the URL fragment and an anchor would have navigated the whole workspace away on its way down the page.
The bug worth naming: Fees & Costs and Listing Defaults were one card with two Save buttons in it, so a seller who filled in both halves and pressed the first had saved neither. Two cards, one Save each. The eleven fee fields are four questions, so they are four named groups. And the units are on the fields — 13.25 was dollars or percent depending on a bracket four words away. Read-only diagnostics moved off the second slot on the page, from above the two steps the app cannot run without, down to the bottom where a thing nobody acts on belongs, which makes the required card's "everything below this is optional" true as written. No endpoint, rule, number or business logic changed.
Two more the same day. The dashboard stopped opening with a wall of recovered drafts — one row per unfinished listing, and with seven of them the entire app sat below the fold. Most of the seven were not abandoned work either: they were autosave snapshots left behind each time the app was restarted during a build, so the banner was mostly reporting its own noise. Autosave is untouched and nothing was discarded — hiding a banner is reversible, deleting someone's part-finished listings is not. And Roll the Dice is held to the same $100 bar the deal board uses: it had been opening with a play netting $33 and another netting $10, neither of which pays for finding, buying, listing and packing the thing, and both of which push down the rows that do. ROI is the default sort there now, and "SELLS FOR" leads the row, because everything else on it is arithmetic derived from that one figure.
The four dashboard numbers, defined →The Terapeak login window loaded fine, and then the credential submit hit eBay's own error page — "Something went wrong on our end" — which reads to a seller as a bad password. The cause was ours: the wait loop was firing a background request at the gated research URL every few seconds while the sign-in POST was still in flight, which is a textbook bot signal that a normal browser never sends. It only probes once you have left the sign-in page now, and it stops re-focusing the window while you are actively typing, which had been dropping keystrokes during password entry.
The connection check also stopped being "does the file exist". One answer was covering five situations with four different fixes — missing, empty, truncated, present-but-stale, present-and-good — and a seller told only "not connected" cannot tell which of those they are in. What eBay served instead of the research page is named too: a sign-in wall, a bot check and an error page all mean "no comps" to the lookup, but they mean very different things to the person, and none of them mean the sold market is empty.
And the sourcing board stopped being all-or-nothing. The sources are searched one at a time on purpose — one of them drives a real browser — so their timeouts add up rather than overlap: six registered sources is 6m45s of searching before a single sold-comp lookup, against a page that gives up at eight minutes. When it overran you lost everything, including the forty Craigslist rows that had arrived in four seconds. The searching has its own budget now, each site is capped by what is left of it, time is charged as measured rather than as allowed, and a site there is no time for is "not searched — out of time", not "error". It was never asked, so calling it an error is a lie about it, and it puts a blocked-looking chip on a site that is working — sending you to check a connection that was never the problem.
The ranking also stopped leading with the row it trusted least. The judge already refuses to go above "thin" when no sold comp carries the item's model number, so a $2,000 profit can be arithmetic on another product's price — and it was sitting at row 1, which is the row somebody drives across town for. Rank sorts on the app's own verdict before the money now, in every mode. Demoted, never dropped: the estimate keeps its place and its figures, money still decides within a band, and losers cannot be lifted over winners.
How a comp set gets cleaned before it is trusted →Thirty-six user-visible changes in two days, grouped by what they were trying to fix rather than the order they were committed in. Nine of them missed the 29 July installer by three hours; all nine are in the 6 August build, and each says so where it sits.
Listing Copilot reads every live listing and every business policy and says what's wrong across all of them at once. The scan writes nothing — it renames nothing, revises nothing and spends no AI credit — because a bulk edit across a live store that fired on page load would be indistinguishable from an accident.
It was checked against a real 89-listing account rather than assumed, and that caught three rules that would each have made an account worse than leaving it alone. Lowercasing before title-casing turned UPS Ground into Ups Ground and SurePost into Surepost. Treating trailing digits as a copy index split the price off the end of a shipping policy, so + Intl $329.99 became $329. 99. And eBay's bulk listing call doesn't return the category at all, which the screen was reporting as "no category" on all 88 listings it had read. The plan went from 35 proposals to 2, and both of those are real.
The rewrite pass covers the whole listing — title, subtitle, a full HTML description and the item specifics — and saves each one as a draft you publish yourself. Three things that used to be assumptions are now code. Your photos are never sent and never touched: the model isn't shown a photo list at all, and the live listing's own images are put back on the draft afterwards, same URLs, same order. Nineteen commercial fields — price, quantity, postage, item location, best-offer settings, per-buyer limits, charity — are copied back from what eBay returned. And the prompt carries an explicit never-invent block, because a blank item specific only costs you a search filter while a wrong one gets you an item-not-as-described return, the item back, and a defect on your account.
On a live listing the title went from Antminer S19 95TH/s Bitcoin Miner | Low Power 2800W Tune | VNiSH Firmware to Bitmain Antminer S19 95TH/s Bitcoin ASIC Miner VNiSH Firmware 2800W Tuned, with 6.6k of description HTML, 11 spec rows and 17 item specifics filled — the brand-then-hashrate shape a buyer actually types. Added since: a checkbox picker, so you can rewrite one listing and look at it before spending on the other 88; a field-by-field diff that tells filled, changed and removed apart, because a specific that disappears is a buyer filter the listing falls out of; a Stop button, which had existed on the server from the start with nothing on screen able to reach it; and readable cards in light theme, where they had been white-on-white.
One rough edge we'd rather publish than hide: the title tidier matches filler words as substrings rather than whole words, so it proposed Cover for Top Cover. That is the argument for the review step. Nothing in here applies itself.
A scan for fanuc came back with one row, and that row couldn't be priced. eBay has 898,905 fanuc listings. Nothing was broken — the search was pointed at the part of the market that is only ever junk.
It asked eBay for the 200 cheapest. A repair shop advertising labour has no cost of goods, so it lists at $0.99 and owns the bottom of that sort: 49 of the 50 cheapest fanuc listings were repair evaluations and manuals. The junk screen correctly binned every one and the board came back empty. Cheapest-first isn't how you find something underpriced, it's how you find whatever was cheapest to list. Fixed-price scans now use eBay's Best Match, and on the same search rows hidden as not-the-item went from 199 to 11, priced products from 1 to 29, and the board from 1 row to 30 — servo amplifiers, interface boards and encoder cables instead of a lathe with no sold history. Auctions keep soonest-ending, because buying before it closes is that mode's whole premise.
Two more ways it reported a real market as an empty one. Every multi-word search was being sent as an exact phrase, so eBay looked for those words adjacent and in that order: miners cryptocurrency returns 0 results quoted and 903 unquoted. Word order inside someone else's listing title isn't yours to predict. The quoted form is still tried first, since where the phrase does exist it's the tighter answer — antminer s19 keeps its 770 over the looser 1,078 — and only a search that finds nothing at all falls back to the plain words. And a typo read as an empty market, because eBay answers antmnier s19 with a flat zero and no correction or suggestion of any kind. An empty scan now gets one spelling pass and a retry: applied and named when the correction finds something to buy, offered as "did you mean" with your own words left in the box when it doesn't.
Depth was the last of it. The eBay scan analysed 30 of the ~200 listings a broad keyword returns while every other scan in the app goes 120 deep — and the rows that clear the $100 bar are a small fraction of what comes back, so a shallow scan mostly returns the fraction that doesn't. At 120: rows clearing $100 went from 3 to 14, and the ones backed by three or more sold comps from 1 to 6. It takes 77 seconds instead of about 25. The fast version was fast at producing nothing.
Results also appear in the panel you searched from now. The eBay Scanner used to print "Searching eBay for…" and then its entire table at the foot of the local-and-online deals card underneath it — a different panel, below a different set of fields — which reasonably reads as the scanner not working at all.
Two things, and neither was the login. The first, fixed on 28 July: a fixed six-minute budget started counting at launch, so a seller who got eBay's bot check two minutes in was solving it against a timer already a third gone — and the finished login was then thrown away, because the session is only written on reaching the research page. The wait is now measured from the last sign of progress, and the first sight of a CAPTCHA grants a fresh ten minutes from when the challenge appeared.
The app also stopped reporting four different connection failures as one thing. A dead Terapeak session, an unreachable comps API and a never-configured key all came out as the same empty result, and nobody could tell which one to go and fix. Settings now opens on a Connections panel: one row per connection, six named states, the exact reason a row is down, and the button that starts the right fix. The checks are real, because "the session file exists" is the answer that made this necessary — eBay does a live token refresh and an authenticated Sell API call, while Facebook and Terapeak have their saved sessions replayed and are asked whether the site still considers them signed in. A row reads Connected only when a check just said so; before one runs, every row is explicitly unknown. Two faults only showed up against live sessions, and both would have called a working connection dead: Facebook refuses a bare request but serves a real navigation, eBay does the exact reverse, so the probe asks both ways — and eBay's bot-check page is not a logged-out page, so it gets its own verdict instead of being called an expired session. A false "expired" is the most expensive thing this can say, because it sends you through a six-minute interactive re-login to fix something that was never broken. Nothing is reported but booleans, expiry dates, HTTP statuses and row counts.
Signing in to eBay is four hops — the app, eBay's consent page, the relay on this site, then the app again — and three of them happen in a browser tab the app doesn't control. Every way they could end without anyone calling back used to end identically: nothing happened, and the screen waited. Each ending is now bounded and named. An authorization URL that can't come back isn't handed out at all, so a missing client secret is reported here instead of failing on eBay's side with wording that blames the app. And your refresh token — an 18-month grant only you can replace — is destroyed by exactly one thing: eBay explicitly answering invalid_grant. A timeout, a 5xx, a mistyped secret and a bare 400 all keep it and retry. Saved files go through an atomic replace now too, so a crash mid-write can't leave half a credentials file where the credentials used to be, and a second copy of the app no longer races the first.
Failed to fetch is gone: clicking Scan My Account with the backend closed showed the browser's own words for "this request never reached a server" to somebody who sells on eBay. 107 call sites now go through one translator, and the page knocks on the app until it answers, then turns the banner green and re-runs the scan you originally clicked.Today's Picks was a wall of photos with an asking price and a town on each. "$600 Segway gokart pro2" is not information — you still had to leave the app, look up what one sells for, and work out whether $600 was a buy. That lookup is the entire job this thing exists to do. Every card now carries what it sells for on eBay, how many sold comps that's based on, the profit after fees and shipping, and the ROI. A card with no matching sold history says no sold data rather than showing $0 profit: one is the truth and the other is a claim. It prices down the same pipeline as the scan boards instead of a second copy of it, because two pricing paths drift and you'd eventually get two different answers for the same item.
Boards are ranked by return rather than size. Net profit put one $857 row above ten $150 flips, and the $857 row was the one resting on a single loose sold comp — $421 back on $36 beats $857 back on $800 when the cash is the constraint. The $100 floor still sits underneath the sort, so ranking by ROI can't surface a 900% return on four dollars.
Two things landed on 28 July. The eBay scanner went above the fold with the local marketplaces and coupons under it — this is an eBay app that wasn't showing eBay — and every result carries its thumbnail, because rows that came back without one were rendering as a bare line of text that read as broken rather than as a listing with no photo. And Deal Radar stopped hiding the nationwide sources: six were registered and four were shown, because the list filtered on "is this local", which dropped eBay and the retail feeds — they ship anywhere and carry no distance — one layer above where anyone would look for them. eBay stays unchecked by default, matching Facebook: it needs a connection, and login-gated sites only run unattended when you ask.
Facebook's Sold and Pending tiles are recorded now too, in their own table, and pointedly not treated as comps. Facebook publishes no sale prices — only the last asking price before a listing disappeared — so the column is named last_ask_price, the row type has no sold-price property at all, and the endpoint states that in its own payload rather than leaving it to be assumed. It fixed two live faults on the way: sold items were being ranked as buyable deals, and sold prices were dragging the local asking median toward a number nobody can buy at.
The app installs from an MSI and never phoned home, so whoever installed in July was still running July's build with no way to find out. Shipping improvements nobody receives is the same as not shipping them — and on 28 July the installer on this site was four days and 58 commits behind the code. That isn't a hypothetical; it's what the release script's own commit message records, and it's why the note at the top of this page exists.
There's one calm banner now when a newer version exists. It reads the latest release tag from the public repo, caches the answer for six hours (GitHub's unauthenticated API allows 60 requests an hour per IP, shared across every install behind one address), compares versions numerically part by part — as text, "2.10.0" sorts below "2.9.0", which would hide exactly the update that matters most — and answers "no update" for every failure, so being offline or rate-limited never reaches you as an error. It points at the download page rather than the git tag, because a tag exists the moment it's pushed while the installer exists only once it has been packaged and uploaded.
Releasing is one script now: test, publish, package, back up the live installer, upload, verify — refusing to continue at each step that fails. The verification step is the reason it exists rather than a shorter script, because every previous failure here was silent: the upload reported success and the download button kept serving the old file. The last step re-reads the public URL and fails the release unless the size matches the file just built and Last-Modified actually moved. A ship that can't prove itself hasn't happened. It backs the live MSI up to a dated copy first, since an installer is the one artefact where putting the old one back has to stay possible without a rebuild, and it deliberately doesn't push or write release notes — both want a human to look first.
Smaller, from 28 July: the earnings import had to be started by hand every time, and failed often enough that it stopped being worth starting. It runs off the eBay connection itself now.
How the guides get written, and who writes them →The dashboard's Get Started list asked for eBay business policies. It was removed at the seller's request — and removing it took the whole panel with it, twice, which is a fair illustration of why small changes get grouped into a changelog instead of announced. The row read "Connect eBay and pick your business policies": one row doing two jobs, so deleting it deleted the eBay step, and with nothing left unfinished the checklist decided it had nothing to show and hid itself. Step 2 is back as Connect eBay alone, it no longer waits on policies to count as done, and its button goes to the eBay login rather than the policy picker. The panel now goes away only when you dismiss it with its own X, and the hero chip that read "eBay connected — policies needed" stopped repeating the same nag in a second place. The picker itself is untouched: Settings and the New Listing form still take policies whenever you want to set them.
This is the worst bug on the page and it was completely silent. An imported listing has an eBay item ID but no Inventory API offer ID, so the editor took its no-offer-ID branch and called ReviseInventoryStatus — a request that carries the item ID, the price and the quantity, and nothing else. Title, description, condition, condition description, category and item specifics were all built into the request and dropped on the way out.
Nothing looked wrong from any side. eBay returned Success, because the smaller call it received was itself valid. The endpoint returned ok. The screen said "Published to eBay live". The log recorded "eBay listing revised". Most of a seller's catalogue is imported, so for most listings the editor changed nothing and told you it had.
That branch now uses ReviseFixedPriceItem, which is the call that can change those fields on an existing item ID, and the response names the fields that actually landed instead of asserting a publish. Two things it deliberately won't send: eBay-hosted images, because importing a listing returns one URL and it's the 140px gallery thumbnail — send that back into a revise and you permanently replace the whole photo set on a live listing with a postage stamp — and blank fields, since in a revise an omitted field means "leave it alone" while a present-but-empty one overwrites. A Warning acknowledgement is no longer treated as plain success either: eBay accepting a revision and quietly dropping a field is how this stayed hidden.
<div style="font-family:Arial…"><h1 style="color:#111;"> where the description should have been. The New Listing form had solved that a while back with three tabs — Edit Text, Edit HTML, Preview — and the edit drawer had none of it, so the same description was readable on one screen and raw source on the other. The drawer has the same three tabs now, driven by the same code rather than a copy of it, and it opens on Edit Text. Preview renders the HTML without running it, which was a live hole and not a theoretical one: a description carrying <img src=x onerror=…> fired the handler during plain-text extraction, before a single tag had been stripped. That HTML is Claude's, or eBay's, or pasted in from someone else's listing — it isn't yours. And the character counter said 0 / 4000 while the SEO template writes 6–7k against a 9,000 ceiling, so it flagged every AI-written description as over budget and taught you to ignore it. Both screens count against 9,000.Merged, tested and packaged. None of this was in the 24 July installer; all of it is in the one on the download button.
Snap & Source takes a photo or a pasted listing link and answers in one word, with the most you can pay and still clear your margin. What makes it usable is the two answers it gives when it doesn't know: a thin-comp warning when the sold history it found doesn't carry the item's model or part number, and a flat can't price it when nothing matched at all. In testing it caught its own bad basis — an Antminer S19j Pro priced off comps that were mostly parts and accessories — and said so on the card rather than printing a confident number.
The desk version of the same question →Deal Radar saves a search — what, where, how far, and the smallest profit worth driving for — then re-runs it every few hours, prices what it finds against the same eBay sold comps the rest of the app uses, and only interrupts you when something clears your bar. It is read-only: nothing buys, bids, lists or messages anyone. It reads each site once per scan, one scan at a time, never signs into anything on a schedule, and never alerts the same find twice. The figure on an alert is frozen at the moment it was found, because a classified is deleted the hour it sells and an alert that re-read its own listing would blank itself exactly when you want to know what you missed.
Sourcing also stopped assuming the item fits in a box. Cars, boats, RVs and anything else that never ships now run through the same pricing and profit rules, with the delivery side simply removed rather than fudged.
How the sourcing screens work →
A new install used to open Settings on Image Generation — a mode picker and a Stable Diffusion endpoint — above everything the app actually needs. Settings now leads with two required steps, each with a live saved/needed pill: your Claude API key, and your eBay business policies. Everything else moved into an optional section.
Underneath was a worse bug with the same shape. Because the save endpoint couldn't tell "this screen wasn't showing that field" from "this field is blank", saving the optional image settings cleared the required eBay business policies and every listing default. So did activating a licence. So did pasting an eBay token. The next publish then failed with an eBay error about a missing policy, on a screen that had never mentioned policies. Absent and empty are now different things.
What connecting the store gets you →Every tool you open now stays open in its own tab. Before this, opening a screen closed the one before it — find a pallet on the Lot Analyzer, go price the parts, come back, and the manifest was gone and the scan ran again. Switching back to a tab does not re-run its scan, which matters because a finished board cost real eBay calls and comp lookups. Two screens are exempt on purpose (Logs and Licence re-read, because they are nothing but server state), and the Auction Sniper's countdown starts and stops with its own tab so no timer runs for a screen nobody is looking at.
The look caught up with the feature count in the same stretch. Twenty-odd feature sessions had each reached for whatever colour was to hand, leaving 157 distinct hex values and 406 hard-coded font sizes across 10,147 lines of CSS — generic web reds and greens on the profit figures, a navy-and-yellow photo editor, a slate-grey setup flow. Now every colour comes from one set of ramps (the raw values left are all plain white) and exactly one hard-coded size survives. On top of that: a motion pass so the app answers when you touch it, real charts instead of number grids, dense tables made scannable, a front page rebuilt from six stacked full-width bands into a masthead, three actions, a money row and a market pulse — and light and dark themes off the same tokens.
Nothing in this group changed a price, a rule or a number. Two known limits, since they're the kind of thing you'd otherwise report: open tabs don't survive a restart (the app reopens the one screen the URL names), and tabs can't be dragged into a different order.
See the dashboard →A $60 trailer hitch on the Local Deals board was showing a $554 resale price and 698% ROI off one loose sold comp. Nothing on the row was arithmetically wrong; the price it rested on was worthless, and the board printed the percentage in the same typeface as one backed by twenty sales. That's the one row a seller drives to.
Two separate faults, fixed separately. The comp count on screen was never the comp count behind the price — a twelve-comp search that ended up pricing off one still displayed "12 sold comps", and every evidence check in the app trusted that number. And the identity guard, which filters comps down to the ones whose titles actually carry the item's model or part number, fell back to the unfiltered set whenever fewer than three survived — precisely the case where the filter was the only thing standing between you and a $74 fuse priced off $1,050 drives. Now three tiers, and only the top one is allowed to make a claim: a row with no model match is capped at thin at any comp count, and its figures are dimmed and labelled as estimates rather than deleted. Shipping cost also now lands on every price in the app instead of being the thing you remember afterwards.
Why keyword-matched sold averages mislead →Five new sources, all priced through the same profit engine: retail and clearance stock when your town has nothing to sell you, businesses closing down and liquidating, things people are giving away, and used stock that still carries a warranty. Coupon and promo codes are now found and stacked before profit is computed, not celebrated after. And Spend My Budget allocates a fixed amount of cash across everything on the board by what it earns back, which is rarely the same answer as buying the single biggest deal.
Rescue Aging Stock works old inventory down on a schedule you'll actually follow, and Lost Sales goes after the sales that nearly happened: relists, plus Second Chance Offers to the people who bid and lost.
The crash-recovery banner also got its credibility back. Its test for "is this draft worth saving?" was a size check — under 400 characters and it was discarded. But an untouched blank listing form already serialises about 500 characters of defaults, so opening the AI listing screen, looking at it and closing it wrote a recovery row, and the next launch announced "an unfinished listing was recovered" over an empty draft called Untitled listing. Shown that twice, nobody reads the banner on the launch where it's holding a real listing. It now names the fields that carry your own work instead of weighing the bytes, and it judges existing rows when it reads them, so the banner is clean on the next launch rather than the next save.
Eight things landed in one evening, and they share a spine: every one of them is the same sold-comp math pointed at a different decision.
Auction Sniper works out the most you can bid on an eBay auction and still make your margin — and it never places the bid; the number is the product. Its first real scan over 69 live listings dropped 61 as not the same item and found nothing worth bidding on, which is the honest result and the one it reported. Where to Sell Highest compares venues instead of defaulting to the one you always use. The lot and pallet analyzer answers the only question a manifest raises: buy this, or walk. The Ad Rate Advisor picks a promoted-listings rate that keeps the most money rather than the rate eBay suggests. Trends shows what's climbing so you can buy it at last month's price. Boards began ranking by how fast the cash comes back, not by the fattest gross margin. Buy-side negotiation drafts the message and tells you where to stop. And take-home — all-in net, break-even and your offer floor — now sits on every price in the app.
The sold-comp data underneath all of this →Offers to Watchers sends a private, time-limited discount to the buyers watching a listing, at a price it works out from your own floor rather than a flat percentage. On our own account the first scan found 53 listings with watchers — 1,527 of them — and eBay cleared 31 of those listings to carry an offer. One honest limit worth stating: no real send has ever been fired from it. Every layer underneath was exercised, but the final click puts a non-recallable offer in front of real buyers, so it belongs to the account owner.
Roll the Dice is for the other problem — not knowing what to look for. It sweeps whole categories of real sold prices and then goes and finds where to buy the ones that clear.
Where offers fit next to repricing →Inventory Health scans what you already have live and says which prices are holding cash. The first run against our own account read 87 active listings with a median age of 199 days. It also got three things wrong before the rules were tightened, and the best of them is worth repeating: a 138-day listing that looked 38% above market had actually sold 44 units and had 64 watchers, and the discount ladder wanted $105 off each of the 80 remaining — $8,400 off a listing that was working. Fixing that moved the stale-capital headline on the same inventory from $260,218 to $185,664. That inventory is mostly ASIC miners, where the right price tracks hashrate rather than how long the listing has been up.
Read the full write-up →The app now asks eBay what a category requires before you publish, instead of finding out by failing, and it separates blockers from warnings rather than blurring the two. Failures became recoverable across the board: no silent errors, no lost drafts, no duplicate listings from a retry. A Local Deals scan can no longer dead-end — every source reports its own status and partial results still render.
Three small fixes in the same stretch, each the kind of thing that quietly wastes an hour: an eBay-only refresh was wiping the "AI key saved" tick; the eBay login window opened behind the app; and an unverified sell-through rate wore a green badge instead of saying low confidence — thin data. Also new: a representative photo library so used items reuse the shots that already work, with the used-item photo gate applied to the upload path too, and a cross-listing export for Facebook Marketplace, Mercari and Amazon.
How a listing gets built →Facebook Marketplace by zip code and radius, then Craigslist through the same pipeline — the arbitrage board stopped knowing which source a row came from, which is what made adding the second one cheap. Rows are ranked by profit after fees, not by the gap between the asking price and a sold price, because gross spread flatters heavy items and anything with a high fee load. The first real design pass landed here too: one design system, and real empty, loading and error states instead of blank panels.
What a photo can and can't tell you →Shipped in the 24 July build and carried forward into the current one.
The app became a free public beta — every feature unlocked, nothing behind a paywall — and the installer ships without any API key of ours in it; you bring your own Claude key, which is also why running costs stay yours and stay visible. The old startup Settings pop-up is gone: you activate from the home page when you're ready. Sold-comp pricing also stopped stepping between confidence buckets and now blends your local sold history with Terapeak on a smooth precision weighting, so one extra comp nudges the estimate instead of jumping it. Installer bumped to 2.3.1.0 so upgrades genuinely replace the old install rather than sitting beside it.
The full guide to the AI listing flow →It no longer installs a Windows service — the app runs as the logged-in user, which is what a desktop tool should do. The local-DNS trick it used to pull (writing to your hosts file) is removed entirely, because nothing that wants to stay on good terms with your antivirus should be editing that file. The finish screen offers a checked-by-default "Open ING AutoLister now", and versions are bumped properly so an upgrade replaces the install.
On the pricing side, the sold-comps bar became permanent instead of appearing only when it had something to say, with a Connect-to-Terapeak prompt when it doesn't, seven comps shown in a larger bar, and the Terapeak login window raised so it stops flickering behind the app. Your own local sold history started feeding the average at a fixed 40% weight — which the smooth weighting on the 24th then replaced.
Connecting a real store →Listings gained a right-side edit drawer with market research inside it, so pricing and specifics stopped being a separate trip, plus keyboard shortcuts for the fields you touch on every item. An accessory-detection scoring bug was fixed — that's the code whose job is to stop a part or an accessory being scored as the machine it fits. And the app got a real x64 MSI with its icon embedded, instead of a folder you ran from.
Type a product name, get a listing →Anything not listed here is either internal (tests, build scripts, the admin panel) or older than 22 July 2026. That earliest release note — sold-comp research moving into the listing flow, and the first look at Opportunity Finder — is still up in full, and every guide is indexed on the guides page. If a screen in the app does something this page doesn't mention, the page is wrong — tell us and it gets fixed.