<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="pretty-atom-feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>DeepakNess - Notes</title>
  <subtitle>Short notes, links, and thoughts – shared as I go through my day.</subtitle>
  <link href="https://deepakness.com/feed/raw.xml" rel="self" />
  <link href="https://deepakness.com/raw/" />
  <updated>2026-06-08T03:28:52Z</updated>
  <id>https://deepakness.com/raw/</id>
  <icon>https://deepakness.com/img/deepakness.png</icon>
  <logo>https://deepakness.com/img/deepakness.png</logo>
  <author>
    <name>DeepakNess</name>
  </author>
  <entry>
    <title>Hardening a VPS with Tailscale</title>
    <link href="https://deepakness.com/raw/hetzner-vps-tailscale/" />
    <updated>2026-06-08T03:28:52Z</updated>
    <id>https://deepakness.com/raw/hetzner-vps-tailscale/</id>
    <summary>Hardening a public VPS by moving admin panels behind Tailscale while keeping websites public.</summary>
    <content type="html">&lt;p&gt;I recently hardened this Hetzner VPS after realizing that keeping admin panels open to the whole internet is just unnecessary risk. And honestly, &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/levelsio/status/2033546675063554213&quot;&gt;@levelsio gave me the idea&lt;/a&gt; to use Tailscale from a few posts he made about this on X.&lt;/p&gt;
&lt;p&gt;On this VPS, I still have a few WordPress sites hosted through a control panel, and I wanted to make the server safer without deleting websites, moving data, or breaking normal access.&lt;/p&gt;
&lt;p&gt;The main idea was simple: websites stay public, admin access becomes private. Ports 80 and 443 stay open because visitors need them. DNS, public web traffic, nothing changes from the outside.&lt;/p&gt;
&lt;p&gt;But the control panel on its admin port, the web server admin panel, and SSH don&#39;t need to be open to every random scanner on the internet. Those are management interfaces, not public website features.&lt;/p&gt;
&lt;p&gt;Tailscale gives the VPS a private network address that only approved devices can reach. So I can open the control panel from my computer through the Tailscale IP, but someone scanning the public VPS IP cannot hit the login page anymore.&lt;/p&gt;
&lt;p&gt;The important part is the order. Don&#39;t close public SSH first – that&#39;s how you lock yourself out.&lt;/p&gt;
&lt;p&gt;The safe order I followed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;take a snapshot first&lt;/li&gt;
&lt;li&gt;then install Tailscale on the VPS and add it to your account (disable key expiry)&lt;/li&gt;
&lt;li&gt;install Tailscale on your local machine&lt;/li&gt;
&lt;li&gt;test that the control panel, web server admin, and SSH all work through the Tailscale IP&lt;/li&gt;
&lt;li&gt;disable anything unused like FTP&lt;/li&gt;
&lt;li&gt;restrict the admin ports&lt;/li&gt;
&lt;li&gt;and only after all of that, restrict public SSH&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For Tailscale, I used &lt;code&gt;--accept-dns=false&lt;/code&gt; because I didn&#39;t want it changing DNS behavior on the VPS. This server hosts websites and mail, so the change needed to be narrow: add private access, don&#39;t surprise anything else.&lt;/p&gt;
&lt;p&gt;Before changing any firewall rules, test everything over the Tailscale IP first. Confirm SSH, the control panel, and the web server admin all work. Once that&#39;s solid, allow those ports from Tailscale&#39;s private IP ranges and remove the public access rules for them.&lt;/p&gt;
&lt;p&gt;For SSH, I used a rollback safety net: a systemd timer that automatically reopens public SSH after 3 minutes if I got locked out. After removing public SSH, I immediately tested both Tailscale SSH (should work) and public SSH (should fail). Only after confirming Tailscale SSH works, cancel the rollback timer.&lt;/p&gt;
&lt;p&gt;A few things to remember: keep cloud console/rescue access available as a backdoor, keep Tailscale running on your machine before trying SSH or admin panels, firewall rules aren&#39;t active until you reload, and always test websites after any firewall change.&lt;/p&gt;
&lt;p&gt;This isn&#39;t the same as rebuilding a compromised server. It&#39;s a practical hardening pass. But for a VPS that needs to keep running websites, it&#39;s a big improvement: keep the public web public, and make the sensitive admin stuff reachable only from your own devices.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Using the Composer 2.5 model in Pi agent harness</title>
    <link href="https://deepakness.com/raw/pi-composer-2-5/" />
    <updated>2026-06-02T14:25:47Z</updated>
    <id>https://deepakness.com/raw/pi-composer-2-5/</id>
    <summary>The best way to use Composer 2.5 inside the Pi coding agent harness via official Cursor agent SDK.</summary>
    <content type="html">&lt;p&gt;Cursor released the Composer 2.5 model a while ago, and it&#39;s very capable model while being super cheap. And since I also love the Pi coding agent, I wanted to use the Composer 2.5 model inside Pi and found the perfect solution for it.&lt;/p&gt;
&lt;p&gt;It&#39;s called &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/fitchmultz/pi-cursor-sdk&quot;&gt;pi-cursor-sdk&lt;/a&gt; and is created by &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/fitchmultz&quot;&gt;Mitch Fultz&lt;/a&gt;. It uses the official Cursor SDK so &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/fitchmultz/status/2061779337549087208&quot;&gt;Cursor&#39;s agent loop and tools are still used&lt;/a&gt; when using the model via the Pi agent. And it&#39;s a great thing because Cursor has one of the best agent harnesses out there.&lt;/p&gt;
&lt;p&gt;I have been using it for the last few days, and it works flawlessly.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Trying the new MiniMax M3 model via OpenCode</title>
    <link href="https://deepakness.com/raw/trying-minimax-m3/" />
    <updated>2026-06-02T06:11:23Z</updated>
    <id>https://deepakness.com/raw/trying-minimax-m3/</id>
    <summary>MiniMax M3 model was released a day ago and it&#39;s a good model, especially for UI design.</summary>
    <content type="html">&lt;p&gt;MiniMax M3 was &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://www.minimax.io/blog/minimax-m3&quot;&gt;released a day ago&lt;/a&gt;, and currently it&#39;s available in OpenCode for free for the last 2-3 days (yes, from even before the release). I, finally, gave it a try and it&#39;s so good, at least at UI design.&lt;/p&gt;
&lt;p&gt;For example, &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://incomparable-concha-d82f3f.netlify.app&quot;&gt;I created this website&lt;/a&gt; using &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2061440252787741002&quot;&gt;just two prompts&lt;/a&gt; (will share below) and it looks stunning. I am damn sure that Codex could never do this, and it&#39;s just Opus 4.8 level design but a lot cheaper. I have also taken a full page screenshot that you see here.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A personal website design by the MiniMax M3 model&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/trying-minimax-m3/personal-website-by-minimax-m3.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;And if you&#39;re curious, prompts were:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prompt 1:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;create a stunning personal website for a developer. use dummy info. don&#39;t use any framework.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prompt 2:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;make it in light mode and don&#39;t use serif fonts. and make the design and ui even better.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After seeing it work great at the UI design, I asked it to &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2061687006842020265&quot;&gt;redesign the entire dashboard&lt;/a&gt; for a new project I am working on, and it did a great job. I approved the plan and left it overnight, where it should have worked for a few hours and then when I woke up in the morning, it was ready. It had several minor errors which Codex quickly fixed, and I loved the overall UI and UX it did. I will soon be merging the new branch to the main.&lt;/p&gt;
&lt;p&gt;For all these things, I used it for free via OpenCode (for a limited time), but if you wanted to try MiniMax M3, they have a very generous plan on their official website. Their &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://platform.minimax.io/docs/guides/pricing-token-plan&quot;&gt;$20/mo plan&lt;/a&gt; can get you up to ~1.6 billion tokens when you use the new M3 model. MiniMax has also released &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://agent.minimax.io/download&quot;&gt;a desktop app called MiniMax Code&lt;/a&gt; and is currently available for macOS as well as Windows. It looks very similar to the Codex app, though.&lt;/p&gt;
&lt;p&gt;By the way, since MiniMax M3 is an open-weight model, you can also try the new model via any other inference provider like OpenRouter and others.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Pi agent lessons from Dillon&#39;s shared session</title>
    <link href="https://deepakness.com/raw/pi-agent-lessons-from-dillon/" />
    <updated>2026-05-30T23:49:27Z</updated>
    <id>https://deepakness.com/raw/pi-agent-lessons-from-dillon/</id>
    <summary>A few practical notes from Dillon Mulroy&#39;s shared Pi coding agent session.</summary>
    <content type="html">&lt;p&gt;I spent some time reading &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/dillon_mulroy/status/2060018957227061299&quot;&gt;Dillon Mulroy&#39;s&lt;/a&gt; shared &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://pi.dev/session/#5ddc8747b98a80ad993c18e95270038e&quot;&gt;Pi session&lt;/a&gt;, and honestly, I learned more from the workflow than the docs.&lt;/p&gt;
&lt;p&gt;The main thing I noticed is that he doesn&#39;t use Pi like a quick code generator. He uses it more like a supervised senior implementation partner. The agent is not just asked to &quot;build this thing&quot;. It is given specs, constraints, examples, review notes, and a clear process.&lt;/p&gt;
&lt;p&gt;A few things I want to copy in my own Pi workflow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Write the spec first&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before asking Pi to implement a large feature, create a small but clear tech spec with goals, constraints, routes, data model, edge cases, and test plan.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Add working-style rules to &lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;My current &lt;code&gt;AGENTS.md&lt;/code&gt; has tool preferences and writing style rules. I should also add how I want to work – something like &quot;prefer 3–5 small focused prompts over one large prompt&quot;, or &quot;never rewrite a file without showing me the diff first&quot;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Do architecture review before coding&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Instead of directly saying &quot;rebuild this&quot;, first ask Pi to inspect the existing files and explain where the design is weak, where cohesion breaks, and what should be changed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Ask for call graphs and seams&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before implementation, ask Pi to sketch the public API, call graph, injected seams, and production vs test adapters. This makes bad design visible before code is written.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Use skills for methodology&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A simple prompt like &quot;use TDD&quot; is weaker than a full TDD skill. Dillon injects an inline &lt;code&gt;&amp;lt;skill&amp;gt;&lt;/code&gt; block that defines the philosophy, anti-patterns, and step-by-step workflow. I should create or reuse small skills for TDD, review, UI polish, refactors, and audits.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. Use vertical slices&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One failing test, one small implementation, one passing check. Don&#39;t ask the model to build the whole dashboard or whole feature in one go.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7. Give hard constraints&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Prompts should include rules like: no new package, no mock data, no broad rewrite, no nullable return, no touching unrelated files. This keeps the agent on a tighter leash.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;8. Use markdown annotations for review&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Instead of explaining everything again, paste notes like this and ask Pi to apply only those changes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## Markdown Annotations
- Section 4.1: update status to &quot;implemented&quot;
- Line 42: rename `fetchUrl` to `resolveShortLink`
- Section 3: remove the assumption about Cloudflare D1 – it&#39;s now R2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;9. Codify mistakes permanently&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When Pi makes the same kind of mistake, don&#39;t just fix it once. Add the rule to &lt;code&gt;AGENTS.md&lt;/code&gt; so future sessions inherit it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;10. Use reference repos&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For framework-specific work, keep local clones or examples and ask Pi to read those first. Real examples are better than model memory.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;11. Use the session tree properly&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If a design exploration is risky, fork the session. If it goes wrong, abandon that branch instead of trying to repair a messy conversation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;12. End with a handoff&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At the end of a longer task, ask Pi for what changed, tests run, files modified, open issues, and the next 5 todos.&lt;/p&gt;
&lt;p&gt;This is probably the biggest takeaway for me:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Better agent results come less from one perfect prompt and more from a better engineering loop.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The loop should be something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;review the existing design
→ sketch options
→ agree on the shape
→ write or update the spec
→ implement one vertical slice
→ run checks
→ review with annotations
→ save new rules in AGENTS.md
→ hand off clearly
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I already use Pi with DeepSeek, web access, goal tracking, and vision proxy, and I wrote about that setup in my &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/blog/pi-agent-setup/&quot;&gt;Pi coding agent setup post&lt;/a&gt;. That setup is working nicely, but Dillon&#39;s session made me realize that it is still mostly tool-focused.&lt;/p&gt;
&lt;p&gt;The next improvement is process-focused – better specs, better review loops, better constraints, and better handoffs.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Cheaper coding models are excellent with good prompts</title>
    <link href="https://deepakness.com/raw/prompting-cheaper-vs-sota-models/" />
    <updated>2026-05-29T12:17:10Z</updated>
    <id>https://deepakness.com/raw/prompting-cheaper-vs-sota-models/</id>
    <summary>Cheaper coding models like Composer, DeepSeek, Kimi, GLM, and Qwen can be excellent, but you can&#39;t prompt them like Claude Code or Codex.</summary>
    <content type="html">&lt;p&gt;Dan &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DanKulkov/status/2059863021120622749&quot;&gt;posted about cancelling Cursor after 30 minutes of using Composer 2.5&lt;/a&gt;, and while the wording was too harsh, I don&#39;t think the frustration itself is completely wrong.&lt;/p&gt;
&lt;p&gt;I &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2060214202472759303&quot;&gt;posted about this on X&lt;/a&gt; as well, but I think the main thing people miss is that cheaper or smaller models need to be prompted differently.&lt;/p&gt;
&lt;p&gt;You can&#39;t prompt DeepSeek, Kimi, GLM, Composer, Qwen, or other similar models the same way you prompt Claude Code or Codex.&lt;/p&gt;
&lt;p&gt;With Claude Code and Codex, especially with the latest models, you can throw a broad task at them and expect the model to explore the repository, understand patterns, implement the feature, run tests, and come back with something mostly correct. It will still make mistakes, obviously, but it can handle much more ambiguity.&lt;/p&gt;
&lt;p&gt;But these cheaper models are not great at that kind of one-shot work.&lt;/p&gt;
&lt;p&gt;If you ask them to &quot;build this full dashboard&quot;, &quot;rework the entire app&quot;, or &quot;implement this complete feature end-to-end&quot;, the result is usually messy. They will often do too much, miss existing patterns, break small things, or create a UI that looks good in one part but doesn&#39;t fully fit the app.&lt;/p&gt;
&lt;p&gt;But if you go feature-by-feature or page-by-page, they can be excellent.&lt;/p&gt;
&lt;p&gt;For example, instead of saying:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Build the entire analytics dashboard with filters, charts, empty states, settings, export, and responsive UI.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I would rather ask:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;create the empty dashboard layout&lt;/li&gt;
&lt;li&gt;add only the filters section&lt;/li&gt;
&lt;li&gt;create the first chart&lt;/li&gt;
&lt;li&gt;add loading and empty states&lt;/li&gt;
&lt;li&gt;make the table work&lt;/li&gt;
&lt;li&gt;polish spacing and mobile layout&lt;/li&gt;
&lt;li&gt;now review the whole page and fix rough edges&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is a different workflow. You need more patience. You need to be more involved. You need to keep the model on a tighter leash.&lt;/p&gt;
&lt;p&gt;But the tradeoff is worth it in many cases because these models are cheap and fast enough that iterating with them still feels good.&lt;/p&gt;
&lt;p&gt;A few days ago, I built a small internal feature for SharePDF using DeepSeek V4 Pro via Pi agent. And honestly, the UI was far better than what Codex usually gives me, and everything worked as expected as well. But I didn&#39;t ask it to rebuild the whole product in one prompt. I gave it a smaller scope, checked the output, and then continued from there.&lt;/p&gt;
&lt;p&gt;This is why I still think models like Composer 2.5, DeepSeek, Kimi, GLM, and Qwen are very useful. In fact, I have already written that &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/raw/using-composer-2-5/&quot;&gt;Cursor&#39;s Composer 2.5 is awesome&lt;/a&gt; and that &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/raw/cursor-value-for-money/&quot;&gt;Cursor&#39;s $20 plan is great value&lt;/a&gt;. That doesn&#39;t mean the model will behave like Claude Code or Codex in every situation.&lt;/p&gt;
&lt;p&gt;Sometimes when you have the option, there is no point using the cheaper model. If I&#39;m doing a complicated refactor, touching billing logic, debugging something subtle, or making a change across many files, I would still prefer the best model I have access to.&lt;/p&gt;
&lt;p&gt;But if I&#39;m designing a page, improving UI, adding a smaller feature, or doing something where I can review each step quickly, I don&#39;t mind using cheaper models at all. In some cases, I even prefer them. I still consider Qwen 3.7 or even 3.6 Plus models far better at design than GPT models.&lt;/p&gt;
&lt;p&gt;So I think the correct conclusion is not &quot;Composer is bad&quot; or &quot;DeepSeek is bad&quot; or &quot;cheap models are useless&quot;.&lt;/p&gt;
&lt;p&gt;The correct conclusion is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;don&#39;t use a cheaper model like a SOTA model.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Use Claude Code or Codex when you want more autonomy. Use DeepSeek, Kimi, GLM, Composer, or Qwen when you are willing to drive more actively.&lt;/p&gt;
&lt;p&gt;Both can be great. You just can&#39;t expect the same prompting style to work everywhere.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Cursor&#39;s $20 plan offers the best value for month</title>
    <link href="https://deepakness.com/raw/cursor-value-for-money/" />
    <updated>2026-05-27T17:37:42Z</updated>
    <id>https://deepakness.com/raw/cursor-value-for-money/</id>
    <summary>Tried using Cursor after 5 months, and I think their Pro plan is the best subscription you can ever get.</summary>
    <content type="html">&lt;p&gt;I last used Cursor in January this year, because it later started seeming too costly. But after their Composer 2.5 model release, I tried Cursor again after 5 months and I loved it a lot. I have been using it for a little over a week now, and it&#39;s the best model for the price out there.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cursor usage&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/cursor-value-for-money/cursor-usage.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;At the time of writing this post, I have used over 430 million tokens in total where almost 320 million tokens are only from Composer 2.5, as you see in the screenshot above.&lt;/p&gt;
&lt;p&gt;I have written &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2057819438158893452&quot;&gt;a post on X&lt;/a&gt; about things I like about Cursor and then things I don&#39;t.&lt;/p&gt;
&lt;p&gt;By the way, I am only on the $20/mo plan for Cursor Pro, and then I have only finished 54% of the monthly limits as of now. I am surprised how good the limits are even on the $20 plan, and I must say, again, that Composer 2.5 is a great model.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Fixing Cursor app&#39;s too much resource usage</title>
    <link href="https://deepakness.com/raw/cursor-app-resource-usage/" />
    <updated>2026-05-26T05:25:19Z</updated>
    <id>https://deepakness.com/raw/cursor-app-resource-usage/</id>
    <summary>Found the issue of Cursor app using 2-3 CPU cores at 100% each, and found the culprit. Thanks to Codex.</summary>
    <content type="html">&lt;p&gt;Cursor app had become weirdly unusable on my Mac recently, and I couldn&#39;t figure out why. So I asked Codex to do a read-only audit of my computer and create a small HTML report.&lt;/p&gt;
&lt;p&gt;Turns out Cursor itself was not exactly the problem.&lt;/p&gt;
&lt;p&gt;Cursor was launching an old Telegram MCP/plugin process from my &lt;code&gt;~/.claude&lt;/code&gt; folder, and that orphaned &lt;code&gt;bun server.ts&lt;/code&gt; process was eating a lot of CPU in the background.&lt;/p&gt;
&lt;p&gt;The funny part is, I don&#39;t even use that Claude setup anymore.&lt;/p&gt;
&lt;p&gt;So I deleted &lt;code&gt;~/.claude&lt;/code&gt;, cleared Trash, and still the process kept running. That was the interesting bit: deleting files does not stop an already running process.&lt;/p&gt;
&lt;p&gt;Codex then traced the exact PID, stopped only that orphan process, verified it didn&#39;t come back, and updated the report with what happened.&lt;/p&gt;
&lt;p&gt;Now &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2059117412239475024&quot;&gt;Cursor is normal again&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The main lesson for me: agent config is not harmless. Old MCP/plugin setup can keep affecting other tools long after you forgot it exists.&lt;/p&gt;
&lt;p&gt;Also, I still don&#39;t fully understand why Cursor was launching something from my old Claude folder in the first place. But this is exactly why stale agent config feels like technical debt now.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Cursor&#39;s Composer 2.5 is awesome</title>
    <link href="https://deepakness.com/raw/using-composer-2-5/" />
    <updated>2026-05-22T20:16:44Z</updated>
    <id>https://deepakness.com/raw/using-composer-2-5/</id>
    <summary>Using Cursor after 5+ months, and this time the Composer 2.5 model does make the difference.</summary>
    <content type="html">&lt;p&gt;I last used Cursor in December last year, and after hearing great things about the new Composer 2.5 model, I decided to give it another try after 5+ months. While my experience is mostly positive, I will be writing about things I liked as well as things I didn&#39;t like.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What I liked:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Composer 2.5 model is fast, even when using without the &lt;code&gt;fast&lt;/code&gt; mode. Most of the things I work on, just take seconds and sometimes a few minutes, making it faster than Codex or Claude models I have used in the past.&lt;/li&gt;
&lt;li&gt;The 2.5 model is cheap, cheaper than all its competitors, actually. I used ~100 million tokens in a day and that resulted in only ~7% usage of the monthly limit, as you see in the screenshot here. I have &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2057819438158893452&quot;&gt;posted on X about it&lt;/a&gt; in detail.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;Cursor usage for the Composer 2.5 model&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/using-composer-2-5/cursor-usage.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;For your information, I am subscribed to the Cursor Pro plan which costs $20/month. And they&#39;re currently running a 2x offer for the week, but I think it&#39;s still a great value for money even after the offer ends. When I last used Cursor, the $20 plan was basically nothing when using any decent model. But that&#39;s not the case anymore, Composer 2.5 is a great model and that makes Cursor a great subscription plan right now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What I didn&#39;t like:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&#39;m using a MacBook Air M2 with 16 GB of RAM and the Cursor app is just consuming too much resources, so much that the laptop is constantly running hot. I have heavily used Codex or Claude Code app but never had this issue earlier, so it&#39;s clear that they need to optimize the app for performance.&lt;/p&gt;
&lt;p&gt;This was so serious that I ditched the app, and currently using the Cursor CLI only. It&#39;s great, I am loving it, and have even created a &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2057803723292967309&quot;&gt;custom /statusline&lt;/a&gt; for myself.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My advice for others:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you&#39;re confused about whether you should subscribe to Cursor, I would strongly suggest giving it a try. The Composer 2.5 model is amazing and can do most of your work.&lt;/p&gt;
&lt;p&gt;As per calculations from my usage, if you&#39;re using 50 million tokens per day by using the Composer 2.5 model, the $20 plan will last for ~24 days before you exhaust your monthly limit. And this is great for people working on one or two projects simultaneously.&lt;/p&gt;
&lt;p&gt;And if you can get the $60/mo plan, it&#39;s even better.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>My experience with Antigravity 2.0 (it&#39;s bad!)</title>
    <link href="https://deepakness.com/raw/antigravity-2-0/" />
    <updated>2026-05-20T02:35:30Z</updated>
    <id>https://deepakness.com/raw/antigravity-2-0/</id>
    <summary>Testing the just-released Antigravity 2.0 with the new Gemini 3.5 Flash mode, and it&#39;s mostly bad experience.</summary>
    <content type="html">&lt;p&gt;Google &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://io.google/2026/&quot;&gt;I/O 2026 happened&lt;/a&gt; and Google announced a bunch of interesting things in the event. One thing I was particularly interested in was the &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://antigravity.google&quot;&gt;new Antigravity 2.0&lt;/a&gt;, as I loved using the tool and coded the first versions of &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://sharepdf.app&quot;&gt;SharePDF&lt;/a&gt; by using this only in December-January this year.&lt;/p&gt;
&lt;p&gt;But the new IDE didn&#39;t live up to my expectations, and it&#39;s bad!&lt;/p&gt;
&lt;p&gt;So... let&#39;s look at &lt;strong&gt;everything bad&lt;/strong&gt; one-by-one for the new Antigravity app:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Couldn&#39;t log in for hours&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As soon as they announced Antigravity in the event, it was available for download. I updated the existing Antigravity app, and it got logged out when the new app opened. I tried logging in multiple times, but I kept seeing auth errors.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Antigravity auth is not working&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/antigravity-2-0/auth-not-working.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I kept seeing the above screen no matter how many times I tried. After an hour or so, the authentication successfully worked but when I quit and reopened the app, it started having the same issues again.&lt;/p&gt;
&lt;p&gt;But it finally worked when I used it after several hours.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Keep asking for approvals&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I have set Auto Execution and Review Policy options to &quot;Always Proceed&quot; as you see in the screenshot below, but it keeps asking for approvals each time.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Auto Execution and Review Policy set to Always Proceed&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/antigravity-2-0/always-proceed-bugs.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;And this is just an example, I had to approve at least 20 times for a simple HTML page I asked it to create. I have given &quot;Full Access&quot; to it, but this is still happening.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At least this wasn&#39;t happening on the Antigravity 1.0, right?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;3. Creates lots of unwanted HTML files&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I asked it to create a personal website for me by taking the required data from my existing website, but to be precise this was the exact prompt:&lt;/p&gt;
&lt;pre class=&quot;language-markdown&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;Create a clean and minimal personal website for me.
Take whatever info you need from my existing website: deepakness.com&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;Antigravity created multiple temporary HTML files&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/antigravity-2-0/temp-html-files.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;And while it created the website using HTML, CSS, and JavaScript, it also created a bunch of temporary HTML files in the folder. I confronted, then it said that those can be safely deleted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. No plan mode anymore&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I don&#39;t see the plan mode anywhere in the IDE, the dropdown we had earlier for planning/fast modes, no longer appears to be there.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Creates SPA all the time&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When you don&#39;t mention the tech-stack, it always creates websites as SPA (single page applications). For the personal website sample project I created earlier:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;All views (#home, #projects, #about, #newsletter) live in a single &lt;code&gt;index.html&lt;/code&gt; and are toggled via JavaScript (&lt;code&gt;navigateTo()&lt;/code&gt; in &lt;code&gt;app.js&lt;/code&gt;) without full page reloads. It uses hash-based routing (#home, #projects, etc.) and content is dynamically shown/hidden client-side.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I tried the same prompt (from #3 above) at least 5 times, it created SPAs every time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. Has a bad design taste&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I thought that the new model will have a great design capabilities, but it does not! It&#39;s still all purple, as you see in screenshots here.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Sample personal website&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/antigravity-2-0/personal-website-sample.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Another sample personal website page&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/antigravity-2-0/another-sample-design.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I blame the Antigravity harness here, because designs are slightly better when I used the same prompt in the Google AI Studio.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7. Antigravity CLI also has bugs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To be honest, the Antigravity CLI is far better than the previous Gemini CLI and it&#39;s better than the Antigravity app as well. But it &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2056819307288613009&quot;&gt;also has some bugs&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the prompt input field sometimes disappear&lt;/li&gt;
&lt;li&gt;the scroll doesn&#39;t work at all sometimes&lt;/li&gt;
&lt;li&gt;keeps asking for approvals, even after setting everything as &quot;Always Proceed&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;8. Other people sharing their experiences&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here are some posts by other people who have shared about Antigravity, that I found while browsing the internet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Robin created &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/robinebers/status/2056928512364400805&quot;&gt;a quick video on X&lt;/a&gt; sharing how bad his experience was.&lt;/li&gt;
&lt;li&gt;The new 3.5 Flash model is very costly as well, as &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/buildwithhassan/status/2056937585604280769&quot;&gt;shared by someone&lt;/a&gt; on X.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, here are some &lt;strong&gt;things I liked&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I liked the multi-folder options for projects, as I can give access to multiple folders without giving access to the entire computer.&lt;/li&gt;
&lt;li&gt;Usage limits for the new models are slightly higher than earlier on the AI Pro plan, and I think they have also added &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2056920991293755520&quot;&gt;1,000 extra AI credits&lt;/a&gt; for everyone.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&#39;s it.&lt;/p&gt;
&lt;p&gt;I will keep updating this page as I discover more things I like or dislike.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>AI Search Optimization Skill as per Google&#39;s guidelines</title>
    <link href="https://deepakness.com/raw/ai-search-optimization-skill/" />
    <updated>2026-05-16T18:55:36Z</updated>
    <id>https://deepakness.com/raw/ai-search-optimization-skill/</id>
    <summary>Google recently released a guide to optimize your website for Google&#39;s generative AI features, so I created an AI skill for it.</summary>
    <content type="html">&lt;p&gt;Recently, Google published a detailed guide on &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://developers.google.com/search/docs/fundamentals/ai-optimization-guide&quot;&gt;optimizing your website&lt;/a&gt; for generative AI features on Google Search, including a lot of interesting information. I came across this from &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/gaganghotra_/status/2055313793274802428&quot;&gt;this post on X from Gagan Ghotra&lt;/a&gt;, and created a powerful skill by consulting Gagan.&lt;/p&gt;
&lt;p&gt;I &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/deepakness/google-ai-search-optimization&quot;&gt;published the skill in this public GitHub repo&lt;/a&gt;, and it can be accessed, installed, and used by anyone by following the provided instructions. And also &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://rumble.com/v79y054-guide-to-install-googles-generative-ai-features-skills-for-ai-agents.html&quot;&gt;created this quick video for beginners&lt;/a&gt; where I&#39;m showing how to set up and use the skill (the &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2055707992897753597&quot;&gt;same video on X&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Over the next few days, I will also be using the skills on different personal projects and will keep improving as per my experience with it. But since the GitHub repo is public, other people are also welcome to contribute.&lt;/p&gt;
&lt;p&gt;And not to mention, the skill can be used with almost any AI agent/harness we have out there.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Freeing 100+ GB of storage on macOS using Codex</title>
    <link href="https://deepakness.com/raw/codex-macos-cleaning/" />
    <updated>2026-05-16T13:02:31Z</updated>
    <id>https://deepakness.com/raw/codex-macos-cleaning/</id>
    <summary>Freeing more than 100 GB or reclaimable storage on my Macbook Air using Codex.</summary>
    <content type="html">&lt;p&gt;I still use the MacBook Air M2 with 16 GB of RAM and only 256 GB of storage, and it was working perfectly fine for my use case until recently. I started getting the low storage warnings sometimes, and that annoyed me a lot. And I was about to factory reset my laptop... but then at the last moment, I &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2055552888823562724&quot;&gt;decided to ask Codex&lt;/a&gt; about it, and glad that I did.&lt;/p&gt;
&lt;p&gt;Codex helped me free more than 100 GB of storage by deleting unnecessary stuff that were there from some apps that I used and deleted earlier. For example, I once tried a local model via Hugging Face and LM Studio and they were together taking 35 GB of storage. Similarly, I tried a Docker alternative called Colima and it was taking another 19 GB, as you see in the screenshot here.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Storage taken by unnecessary stuff on MacBook Air&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/codex-macos-cleaning/unused-apps-storage.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;It also gave me suggestion to remove folders from the &lt;code&gt;~Library/Application Support/*&lt;/code&gt; from apps which were not used or not installed on my system anymore. From here, you can see that I try a lot of applications like browsers and so on.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Library &gt; Application Data on macOS&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/codex-macos-cleaning/library-application-data.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;The screenshots you see above, is from an HTML file that I asked Codex to create after analyzing my laptop in detail. And it created a complete checklist with all the information that I can do to optimize my laptop. It did a great job.&lt;/p&gt;
&lt;p&gt;Now, the funny thing is I earlier &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/tw93/mole&quot;&gt;used Mole&lt;/a&gt; and even subscribed to the CleanMyMac app and there also weren&#39;t able to free these unnecessarily occupied storage. I tried them a few times, and they only cleared a maximum of 5-10 GB storage.&lt;/p&gt;
&lt;p&gt;Another funny thing is, I have used Linux for years in the past and I know about the file systems a bit. But I have become lazy ever since I started using macOS (I love my MacBook though) and didn&#39;t even bother to check those folders. But after Codex gave suggestions, I went and deleted unnecessary folders and files by myself, and cleared over 100 GB of storage.&lt;/p&gt;
&lt;p&gt;Life&#39;s good now!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>SharePDF now has 200 users</title>
    <link href="https://deepakness.com/raw/sharepdf-200-users/" />
    <updated>2026-05-12T17:37:28Z</updated>
    <id>https://deepakness.com/raw/sharepdf-200-users/</id>
    <summary>The simple PDF sharing app I created now has 200 users, and it&#39;s been an amazing feeling so far.</summary>
    <content type="html">&lt;p&gt;I started working on SharePDF in January 2026, and it&#39;s been an amazing journey. It took ~4 months to reach &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://sharepdf.app/blog/sharepdf-now-has-100-users&quot;&gt;100 users&lt;/a&gt;, and now we&#39;re &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://sharepdf.app/blog/sharepdf-200-users&quot;&gt;looking at 200 users&lt;/a&gt; in just 20 days after that.&lt;/p&gt;
&lt;p&gt;Crazy, right? At least for me.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;SharePDF now has 200 users&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/sharepdf-200-users/200-users.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;And in the last few weeks, I have also added enhanced existing stuff and have also added a few more features to the app. Some improvements done were:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Added a way to replace PDFs while keeping the same old share link&lt;/li&gt;
&lt;li&gt;Introduced collections, a way to better manage lots of PDFs for power users&lt;/li&gt;
&lt;li&gt;Improved analytics, so now users can see more data points, including per PDF analytics as well&lt;/li&gt;
&lt;li&gt;Improved custom domain, billing, support, uploads, reliability, etc.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And still working to make everything even better for users.&lt;/p&gt;
&lt;p&gt;Also, wrote a new blog post listing all the &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://sharepdf.app/blog/sharepdf-features&quot;&gt;cool features SharePDF now has&lt;/a&gt;. I have tried to include everything here, and will probably keep this updated as well.&lt;/p&gt;
&lt;p&gt;Apart from this, I am also &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://www.producthunt.com/products/sharepdf?launch=sharepdf&quot;&gt;launching SharePDF on Product Hunt&lt;/a&gt; tomorrow, i.e., May 13th at 12:30 IST. And I request your support for the launch, if you&#39;re reading this.&lt;/p&gt;
&lt;p&gt;Thank you!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Run NVIDIA Kimi K2.6 and others in OpenCode</title>
    <link href="https://deepakness.com/raw/nvidia-models-via-opencode/" />
    <updated>2026-05-10T07:41:09Z</updated>
    <id>https://deepakness.com/raw/nvidia-models-via-opencode/</id>
    <summary>A simple step-by-step guide to configure NVIDIA&#39;s AI models in OpenCode, set it as the default model, and verify it from the CLI.</summary>
    <content type="html">&lt;p&gt;I wanted to use &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://build.nvidia.com/moonshotai/kimi-k2.6&quot;&gt;Kimi K2.6 from NVIDIA&lt;/a&gt; inside OpenCode, and it was simpler than I first thought. This and a bunch of other open-source models are free to try in NVIDIA, by the way.&lt;/p&gt;
&lt;p&gt;I only had to add the API key, model details, and the correct base URL in the OpenCode config.&lt;/p&gt;
&lt;p&gt;I wanted to try Kimi K2.6 but you can try other models as well. For Kimi, NVIDIA&#39;s model name is:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;moonshotai/kimi-k2.6&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But inside OpenCode, I had use it like below&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;nvidia/moonshotai/kimi-k2.6&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I edited this file on my macOS device:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;~/.config/opencode/opencode.jsonc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And added this config:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://opencode.ai/config.json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nvidia/moonshotai/kimi-k2.6&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;provider&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;nvidia&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;npm&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@ai-sdk/openai-compatible&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NVIDIA&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;api&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://integrate.api.nvidia.com/v1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;options&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;baseURL&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://integrate.api.nvidia.com/v1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;apiKey&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;YOUR_NVIDIA_API_KEY_HERE&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;timeout&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;600000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;chunkTimeout&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;extraBody&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;chat_template_kwargs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;thinking&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;models&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;moonshotai/kimi-k2.6&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Kimi K2.6&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;reasoning&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;tool_call&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;temperature&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;attachment&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;interleaved&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;field&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;reasoning_content&quot;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;modalities&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;input&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;video&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;output&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;limit&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;context&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;262144&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;output&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;65536&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;options&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;chat_template_kwargs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;token property&quot;&gt;&quot;thinking&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The important bit is this URL:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;https://integrate.api.nvidia.com/v1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;NVIDIA&#39;s example uses the full &lt;code&gt;/chat/completions&lt;/code&gt; URL, but OpenCode only needs the base URL. It adds &lt;code&gt;/chat/completions&lt;/code&gt; by itself.&lt;/p&gt;
&lt;p&gt;Works as expected, so that&#39;s it.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Laravel installer getting killed after update</title>
    <link href="https://deepakness.com/raw/laravel-herd-lite-fix/" />
    <updated>2026-05-06T16:50:15Z</updated>
    <id>https://deepakness.com/raw/laravel-herd-lite-fix/</id>
    <summary>A short note on fixing Laravel installer commands getting killed on macOS after updating Herd Lite / php.new.</summary>
    <content type="html">&lt;p&gt;I ran into this after updating Laravel / Herd Lite using the &lt;code&gt;php.new&lt;/code&gt; installer. The update itself looked successful, but when I tried creating a new Laravel project, the command was immediately killed by macOS.&lt;/p&gt;
&lt;p&gt;Initially, it looked like a Laravel installer issue because I also saw a PHP parse error from inside the Laravel installer PHAR. But the actual issue was lower-level: the bundled PHP binary was getting blocked/killed when running from Herd Lite&#39;s installed bin directory.&lt;/p&gt;
&lt;p&gt;The fix was to download fresh PHP, Composer, and Laravel installer binaries and place them in a clean local bin directory. Then I updated my shell &lt;code&gt;PATH&lt;/code&gt; so this clean directory is used before the problematic Herd Lite bin path.&lt;/p&gt;
&lt;p&gt;In short:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;PATH&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token environment constant&quot;&gt;$HOME&lt;/span&gt;/.local/herd-lite-bin:&lt;span class=&quot;token environment constant&quot;&gt;$PATH&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After reloading the terminal, &lt;code&gt;php&lt;/code&gt;, &lt;code&gt;composer&lt;/code&gt;, and &lt;code&gt;laravel&lt;/code&gt; resolved to the working binaries, and &lt;code&gt;laravel new&lt;/code&gt; started working again.&lt;/p&gt;
&lt;p&gt;So if Laravel commands suddenly start saying &lt;code&gt;zsh: killed&lt;/code&gt; after a Herd Lite / php.new update, check where your &lt;code&gt;php&lt;/code&gt; and &lt;code&gt;laravel&lt;/code&gt; binaries are coming from first.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>From free tools to full SaaS</title>
    <link href="https://deepakness.com/raw/free-tools-to-saas/" />
    <updated>2026-05-06T01:10:16Z</updated>
    <id>https://deepakness.com/raw/free-tools-to-saas/</id>
    <summary>A quick thought on how to build SaaS in the age of AI, that I think still works.</summary>
    <content type="html">&lt;p&gt;I created a free tool a few months ago, and now it&#39;s getting 10-15 clicks every day from Google, as you see in the screenshot here. So... I researched a bit and realized that there is a solid SaaS opportunity on the site, I can have the main tool free but then can also build some paid features in the web app.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Google Search Console screenshot of a free tool getting traffic&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/free-tools-to-saas/gsc-1.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;And not just this, take a look at another free tool I created before ChatGPT was launched, and it&#39;s still getting lots of traffic from Google and other referrers. Take a look at the screenshot here:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;GSC for another free app getting traffic from Google&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/free-tools-to-saas/gsc-2.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;This one is getting 80-140 clicks a day consistently for years now, and I haven&#39;t done anything with it yet, but not anymore. I am working on it to bring some paid offerings in the app, currently, in the brainstorming phase. For research, I am analyzing other similar apps and also going through the data from Google Search Console, and it&#39;s been very helpful so far.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you&#39;re wondering, I am not going to tell you what the app is about just yet because it&#39;s very simple, and the idea can be copied with just a prompt. But yes, I will eventually share more about these.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Honestly, &quot;distribution&quot; has always been important, but it has become even more important in the age of AI because &quot;code&quot; is not the moat anymore. In my case, I already have thousands of visitors coming to the tool and if I create the paid version, I will instantly have lots of potential customers.&lt;/p&gt;
&lt;p&gt;Also, the concept of &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/blog/engineering-as-marketing/&quot;&gt;engineering as marketing&lt;/a&gt; is the most rewarding than ever in the current time, because creating free tools around your main product is simpler and faster than ever. If you want to experiment something with the lowest effort, just ask any LLM to give you ideas for free tools around you main product, create one, publish it in a subdomain, and forget it for a few weeks. If you see a positive traction, create the tool on the main domain, and do a redirect from the subdomain.&lt;/p&gt;
&lt;p&gt;I think, this is the best use-case of AI for marketing.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Save a clipboard image to computer on macOS</title>
    <link href="https://deepakness.com/raw/save-clipboard-image-macos/" />
    <updated>2026-05-01T16:25:54Z</updated>
    <id>https://deepakness.com/raw/save-clipboard-image-macos/</id>
    <summary>Just find out this trick to save clipboard images to your computer when you&#39;re on macOS.</summary>
    <content type="html">&lt;p&gt;I take a lot of screenshots and most of the time keep them in my clipboard and then paste wherever needed, like on socials or in AI coding tools when working. But sometimes, I also need to save those images locally on my computer, and till now I have been doing one of these two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Either take the screenshot once again, or&lt;/li&gt;
&lt;li&gt;Paste images somewhere like on Imgur, and then save by using &amp;quot;save image as&amp;quot; feature&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Silly, but yes.&lt;/p&gt;
&lt;p&gt;However, I recently found out a trick that works like a charm, at least on macOS. The process is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open the Preview app, you can do so by searching for Preview via Spotlight search&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;cmd + n&lt;/code&gt; and you should already see the image from your clipboard&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now, just save it using &lt;code&gt;cmd + s&lt;/code&gt; or however you want to, as you see in the screenshot here.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Save clipboard image on computer in macOS&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/save-clipboard-image-macos/save-clipboard-image.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;It works as expected and even gives you image format you want to save your screenshots as.&lt;/p&gt;
&lt;p&gt;TIL.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>DeepSeek v4 Pro should be taken seriously</title>
    <link href="https://deepakness.com/raw/deepseek-v4-pro/" />
    <updated>2026-04-30T17:01:42Z</updated>
    <id>https://deepakness.com/raw/deepseek-v4-pro/</id>
    <summary>I loved the new DeepSeek v4 Pro model so much that I think I won&#39;t be renewing my Codex subscription.</summary>
    <content type="html">&lt;p&gt;For the last 2 days, I have been using the DeepSeek v4 Pro model via &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://opencode.ai/go&quot;&gt;OpenCode Go&lt;/a&gt; and it has been a fantastic experience. I never expected the model to be this good at UI as well as logic.&lt;/p&gt;
&lt;p&gt;For example, I am creating &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2049892556079788256&quot;&gt;a custom blog publishing CMS&lt;/a&gt; powered entirely by Cloudflare (D1, R2, and Workers). Initially, I used Codex for this and Codex did ready the first working version, but the UI was very bad and cluttered and the user-experience wasn&#39;t great either. I didn&#39;t even like the CMS a bit.&lt;/p&gt;
&lt;p&gt;But then I fired up OpenCode and gave everything to the DeepSeek v4 Pro model, and asked it to re-do and re-design everything by keeping user-experience in mind. I, then, went to the gym and the model had done its magic by the time I returned. It ran for ~35 mins and completed everything in one go, and the design was already looking much cleaner and just better.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Design created by DeepSeek v4 Pro&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/deepseek-v4-pro/design-by-deepseek-v4-pro.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I still had to give a few more prompts to refine some things, and it did everything perfectly. Just for your information, while working, I kept the thinking effort as default, as you see in the screenshot.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;DeepSeek v4 Pro thinking effort as Default&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/deepseek-v4-pro/thinking-effort.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;From the next month, I think I am going to &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/raw/50-dollar-ai/&quot;&gt;save decent amount of money&lt;/a&gt; on AI tools subscriptions. Currently, I am subscribed to Codex $100 plan but now I think Codex $20 with OpenCode $10 (+ $10-20 for extra usage) should be enough for my use case.&lt;/p&gt;
&lt;p&gt;Lastly, I think the DeepSeek v4 models should be taken more seriously by everyone. Their &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://api-docs.deepseek.com/quick_start/pricing&quot;&gt;API pricing&lt;/a&gt; is also currently discounted by 75%, and there is absolutely no reason to not use this model.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Introducing EternalQR – a dynamic QR code tool</title>
    <link href="https://deepakness.com/raw/eternalqr-intro/" />
    <updated>2026-04-28T03:24:11Z</updated>
    <id>https://deepakness.com/raw/eternalqr-intro/</id>
    <summary>Introducing EternalQR, a dynamic QR code tool with editable links, scan analytics, and simple pricing.</summary>
    <content type="html">&lt;p&gt;Introducing &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://eternalqr.app&quot;&gt;EternalQR&lt;/a&gt; – a small web-app to create dynamic QR codes, update their links later, track scans, customize them, and download them as PNG or SVG files.&lt;/p&gt;
&lt;p&gt;I got the idea for this from something that happened to my brother.&lt;/p&gt;
&lt;p&gt;He had created a video on YouTube and added a QR code to it using some free QR code tool he found online. Initially, the QR code was working correctly. But later, when the video started getting lots of views, the QR code stopped working.&lt;/p&gt;
&lt;p&gt;And because the QR code was already inside the video, there was no way to update or replace it.&lt;/p&gt;
&lt;p&gt;That made me think that QR codes are a bit different from normal links. A link on a website can be changed anytime. But a QR code often ends up in places that are hard to edit later – YouTube videos, restaurant menus, business cards, flyers, packaging, event signs, invoices, stickers, and so on.&lt;/p&gt;
&lt;p&gt;So I created &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://eternalqr.app&quot;&gt;EternalQR&lt;/a&gt; around one simple idea: if a QR code is already created and used somewhere, normal plan changes should not turn it into a dead link.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating new QR code in EternalQR app&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/eternalqr-intro/create-new-qr-code.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Some things it supports right now:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dynamic QR codes with editable destinations&lt;/li&gt;
&lt;li&gt;scan analytics with country, device, browser, referrer, and time&lt;/li&gt;
&lt;li&gt;QR codes for websites, contact cards, Wi-Fi, SMS, email, phone, and plain text&lt;/li&gt;
&lt;li&gt;logo and color customization&lt;/li&gt;
&lt;li&gt;PNG and SVG downloads&lt;/li&gt;
&lt;li&gt;pause, expiry dates, tags, and basic dashboard management&lt;/li&gt;
&lt;li&gt;existing QR codes keep redirecting through normal plan changes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2048801107334627425&quot;&gt;app is built on&lt;/a&gt; Cloudflare Workers, D1, and KV, so redirects are very cheap to serve. Paid plans are mainly for things like more QR codes, longer analytics history, customization, and other features.&lt;/p&gt;
&lt;p&gt;The pricing is also kept simple:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Free – 5 QR codes&lt;/li&gt;
&lt;li&gt;Starter – $5/mo for 50 QR codes&lt;/li&gt;
&lt;li&gt;Pro – $19/mo for unlimited QR codes&lt;/li&gt;
&lt;li&gt;Lifetime – $89 once for Starter features&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Not to mention, but all these plans come with unlimited scans.&lt;/p&gt;
&lt;p&gt;Here&#39;s how an already created QR code page looks, with scan analytics and more.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scan analytics for QR codes at EternalQR&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/eternalqr-intro/scan-analytics.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;It&#39;s not a huge ambitious product, but just a practical tool for a problem I saw happen in real life.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Compact Tabs are back in the Safari browser</title>
    <link href="https://deepakness.com/raw/safari-compact-tabs-in-26-4-1/" />
    <updated>2026-04-26T20:42:27Z</updated>
    <id>https://deepakness.com/raw/safari-compact-tabs-in-26-4-1/</id>
    <summary>Apple brought back the Compact Tabs feature in the Safari browser in the latest macOS Tahoe 26.4.1 update.</summary>
    <content type="html">&lt;p&gt;I love using the Safari web browser on my MacBook, especially when I&#39;m traveling because it consumes less battery on the laptop. But with the macOS Tahoe 26 update, the Compact tabs feature was removed from the browser, and I was sad about it.&lt;/p&gt;
&lt;p&gt;And I&#39;m just learning that with the new macOS Tahoe 26.4.1 update, the compact tabs feature is back in the Safari browser, as you see in the screenshot here.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Compact tabs feature in the Safari browser. &quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/safari-compact-tabs-in-26-4-1/compact-tabs-safari.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;It&#39;s good already, but I think it behaves a bit differently than it did in the macOS Sequoia or Sonoma, when it was still available. But it&#39;s still good, and I&#39;m using it for a day and love it.&lt;/p&gt;
&lt;p&gt;Thank you, Apple.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How to best spend $50 on AI coding tools</title>
    <link href="https://deepakness.com/raw/50-dollar-ai/" />
    <updated>2026-04-24T16:24:36Z</updated>
    <id>https://deepakness.com/raw/50-dollar-ai/</id>
    <summary>If you have $50 to spend each month on AI coding tools, go with Claude Pro, Codex Plus, and OpenCode Go.</summary>
    <content type="html">&lt;p&gt;I have been spending over $100 every month on Claude Max and Codex Pro plans as I use the latest models from these providers for coding, but now I don&#39;t think that&#39;s the best way to do it anymore.&lt;/p&gt;
&lt;p&gt;The current best option I think is, instead of getting higher plan for any one AI tool, get smaller plans for multiple providers. And the best combo I can think of is the following.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Claude Pro – $20/mo&lt;/li&gt;
&lt;li&gt;Codex Plus – $20/mo&lt;/li&gt;
&lt;li&gt;OpenCode Go – $10/mo&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Getting all these will only cost $50, but this is more than enough for my requirements. Here I will save money and also have access to top models from multiple providers. The different models can be used for different tasks that they&#39;re actually good at, for example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;for all design and UI related work – use the latest Claude models&lt;/li&gt;
&lt;li&gt;for complex logic and programming – use the latest Codex models&lt;/li&gt;
&lt;li&gt;for smaller tasks and everything else – use Kimi, GLM, or Qwen models via OpenCode&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And not just me but several &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DanKulkov/status/2047701466408976525&quot;&gt;other people&lt;/a&gt; are also starting to realize this.&lt;/p&gt;
&lt;p&gt;Currently, I am subscribed to Codex $100 plan that ends next month, and also to OpenCode Go plan. But I&#39;m going to downgrade Codex to $20 plan and then also subscribe to Claude $20 plan and keep my OpenCode Go for $10.&lt;/p&gt;
&lt;p&gt;That should be more than enough for three &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/projects/&quot;&gt;full-time projects&lt;/a&gt; I am currently working on.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>My experience with the new GPT-5.5 model</title>
    <link href="https://deepakness.com/raw/gpt-5-5-experience/" />
    <updated>2026-04-24T08:41:29Z</updated>
    <id>https://deepakness.com/raw/gpt-5-5-experience/</id>
    <summary>Yesterday, OpenAI launched its new GPT-5.5 model and I am documenting my experiences in this post.</summary>
    <content type="html">&lt;p&gt;Yesterday, OpenAI launched the newest &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://openai.com/index/introducing-gpt-5-5/&quot;&gt;model GPT-5.5&lt;/a&gt; which I was too excited about for the last few days. And here are my experiences so far with using the new model inside the Codex app.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GPT-5.5 is far &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2047393668324331616&quot;&gt;better in frontend design&lt;/a&gt; than other OpenAI models like GPT-5.4 or 5.3-Codex. But it&#39;s still not at the level of Opus 4.7 of 4.6 when it comes to UI design.&lt;/li&gt;
&lt;li&gt;Even though it was claimed by Sam Altman that the new model &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/sama/status/2047378254575685707&quot;&gt;uses fewer tokens per task&lt;/a&gt; than previous models, it&#39;s not the case when I use it. In my case, it used way more tokens than GPT-5.4 because earlier I could never finish the 5-hour limit on the $100 plan, but today I did, as you see below.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;GPT-5.5 token usage&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/gpt-5-5-experience/gpt-5-5-token-usage.png&quot;&gt;&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;The new model, GPT-5.5, definitely feels slightly faster than the previous, GPT-5.4, model in the standard mode. I think, both are equally faster in the speed/fast mode.&lt;/li&gt;
&lt;li&gt;I didn&#39;t notice any significant improvement in the programming though with the GPT-5.5 model, it feels similarly capable as GPT-5.4 model. Or, maybe I haven&#39;t tested this enough yet.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Also, the new Codex app feels snappier and the UI and UX is slightly improved now.&lt;/p&gt;
&lt;p&gt;Apart from this, I can still not rely completely on the Codex subscription itself. I can &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2047184706412953894&quot;&gt;use OpenCode&lt;/a&gt; with models like GLM-5.1 and Kimi-K2.6 for frontend design and then GPT-5.5 for everything else. The OpenCode Go plan is very generous at $10/mo and has crazy limits as well. So if I had to reduce my monthly spending, I would go with OpenCode Go ($10/mo) + ChatGPT Plus ($20/mo) and maybe $20-30 extra on OpenCode, and that should cover all my requirements.&lt;/p&gt;
&lt;p&gt;I&#39;m still playing with the GPT-5.5 model so if I find something new worth sharing, I will keep this post updated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Apr 25, 2026&lt;/p&gt;
&lt;p&gt;I &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2047640208347447332&quot;&gt;posted about limits draining too fast on X&lt;/a&gt; and many people recommended that I should rarely use Extra High effort for my tasks, and suggested using either Medium or High for most tasks. So... I gave the &quot;High&quot; effort a try, and it&#39;s good, I am satisfied with it so far.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>SharePDF reaches 100 users</title>
    <link href="https://deepakness.com/raw/sharepdf-100-users/" />
    <updated>2026-04-23T06:43:06Z</updated>
    <id>https://deepakness.com/raw/sharepdf-100-users/</id>
    <summary>Probably my first proper SaaS product has now reached 100 users and I am so happy for it.</summary>
    <content type="html">&lt;p&gt;The app to share PDFs, &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://sharepdf.app&quot;&gt;SharePDF.app&lt;/a&gt;, that I created early this year has now reached the milestone of &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://sharepdf.app/blog/sharepdf-now-has-100-users&quot;&gt;100 users&lt;/a&gt; and I&#39;m so happy for it. It took around 4 months to reach this milestone and I don&#39;t know what, but it makes me super happy.&lt;/p&gt;
&lt;p&gt;I have been documenting most of the things &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/sharepdf/&quot;&gt;on this page&lt;/a&gt; and reading previous logs takes me through the journey of things I did in the past few months – how I finalized which tech-stack to use, how I decided different features the app has, and more.&lt;/p&gt;
&lt;p&gt;SharePDF is running stable and I don&#39;t need to do much on it now. But I still have 1-2 features or rather enhancements planned for near future. Also, I will be working on improving the landing pages as well, and maybe even create a few new ones targeting keywords that get searched a lot.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Codex is smarter than Claude Code</title>
    <link href="https://deepakness.com/raw/codex-is-smarter-than-claude/" />
    <updated>2026-04-21T07:07:11Z</updated>
    <id>https://deepakness.com/raw/codex-is-smarter-than-claude/</id>
    <summary>After seriously using Codex for a few days, it definitely seems smarter than Claude Code. It&#39;s just bad at design.</summary>
    <content type="html">&lt;p&gt;After seriously using Codex for a few days, it definitely seems smarter than Claude Code. But Codex is just awful at design. I have tried to make good designs using Codex multiple times, and it just doesn&#39;t work. In fact, I tried creating a few new pages for my Vemgram project that I am mainly working on these days, and even though the site has a design system set up, Codex is still unable to create designs that matches the aesthetics of the rest of the website.&lt;/p&gt;
&lt;p&gt;I am very much disappointed for that.&lt;/p&gt;
&lt;p&gt;For this reason, nowadays, I have started using &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://opencode.ai/&quot;&gt;OpenCode&lt;/a&gt; whenever I need to design something. I love the newest launched models like Kimi K2.5, Qwen 3.6 Plus, and GLM-5.1 models inside OpenCode. These open-source models are almost as good as Opus 4.6/4.7 when it comes to design.&lt;/p&gt;
&lt;p&gt;Apart from this, I am hearing rumors that OpenAI is about to launch GPT-5.5 and also that it&#39;s great at design. If that&#39;s the case, I won&#39;t regret subscribing to Codex Pro at all.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>After Claude, now Codex can&#39;t keep up with the demand</title>
    <link href="https://deepakness.com/raw/codex-cant-keep-up/" />
    <updated>2026-04-20T15:18:22Z</updated>
    <id>https://deepakness.com/raw/codex-cant-keep-up/</id>
    <summary>I wonder if they can&#39;t keep up with rising demands, why don&#39;t they pause Codex signups temporarily?</summary>
    <content type="html">&lt;p&gt;It&#39;s been almost an hour since OpenAI&#39;s &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://status.openai.com&quot;&gt;Codex is completely down&lt;/a&gt;, as you see in the screenshot below. I recently moved away from Claude for this reason, and now I am facing the same issues here as well.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Codex is down&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/codex-cant-keep-up/codex-down.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Codex still hasn&#39;t become as bad as Claude was a week ago and before that, but it seems like it&#39;s getting there. And it&#39;s surprising to me that if these AI companies can&#39;t keep up with the rising demands, why don&#39;t they just pause new signups temporarily? I mean, it will be better for everyone, no? – for users and then for their own brand image as well.&lt;/p&gt;
&lt;p&gt;This is not at all fair for users. They&#39;re paying the premium to just experience degraded performance all the time. For example, just take a look at &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://status.claude.com&quot;&gt;Claude&#39;s status chart&lt;/a&gt; for the last 90 days and you&#39;ll see lots of yellows and reds.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Claude status for the last 90 days&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/codex-cant-keep-up/claude-status-90.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I, myself, had been paying at least $100 each month to Claude and now to Codex, but getting the same degraded performance. Honestly, I don&#39;t blame OpenAI or Anthropic for that they can&#39;t keep up with the demand, but I blame them because why are they still allowing signups and ruining the experience for everyone? They should just pause signups for some time till they get more compute, and if required pause again for some time till they get more compute, and so on.&lt;/p&gt;
&lt;p&gt;I also run a SaaS, and I will feel very bad if I keep charging a fee to my customers and if my app is consistently down. I will even refund them and pause new signups till I get things sorted.&lt;/p&gt;
&lt;p&gt;That&#39;s it.&lt;/p&gt;
&lt;p&gt;Sorry for the rant, really.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>I like Claude Code CLI&#39;s no flicker mode</title>
    <link href="https://deepakness.com/raw/claude-no-flicker-mode/" />
    <updated>2026-04-14T12:31:19Z</updated>
    <id>https://deepakness.com/raw/claude-no-flicker-mode/</id>
    <summary>Just started using Claude Code&#39;s new no-flicker or full-screen mode and I like it better than earlier.</summary>
    <content type="html">&lt;p&gt;I just started using Claude Code&#39;s new &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://code.claude.com/docs/en/fullscreen&quot;&gt;no-flicker or full-screen mode&lt;/a&gt; for the CLI and I like it better than earlier. When enabled, it just sends the text input field at the bottom of the screen and makes it sticky. Just like how you see in the screenshot here:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Claude Code CLI no-flicker mode&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/claude-no-flicker-mode/claude-no-flicker.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I like it because it doesn&#39;t disturb me when Claude is generating a large output, then I can keep reading from the top while it outputs at the bottom, without disturbing my flow.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Mistakes were made at Google Search Console</title>
    <link href="https://deepakness.com/raw/mistakes-at-gsc/" />
    <updated>2026-04-14T12:10:00Z</updated>
    <id>https://deepakness.com/raw/mistakes-at-gsc/</id>
    <summary>Receiving emails from GSC that are normally sent when a new site is added to Google Search Console.</summary>
    <content type="html">&lt;p&gt;Today, I suddenly started receiving emails like below from Google Search Console for all my sites already added. These emails are normally sent when a new site is added to the GSC for tracking the search performance, but mistakes were made, for sure.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Repeated emails from Google Search Console&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/mistakes-at-gsc/emails-from-gsc.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I have at least 8-10 sites added to this Gmail account and I received emails for all those in a 3-5 hour span. I also &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2044010310160564235&quot;&gt;posted about this on X&lt;/a&gt; and several people confirmed that they have also received the same emails.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;GSC email detail&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/mistakes-at-gsc/gsc-email-detail.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;And if you&#39;re curious about the contents of these emails, see the screenshot above. It&#39;s the same that Google sends when you add a new site to GSC.&lt;/p&gt;
&lt;p&gt;I hope they fix it soon and do not annoy me, again.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Apr 15, 2026&lt;/p&gt;
&lt;p&gt;It was just a &quot;glitch&quot; as everyone suspected, as confirmed by John Muller from Google. Learned about this from &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/gaganghotra_/status/2044132632058048933&quot;&gt;this post on X&lt;/a&gt; by Gagan Ghotra.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Introducing SharePDF app</title>
    <link href="https://deepakness.com/raw/introducing-sharepdf/" />
    <updated>2026-04-14T04:29:42Z</updated>
    <id>https://deepakness.com/raw/introducing-sharepdf/</id>
    <summary>SharePDF is a web app to upload and share PDFs as URLs and track their analytics in an easier and better way.</summary>
    <content type="html">&lt;p&gt;Introducing &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://sharepdf.app&quot;&gt;SharePDF&lt;/a&gt; – a web-app to host PDFs, share them as URLs, track their view analytics, and do much more. It&#39;s live and working, and already has more than 80 users at the time of writing this post.&lt;/p&gt;
&lt;p&gt;I had this idea to create an app that makes sharing PDFs easier for at least 2 years, but I never worked on it. However, somehow I started working on it from January this year, i.e. 2026. I haven&#39;t done any kind of marketing as of now, and still regularly getting signups from sources I wouldn&#39;t even have guessed – Instagram and ChatGPT. Yes, someone must have created some content that people are discovering SharePDF from.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;SharePDF X intro&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/introducing-sharepdf/sharepdf-x-intro.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Today, I have also &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2043864578615062884&quot;&gt;posted on X&lt;/a&gt; for the first time about the app. Apart from this, I have also been sharing build logs &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/sharepdf/&quot;&gt;on this page&lt;/a&gt; on my website – it just helps me keep myself in the loop.&lt;/p&gt;
&lt;p&gt;Currently, I am not working on new features for the app but mainly working on improving the landing page, copy, and user experience.&lt;/p&gt;
&lt;p&gt;By the way, I also &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/raw/introducing-vemgram/&quot;&gt;launched Vemgram&lt;/a&gt;, a platform to connect Indian manufacturers with buyers, a few days ago. So, now, I have two full time projects that I am working on these days.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Better utilize Claude Code limits</title>
    <link href="https://deepakness.com/raw/better-utilize-claude-limits/" />
    <updated>2026-04-11T04:01:14Z</updated>
    <id>https://deepakness.com/raw/better-utilize-claude-limits/</id>
    <summary>A quick guide to better utilize Claude Code limits so that tokens don&#39;t go to waste.</summary>
    <content type="html">&lt;p&gt;Came across &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/hqmank/status/2042201466769903906&quot;&gt;this post on X&lt;/a&gt; that shares a hack, a way to maximum utilize your Claude Code usage limits by setting up scheduled tasks. It seems silly at first, but it&#39;s actually helpful.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Claude Code reset Cron&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/better-utilize-claude-limits/reset-cron.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;As explained in the post, I set up a cron that sends &quot;hi&quot; every 5 hours starting from 8AM IST so that as soon as the limit resets, it immediately starts a new cycle so that you have clean time blocks.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;30 2,7,12,17 * * *
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the best thing is, you don&#39;t need any extra tool to use for this.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Meta&#39;s new Muse Spark model is here</title>
    <link href="https://deepakness.com/raw/meta-muse-spark-launch/" />
    <updated>2026-04-08T17:21:02Z</updated>
    <id>https://deepakness.com/raw/meta-muse-spark-launch/</id>
    <summary>Meta just launched a new AI model called Muse Spark which is now available to use via Meta.ai app.</summary>
    <content type="html">&lt;p&gt;Meta just &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://ai.meta.com/blog/introducing-muse-spark-msl/&quot;&gt;launched a new AI model&lt;/a&gt; called Muse Spark which is now available to use via meta.ai and the Meta app. It&#39;s not available via the API, yet.&lt;/p&gt;
&lt;p&gt;As of now, it looks good on the evals as you see in the screenshot here. In categories, it&#39;s shown to be even better than Opus 4.6 and GPT-5.4.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Muse Spark model looks good on evals&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/meta-muse-spark-launch/muse-spark-evals.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I tried the model via meta.ai web interface with my Facebook login, and I must say that it has a better sense of design than GPT-5.4. For example, I just asked it to create a minimal personal website and this was the result.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Muse Spark at web design&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/meta-muse-spark-launch/design.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I am still testing this, and will keep this post updated.&lt;/p&gt;
&lt;p&gt;Also, I must say that I liked the meta.ai web interface and it feels fast and snappy. It even let me see the website in a new tab.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Milla Jovovich&#39;s mempalace is nice, but...</title>
    <link href="https://deepakness.com/raw/milla-jovovich-mempalace/" />
    <updated>2026-04-07T16:13:12Z</updated>
    <id>https://deepakness.com/raw/milla-jovovich-mempalace/</id>
    <summary>Milla Jovovich launched an open-source AI memory system that is nice, but with lots of false claims.</summary>
    <content type="html">&lt;p&gt;Milla Jovovich launched an open-source AI memory system called &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/milla-jovovich/mempalace&quot;&gt;mempalace&lt;/a&gt; with a bold claim saying &quot;highest-scoring AI memory system ever benchmarked&quot;. She first announced about this &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://www.instagram.com/reel/DWzNnqwD2Lu/&quot;&gt;on her Instagram&lt;/a&gt; and then it&#39;s &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/NetworkChuck/status/2041505133025194343&quot;&gt;picked by multiple folks&lt;/a&gt; from there.&lt;/p&gt;
&lt;p&gt;And yes, that &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Milla_Jovovich&quot;&gt;Milla Jovovich&lt;/a&gt; from movies like Resident Evil and The Fifth Element. She&#39;s an engineer and loves to code as well.&lt;/p&gt;
&lt;p&gt;But then I came across &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/milla-jovovich/mempalace/issues/27&quot;&gt;this issue on GitHub&lt;/a&gt; that highlights multiple false claims, as you see in the screenshot.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Issues with mempalace by Milla Jovovich&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/milla-jovovich-mempalace/mempalace-issues.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;As she claims in the video, it&#39;s still work in progress, and she might still be working on this, so there might be some gaps in the README vs the actual codebase. But the concept of the tool is still very good, and there is also lots of good information &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/milla-jovovich/mempalace/blob/main/README.md&quot;&gt;in the README file&lt;/a&gt; that you can explore.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Google AI Edge Gallery app is good</title>
    <link href="https://deepakness.com/raw/google-ai-edge-gallery/" />
    <updated>2026-04-07T15:40:25Z</updated>
    <id>https://deepakness.com/raw/google-ai-edge-gallery/</id>
    <summary>Google has a new AI app called AI Edge Gallery that lets people try and use different AI models locally.</summary>
    <content type="html">&lt;p&gt;Google has a new &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://play.google.com/store/apps/details?id=com.google.ai.edge.gallery&quot;&gt;app for Android&lt;/a&gt; and &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://apps.apple.com/us/app/google-ai-edge-gallery/id6749645337&quot;&gt;also for iOS&lt;/a&gt; called AI Edge Gallery that lets people explore and use local on-device LLMs. Currently, it&#39;s featuring the newly launched Gemma 4 family of models.&lt;/p&gt;
&lt;p&gt;This is written in their app description on app stores:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;AI Edge Gallery is the premier destination for running the world&#39;s most powerful open-source Large Language Models (LLMs) on your mobile device. Experience high-performance Generative AI directly on your hardware—fully offline, private, and lightning-fast.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And to my surprise, the &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/google-ai-edge/gallery&quot;&gt;app itself is open-source&lt;/a&gt;. I love whatever is Google&#39;s game here.&lt;/p&gt;
&lt;p&gt;I tried the app on my Android device, and even downloaded the smallest &lt;code&gt;Gemma-4-E2B-it&lt;/code&gt; model and it worked fine. The app has multiple different options, as you see in the screenshots, and it looks stunning as well.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Google AI Edge Gallery app on Android&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/google-ai-edge-gallery/google-ai-edge-gallery.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I am traveling next week via train and the network is not stable sometimes, so I can easily chat with these local models. I have tested for a bit, and they&#39;re good at non-coding stuff.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Blocking disposable email sign-ups in Laravel</title>
    <link href="https://deepakness.com/raw/blocking-disposable-emails/" />
    <updated>2026-04-05T02:41:53Z</updated>
    <id>https://deepakness.com/raw/blocking-disposable-emails/</id>
    <summary>Blocking disposable email sign-ups in Laravel with a custom validation rule and a 72,000+ domain JSON blocklist.</summary>
    <content type="html">&lt;p&gt;I noticed some users signing up on a project with throwaway emails from services like yopmail, guerrillamail, and tempmail. They&#39;d sign up, poke around, and create multiple accounts to use the service for free.&lt;/p&gt;
&lt;p&gt;I researched solutions for it and found &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/Propaganistas/Laravel-Disposable-Email&quot;&gt;propaganistas/laravel-disposable-email&lt;/a&gt;, a popular Laravel package (~1.35M downloads) that gives you an &lt;code&gt;indisposable&lt;/code&gt; validation rule. It pulls from a community-maintained list of ~72k known disposable domains.&lt;/p&gt;
&lt;p&gt;But I didn&#39;t want another package dependency for something this simple. So I grabbed their JSON file with 72,000+ disposable domains, and wrote a tiny custom validation rule:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name-definition class-name&quot;&gt;NotDisposableEmail&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ValidationRule&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword type-hint&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$attribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword type-hint&quot;&gt;mixed&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name type-declaration&quot;&gt;Closure&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword return-type&quot;&gt;void&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$domain&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strtolower&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strrchr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;@&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;in_array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$domain&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;disposableDomains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token variable&quot;&gt;$fail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Disposable email addresses are not allowed. Please use a permanent email address.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;disposableDomains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword return-type&quot;&gt;array&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;once&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword return-type&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token variable&quot;&gt;$path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resource_path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;data/disposable-domains.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;file_exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;json_decode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;file_get_contents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then added it to the registration validation in &lt;code&gt;CreateNewUser.php&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;email&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;required&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;string&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;email&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;max:255&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NotDisposableEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name static-context&quot;&gt;Rule&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name static-context&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s it. No package, no API calls, no latency. The JSON file loads once per request (using Laravel&#39;s &lt;code&gt;once()&lt;/code&gt; helper), and if the file is somehow missing, it silently passes so nothing breaks. It shows this when someone tries signing up using a disposable email:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Disposable email signup block&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/blocking-disposable-emails/disposable-email-signup.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;The only downside is that the list is static and new disposable services won&#39;t be caught until I update the JSON. But for now, it&#39;s good.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After many people &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://www.threads.com/@deepakness/post/DWv9ry_kbK0&quot;&gt;pointed out on Thread&lt;/a&gt; and X, I have now removed the blocking for disposable domains and exploring better ways to filter out low-quality signups.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Backing up important GitHub repos</title>
    <link href="https://deepakness.com/raw/github-repos-backup/" />
    <updated>2026-04-04T12:08:24Z</updated>
    <id>https://deepakness.com/raw/github-repos-backup/</id>
    <summary>How I am using my small Raspberry Pi 4B device to keep additional copies of code for my important GitHub repos.</summary>
    <content type="html">&lt;p&gt;Lately, GitHub hasn&#39;t been very stable and I also read a story of GitHub blocking someone&#39;s account on Reddit, so I do not have a lot of trust to keep my code only on one platform. And I used my small Raspberry Pi 4B 1 GB device to keep additional copies of my important repos.&lt;/p&gt;
&lt;p&gt;Here&#39;s the bash script to mirror specific GitHub repos locally (with optional GitLab push). Supports org repos, wikis, LFS, allowlist/blocklist filtering, and dry-run mode:&lt;/p&gt;
&lt;p&gt;First, this &lt;code&gt;backup_github_repos.sh&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-Eeuo&lt;/span&gt; pipefail

&lt;span class=&quot;token function-name function&quot;&gt;usage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;EOF&#39;
Backup all owned GitHub repositories to local mirror clones and optionally push them to GitLab.

Usage:
  ./backup_github_repos.sh [path/to/config.env]

Prerequisites:
  - git
  - gh
  - jq
  - gh auth login
  - gh auth setup-git

Optional:
  - git-lfs (if FETCH_LFS=1)
  - GitLab SSH key (if ENABLE_GITLAB_PUSH=1)

This script:
  - mirrors all repos you own on GitHub
  - can also mirror selected GitHub org repos
  - can limit backups to an exact allowlist of repos
  - can back up wiki repos when they exist
  - can push matching repos to GitLab over SSH

It does NOT back up GitHub issues, pull requests, discussions, or release assets.
EOF&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function-name function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[%s] %s&#92;n&#39;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;+%F %T&#39;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$*&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function-name function&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[%s] WARNING: %s&#92;n&#39;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;+%F %T&#39;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$*&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;2&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function-name function&quot;&gt;die&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[%s] ERROR: %s&#92;n&#39;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;+%F %T&#39;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$*&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;2&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function-name function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${DRY_RUN}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;DRY_RUN:&#39;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39; %q&#39;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$@&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#92;n&#39;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$@&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function-name function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${1&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;}&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token assign-left variable&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;${value#&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${value&lt;span class=&quot;token operator&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;space&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;*}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;}&quot;&lt;/span&gt;
  &lt;span class=&quot;token assign-left variable&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;${value%&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${value&lt;span class=&quot;token operator&quot;&gt;##&lt;/span&gt;*&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;space&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;}&lt;/span&gt;&quot;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  printf &#39;%s&#39; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
}

require_cmd() {
  command -v &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &gt;/dev/null 2&gt;&amp;amp;1 || die &quot;&lt;/span&gt;Missing required command: &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
}

csv_list_contains() {
  local needle=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local csv=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local item

  IFS=&#39;,&#39; read -r -a items &amp;lt;&amp;lt;&amp;lt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$csv&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  for raw_item in &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${items&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;@&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;; do
    item=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;trim &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$raw_item&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
    [[ -n &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$item&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ]] || continue
    [[ &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$item&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; == &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$needle&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ]] &amp;amp;&amp;amp; return 0
  done

  return 1
}

gh_repo_stream_owned() {
  gh api --paginate &quot;&lt;/span&gt;/user/repos?affiliation&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;owner&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;per_page&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &#92;
    | jq -c &#39;.[] | {
        name,
        full_name,
        private,
        archived,
        fork,
        has_wiki,
        clone_url,
        ssh_url,
        owner: .owner.login
      }&#39;
}

gh_repo_stream_org() {
  local org=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  gh api --paginate &quot;&lt;/span&gt;/orgs/&lt;span class=&quot;token variable&quot;&gt;${org}&lt;/span&gt;/repos?type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;all&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;per_page&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &#92;
    | jq -c &#39;.[] | {
        name,
        full_name,
        private,
        archived,
        fork,
        has_wiki,
        clone_url,
        ssh_url,
        owner: .owner.login
      }&#39;
}

write_repo_metadata() {
  local repo_json=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local owner=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local repo=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$3&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local metadata_dir=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${BACKUP_ROOT}&lt;/span&gt;/metadata/&lt;span class=&quot;token variable&quot;&gt;${owner}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  mkdir -p &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$metadata_dir&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  jq &#39;.&#39; &amp;lt;&amp;lt;&amp;lt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &gt; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${metadata_dir}&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;${repo}&lt;/span&gt;.json&lt;span class=&quot;token string&quot;&gt;&quot;
}

sync_git_mirror() {
  local source_url=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local destination=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local label=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$3&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;

  mkdir -p &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dirname&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;

  if [[ -d &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ]]; then
    log &quot;&lt;/span&gt;Updating mirror: &lt;span class=&quot;token variable&quot;&gt;${label}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
    run git -C &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; remote set-url origin &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$source_url&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
    run git -C &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; remote update --prune
  else
    log &quot;&lt;/span&gt;Creating mirror: &lt;span class=&quot;token variable&quot;&gt;${label}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
    run git clone --mirror &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$source_url&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  fi
}

fetch_lfs_objects() {
  local destination=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local label=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;

  if [[ &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${FETCH_LFS}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; != &quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ]]; then
    return 0
  fi

  if ! git lfs version &gt;/dev/null 2&gt;&amp;amp;1; then
    die &quot;&lt;/span&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;FETCH_LFS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; but git-lfs is not installed&lt;span class=&quot;token string&quot;&gt;&quot;
  fi

  log &quot;&lt;/span&gt;Fetching LFS objects: &lt;span class=&quot;token variable&quot;&gt;${label}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  if ! run git -C &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; lfs fetch --all origin; then
    warn &quot;&lt;/span&gt;LFS fetch failed &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;${label}&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; The Git mirror is still valid, but LFS content may be incomplete.&lt;span class=&quot;token string&quot;&gt;&quot;
  fi
}

gitlab_remote_url() {
  local repo_name=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  printf &#39;git@gitlab.com:%s/%s.git&#39; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$GITLAB_NAMESPACE&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$repo_name&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
}

gitlab_remote_exists() {
  local repo_name=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  git ls-remote &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;gitlab_remote_url &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_name&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &gt;/dev/null 2&gt;&amp;amp;1
}

ensure_gitlab_repo() {
  local repo_name=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;

  if gitlab_remote_exists &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$repo_name&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;; then
    return 0
  fi

  if [[ &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${GITLAB_CREATE_REPOS}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; != &quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ]]; then
    die &quot;&lt;/span&gt;GitLab repo &lt;span class=&quot;token variable&quot;&gt;${GITLAB_NAMESPACE}&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;${repo_name}&lt;/span&gt; does not exist and &lt;span class=&quot;token assign-left variable&quot;&gt;GITLAB_CREATE_REPOS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  fi

  log &quot;&lt;/span&gt;GitLab repo &lt;span class=&quot;token variable&quot;&gt;${GITLAB_NAMESPACE}&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;${repo_name}&lt;/span&gt; will be created on first push &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; your SSH key can create projects &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; that namespace&lt;span class=&quot;token string&quot;&gt;&quot;
}

push_git_mirror_to_gitlab() {
  local destination=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local repo_name=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local label=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$3&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local remote_url

  remote_url=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;gitlab_remote_url &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_name&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;

  if git -C &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; remote get-url gitlab &gt;/dev/null 2&gt;&amp;amp;1; then
    run git -C &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; remote set-url gitlab &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$remote_url&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  else
    run git -C &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; remote add gitlab &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$remote_url&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  fi

  log &quot;&lt;/span&gt;Pushing branches and tags to GitLab: &lt;span class=&quot;token variable&quot;&gt;${label}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  run git -C &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; push --prune gitlab &#92;
    &#39;+refs/heads/*:refs/heads/*&#39; &#92;
    &#39;+refs/tags/*:refs/tags/*&#39;

  if [[ &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${FETCH_LFS}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; == &quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ]]; then
    if ! run git -C &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; lfs push --all gitlab; then
      warn &quot;&lt;/span&gt;LFS push failed &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;${label}&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; Check GitLab LFS configuration &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; this repo uses LFS.&lt;span class=&quot;token string&quot;&gt;&quot;
    fi
  fi
}

should_backup_repo() {
  local repo_json=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local archived
  local forked
  local full_name

  archived=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.archived&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  forked=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.fork&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  full_name=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.full_name&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;

  if [[ -n &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${REPO_ALLOWLIST}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ]] &amp;amp;&amp;amp; ! csv_list_contains &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$full_name&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$REPO_ALLOWLIST&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;; then
    return 1
  fi

  if [[ -n &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${REPO_BLOCKLIST}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ]] &amp;amp;&amp;amp; csv_list_contains &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$full_name&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$REPO_BLOCKLIST&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;; then
    return 1
  fi

  if [[ &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$archived&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; == &quot;&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &amp;amp;&amp;amp; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${INCLUDE_ARCHIVED_REPOS}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; != &quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ]]; then
    return 1
  fi

  if [[ &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$forked&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; == &quot;&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &amp;amp;&amp;amp; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${INCLUDE_FORKS}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; != &quot;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ]]; then
    return 1
  fi

  return 0
}

sync_repo_bundle() {
  local repo_json=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  local full_name
  local owner
  local repo
  local clone_url
  local private_flag
  local has_wiki
  local mirror_dir
  local wiki_dir
  local wiki_url
  local wiki_repo_name

  full_name=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.full_name&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  owner=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${full_name&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;*}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  repo=&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${full_name&lt;span class=&quot;token operator&quot;&gt;#&lt;/span&gt;*&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;}&lt;/span&gt;&quot;
  &lt;span class=&quot;token assign-left variable&quot;&gt;clone_url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.clone_url&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token assign-left variable&quot;&gt;private_flag&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.private&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token assign-left variable&quot;&gt;has_wiki&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.has_wiki&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;

  &lt;span class=&quot;token assign-left variable&quot;&gt;mirror_dir&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BACKUP_ROOT}&lt;/span&gt;/mirrors/&lt;span class=&quot;token variable&quot;&gt;${owner}&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;${repo}&lt;/span&gt;.git&quot;&lt;/span&gt;
  write_repo_metadata &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$owner&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo&lt;/span&gt;&quot;&lt;/span&gt;
  sync_git_mirror &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$clone_url&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$mirror_dir&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$full_name&lt;/span&gt;&quot;&lt;/span&gt;
  fetch_lfs_objects &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$mirror_dir&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$full_name&lt;/span&gt;&quot;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${ENABLE_GITLAB_PUSH}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    ensure_gitlab_repo &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo&lt;/span&gt;&quot;&lt;/span&gt;
    push_git_mirror_to_gitlab &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$mirror_dir&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$full_name&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$has_wiki&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${INCLUDE_WIKIS}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

  &lt;span class=&quot;token assign-left variable&quot;&gt;wiki_url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${clone_url&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;.git}&lt;/span&gt;.wiki.git&quot;&lt;/span&gt;
  &lt;span class=&quot;token assign-left variable&quot;&gt;wiki_repo_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${repo}&lt;/span&gt;.wiki&quot;&lt;/span&gt;
  &lt;span class=&quot;token assign-left variable&quot;&gt;wiki_dir&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BACKUP_ROOT}&lt;/span&gt;/mirrors/&lt;span class=&quot;token variable&quot;&gt;${owner}&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;${wiki_repo_name}&lt;/span&gt;.git&quot;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; ls-remote &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$wiki_url&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;/dev/null &lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;2&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    sync_git_mirror &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$wiki_url&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$wiki_dir&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${full_name}&lt;/span&gt; wiki&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${ENABLE_GITLAB_PUSH}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${GITLAB_PUSH_WIKIS}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
      ensure_gitlab_repo &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$wiki_repo_name&lt;/span&gt;&quot;&lt;/span&gt;
      push_git_mirror_to_gitlab &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$wiki_dir&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$wiki_repo_name&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${full_name}&lt;/span&gt; wiki&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    warn &lt;span class=&quot;token string&quot;&gt;&quot;Wiki enabled but no wiki repo found for &lt;span class=&quot;token variable&quot;&gt;${full_name}&lt;/span&gt;; skipping wiki backup&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${1&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-h&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${1&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;--help&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
  usage
  &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$#&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-gt&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
  usage &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;2&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$#&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-eq&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
  &lt;span class=&quot;token assign-left variable&quot;&gt;ENV_FILE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$ENV_FILE&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; die &lt;span class=&quot;token string&quot;&gt;&quot;Config file not found: &lt;span class=&quot;token variable&quot;&gt;$ENV_FILE&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-a&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# shellcheck source=/dev/null&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$ENV_FILE&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; +a
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;token assign-left variable&quot;&gt;BACKUP_ROOT&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BACKUP_ROOT&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;$HOME&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;github-repo-backups}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;INCLUDE_OWNED_REPOS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${INCLUDE_OWNED_REPOS&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;1}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;GITHUB_ORGS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${GITHUB_ORGS&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;REPO_ALLOWLIST&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${REPO_ALLOWLIST&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;REPO_BLOCKLIST&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${REPO_BLOCKLIST&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;INCLUDE_ARCHIVED_REPOS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${INCLUDE_ARCHIVED_REPOS&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;1}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;INCLUDE_FORKS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${INCLUDE_FORKS&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;1}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;INCLUDE_WIKIS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${INCLUDE_WIKIS&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;1}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;FETCH_LFS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${FETCH_LFS&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;0}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;ENABLE_GITLAB_PUSH&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${ENABLE_GITLAB_PUSH&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;0}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;GITLAB_NAMESPACE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${GITLAB_NAMESPACE&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;GITLAB_CREATE_REPOS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${GITLAB_CREATE_REPOS&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;1}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;GITLAB_PUSH_WIKIS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${GITLAB_PUSH_WIKIS&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;1}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;DRY_RUN&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${DRY_RUN&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;0}&lt;/span&gt;&quot;&lt;/span&gt;

require_cmd &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt;
require_cmd gh
require_cmd jq
gh auth status &lt;span class=&quot;token parameter variable&quot;&gt;--hostname&lt;/span&gt; github.com &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;/dev/null &lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;2&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; die &lt;span class=&quot;token string&quot;&gt;&quot;GitHub CLI is not authenticated. Run: gh auth login&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${ENABLE_GITLAB_PUSH}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${GITLAB_NAMESPACE}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; die &lt;span class=&quot;token string&quot;&gt;&quot;ENABLE_GITLAB_PUSH=1 requires GITLAB_NAMESPACE&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BACKUP_ROOT}&lt;/span&gt;/mirrors&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${BACKUP_ROOT}&lt;/span&gt;/metadata&quot;&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;seen_repos&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;repo_count&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${INCLUDE_OWNED_REPOS}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${GITHUB_ORGS}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
  die &lt;span class=&quot;token string&quot;&gt;&quot;Nothing to do. Set INCLUDE_OWNED_REPOS=1 and/or GITHUB_ORGS&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

log &lt;span class=&quot;token string&quot;&gt;&quot;Backup root: &lt;span class=&quot;token variable&quot;&gt;${BACKUP_ROOT}&lt;/span&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;IFS&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; repo_json&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;continue&lt;/span&gt;

  &lt;span class=&quot;token assign-left variable&quot;&gt;full_name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;jq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.full_name&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${seen_repos&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;$full_name&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;continue&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
  seen_repos&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$full_name&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; should_backup_repo &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    log &lt;span class=&quot;token string&quot;&gt;&quot;Skipping repo due to filters: &lt;span class=&quot;token variable&quot;&gt;${full_name}&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;continue&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

  sync_repo_bundle &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$repo_json&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;((&lt;/span&gt;repo_count&lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${INCLUDE_OWNED_REPOS}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
      gh_repo_stream_owned
    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

    &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;IFS&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;,&#39;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-a&lt;/span&gt; orgs &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${GITHUB_ORGS}&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token for-or-select variable&quot;&gt;raw_org&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${orgs&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;@&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;}&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;token assign-left variable&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;trim &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$raw_org&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$org&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;continue&lt;/span&gt;
      gh_repo_stream_org &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$org&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

log &lt;span class=&quot;token string&quot;&gt;&quot;Completed backup run for &lt;span class=&quot;token variable&quot;&gt;${repo_count}&lt;/span&gt; repositories&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then this &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Local backup location&lt;/span&gt;
BACKUP_ROOT=&quot;$HOME/github&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;backup/repo&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;backups&quot;

&lt;span class=&quot;token comment&quot;&gt;# Backup all repos owned by the authenticated GitHub user.&lt;/span&gt;
INCLUDE_OWNED_REPOS=1

&lt;span class=&quot;token comment&quot;&gt;# Optional comma-separated GitHub org names to back up too.&lt;/span&gt;
GITHUB_ORGS=&quot;&quot;

&lt;span class=&quot;token comment&quot;&gt;# Optional exact repo allow/block lists using owner/repo names.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# If REPO_ALLOWLIST is non-empty, only those repos are backed up.&lt;/span&gt;
REPO_ALLOWLIST=&quot;&quot;
REPO_BLOCKLIST=&quot;&quot;

&lt;span class=&quot;token comment&quot;&gt;# Include archived repos and forks.&lt;/span&gt;
INCLUDE_ARCHIVED_REPOS=1
INCLUDE_FORKS=1

&lt;span class=&quot;token comment&quot;&gt;# Also back up wiki repos when they exist.&lt;/span&gt;
INCLUDE_WIKIS=1

&lt;span class=&quot;token comment&quot;&gt;# Set to 1 if you use Git LFS and have git-lfs installed.&lt;/span&gt;
FETCH_LFS=0

&lt;span class=&quot;token comment&quot;&gt;# Optional GitLab mirror push.&lt;/span&gt;
ENABLE_GITLAB_PUSH=0

&lt;span class=&quot;token comment&quot;&gt;# The target user or group on GitLab.&lt;/span&gt;
GITLAB_NAMESPACE=&quot;&quot;

&lt;span class=&quot;token comment&quot;&gt;# If set to 1, GitLab may create missing repos on first push if your SSH key&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# has permission to create projects in that namespace.&lt;/span&gt;
GITLAB_CREATE_REPOS=0

&lt;span class=&quot;token comment&quot;&gt;# Also push wiki mirrors to GitLab.&lt;/span&gt;
GITLAB_PUSH_WIKIS=0

&lt;span class=&quot;token comment&quot;&gt;# Print actions without changing anything.&lt;/span&gt;
DRY_RUN=0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then here are some instructions to set this up:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Install dependencies&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt&lt;/span&gt; update &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; jq&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then install the GitHub CLI:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;755&lt;/span&gt; /etc/apt/keyrings
&lt;span class=&quot;token function&quot;&gt;wget&lt;/span&gt; -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tee&lt;/span&gt; /etc/apt/keyrings/githubcli-archive-keyring.gpg &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /dev/null
&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;deb [arch=&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;dpkg --print-architecture&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt; signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tee&lt;/span&gt; /etc/apt/sources.list.d/github-cli.list &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /dev/null
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt&lt;/span&gt; update &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; gh&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Authenticate&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gh auth login
gh auth setup-git&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Place your files&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Put backup_github_repos.sh and your config.env somewhere like ~/github-backup/. Make the script executable:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; +x backup_github_repos.sh&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;strong&gt;Test it&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;./backup_github_repos.sh config.env&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;&lt;strong&gt;Automate with cron&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Run &lt;code&gt;crontab -e&lt;/code&gt; and add a line like:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; * * * /home/pi/github-backup/backup_github_repos.sh /home/pi/github-backup/config.env &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; /home/pi/github-backup/backup.log &lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;2&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This runs the backup daily at 3 AM and logs output. Adjust the paths and schedule to your liking.&lt;/p&gt;
&lt;p&gt;I might be missing some steps here, so if you&#39;re stuck somewhere make sure to give this to an LLM and ask it to help you do the setup.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Introducing Vemgram</title>
    <link href="https://deepakness.com/raw/introducing-vemgram/" />
    <updated>2026-04-03T13:29:38Z</updated>
    <id>https://deepakness.com/raw/introducing-vemgram/</id>
    <summary>Vemgram is a platform that helps connect Indian manufacturers with retailers, gives them an online identity.</summary>
    <content type="html">&lt;p&gt;It all started from &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/Ajain112/status/2000894862087086201&quot;&gt;this post on X&lt;/a&gt; from Akshay G Jain which was shared with by my friend &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://amitsarda.xyz&quot;&gt;Amit Sarda&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Akshay about IndiaMart&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/introducing-vemgram/akshay-about-indiamart.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I immediately decided to &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2002826312352981013&quot;&gt;plan and work on it&lt;/a&gt;. Initially, I was working at a slow pace but I kept working. And here we are with this brand-new platform called &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://vemgram.com&quot;&gt;Vemgram&lt;/a&gt; that helps Indian manufacturers connect with retailers and build a strong digital presence.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Vemgram homepage screenshot&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/introducing-vemgram/vemgram-homepage.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I am working with &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://bikashkampo.com&quot;&gt;Bikash Kampo&lt;/a&gt; on this project and the concept is simple, we want to build a trusted directory of Indian manufactures where retailers won&#39;t have to worry about getting scammed, and manufactures get a solid digital presence. I am also regularly updating what I am working on for this project &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/vemgram/&quot;&gt;on this page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&#39;s still work in progress, and probably always will be, but the current version of Vemgram allows people to create &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://vemgram.com/m/sarda-ladha-group-oJHO7jZodLpm&quot;&gt;business profiles like this&lt;/a&gt;, list their products, and receive business inquiries from retailers. And currently I am working on implementing custom domain and analytics features.&lt;/p&gt;
&lt;p&gt;I have done an &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2040055186862006276&quot;&gt;introduction post on X&lt;/a&gt;. And I am also open to feedback on this, so if you have any please email me or DM me on socials.&lt;/p&gt;
&lt;p&gt;Additionally, I am grateful to my friends Amit Sarda, &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://rohit.online&quot;&gt;Rohit&lt;/a&gt;, and my girlfriend for their helpful feedback on my ideas.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Preventing Docker and journal cache bloat on VPS</title>
    <link href="https://deepakness.com/raw/docker-journal-cache-bloat-fix/" />
    <updated>2026-04-03T12:32:49Z</updated>
    <id>https://deepakness.com/raw/docker-journal-cache-bloat-fix/</id>
    <summary>Preventing Docker cache and systemd journal logs from bloating my VPS disk space with automated cleanup.</summary>
    <content type="html">&lt;p&gt;I have two VPS servers running Dokploy, and I noticed that even 80 GB of disk space on the servers were getting full and apps failed to deploy. The culprits were Docker cache (old images, build cache, dangling stuff from past deployments) and systemd journal logs that grow indefinitely by default.&lt;/p&gt;
&lt;p&gt;Running the &lt;code&gt;docker builder prune -a&lt;/code&gt; command freed ~67 GB of space on the server, so I set up a few things to automate this process:&lt;/p&gt;
&lt;p&gt;First, I added a cron job that auto-prunes Docker every 6 hours, but only if disk usage goes above 70%:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;crontab &lt;span class=&quot;token parameter variable&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;2&lt;/span&gt;&gt;&lt;/span&gt;/dev/null&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;0 */6 * * * [ $(df / --output=pcent | tail -1 | tr -dc 0-9) -gt 70 ] &amp;amp;&amp;amp; docker system prune -af --filter &quot;until=72h&quot; &amp;amp;&amp;amp; docker builder prune -af &gt;&gt; /var/log/docker-prune.log 2&gt;&amp;amp;1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;crontab&lt;/span&gt; -&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This removes unused images and build cache older than 72 hours. It doesn&#39;t touch running containers, so active deployments are safe.&lt;/p&gt;
&lt;p&gt;Then, I vacuumed the existing journal logs down to 200MB:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;journalctl --vacuum-size&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;200M&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally, I capped the journal log size permanently so it never grows beyond 200MB again:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;s/#SystemMaxUse=/SystemMaxUse=200M/&#39;&lt;/span&gt; /etc/systemd/journald.conf
systemctl restart systemd-journald&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Applied the same setup on both servers and now I don&#39;t have to worry about cache eating up disk space over time. I know there are some drawbacks of this method, but I think the benefits outweigh them.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>LLM Knowledge Bases post by Andrej Karpathy</title>
    <link href="https://deepakness.com/raw/llm-knowledge-bases/" />
    <updated>2026-04-03T02:51:58Z</updated>
    <id>https://deepakness.com/raw/llm-knowledge-bases/</id>
    <summary>Thoughts on the post from Andrej Karpathy about using LLMs to manage personal knowledge bases using Obsidian.</summary>
    <content type="html">&lt;p&gt;Andrej Karpathy recently &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/karpathy/status/2039805659525644595&quot;&gt;published this post on X&lt;/a&gt; about building and managing personal knowledge bases using LLMs, and there&#39;s some interesting information in the post that I am going to collect below.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lately, Andrej is spending more tokens manipulating knowledge than manipulating code.&lt;/li&gt;
&lt;li&gt;He uses Obsidian for storing all the knowledge (articles, papers, repos, datasets, etc.) in Markdown and image formats. And uses Obsidian&#39;s Web Clipper to grab info from web articles.&lt;/li&gt;
&lt;li&gt;He puts everything in a &lt;code&gt;/raw&lt;/code&gt; folder and then uses an LLM to incrementally &quot;compile&quot; a wiki with visualizations. He specifically mentions that the LLM writes and maintains all of the data of the wiki and he doesn&#39;t manually edit/add anything.&lt;/li&gt;
&lt;li&gt;He has ~100 articles on several topics that he can ask LLMs to fetch answers to complex questions against the wiki.&lt;/li&gt;
&lt;li&gt;When chatting with the LLM against the wiki, he prefers generating new Markdown files, slideshows (Marp format), or matplotlib images. And then even files the outputs back into the wiki to further enhance it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&#39;s much more info in the post that you can read.&lt;/p&gt;
&lt;p&gt;I love this approach and I guess I will also be using something similar very soon, as managing lots of stuff is becoming difficult over time. And if I do, I will write about it.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>List of 187 Claude spinner verbs (leaked)</title>
    <link href="https://deepakness.com/raw/claude-spinner-verbs/" />
    <updated>2026-04-01T06:46:58Z</updated>
    <id>https://deepakness.com/raw/claude-spinner-verbs/</id>
    <summary>From the leaked Claude codebase, here&#39;s the list of all, 187, spinner verbs that you see when Claude Code is working.</summary>
    <content type="html">&lt;p&gt;No idea who leaked the Claude Code codebase, but I came across this list of spinner verbs Claude uses &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/wesbos/status/2038958747200962952&quot;&gt;from this post on X&lt;/a&gt;. And it&#39;s super cool.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Accomplishing&lt;/li&gt;
&lt;li&gt;Actioning&lt;/li&gt;
&lt;li&gt;Actualizing&lt;/li&gt;
&lt;li&gt;Architecting&lt;/li&gt;
&lt;li&gt;Baking&lt;/li&gt;
&lt;li&gt;Beaming&lt;/li&gt;
&lt;li&gt;Beboppin&#39;&lt;/li&gt;
&lt;li&gt;Befuddling&lt;/li&gt;
&lt;li&gt;Billowing&lt;/li&gt;
&lt;li&gt;Blanching&lt;/li&gt;
&lt;li&gt;Bloviating&lt;/li&gt;
&lt;li&gt;Boogieing&lt;/li&gt;
&lt;li&gt;Boondoggling&lt;/li&gt;
&lt;li&gt;Booping&lt;/li&gt;
&lt;li&gt;Bootstrapping&lt;/li&gt;
&lt;li&gt;Brewing&lt;/li&gt;
&lt;li&gt;Bunning&lt;/li&gt;
&lt;li&gt;Burrowing&lt;/li&gt;
&lt;li&gt;Calculating&lt;/li&gt;
&lt;li&gt;Canoodling&lt;/li&gt;
&lt;li&gt;Caramelizing&lt;/li&gt;
&lt;li&gt;Cascading&lt;/li&gt;
&lt;li&gt;Catapulting&lt;/li&gt;
&lt;li&gt;Cerebrating&lt;/li&gt;
&lt;li&gt;Channeling&lt;/li&gt;
&lt;li&gt;Channelling&lt;/li&gt;
&lt;li&gt;Choreographing&lt;/li&gt;
&lt;li&gt;Churning&lt;/li&gt;
&lt;li&gt;Clauding&lt;/li&gt;
&lt;li&gt;Coalescing&lt;/li&gt;
&lt;li&gt;Cogitating&lt;/li&gt;
&lt;li&gt;Combobulating&lt;/li&gt;
&lt;li&gt;Composing&lt;/li&gt;
&lt;li&gt;Computing&lt;/li&gt;
&lt;li&gt;Concocting&lt;/li&gt;
&lt;li&gt;Considering&lt;/li&gt;
&lt;li&gt;Contemplating&lt;/li&gt;
&lt;li&gt;Cooking&lt;/li&gt;
&lt;li&gt;Crafting&lt;/li&gt;
&lt;li&gt;Creating&lt;/li&gt;
&lt;li&gt;Crunching&lt;/li&gt;
&lt;li&gt;Crystallizing&lt;/li&gt;
&lt;li&gt;Cultivating&lt;/li&gt;
&lt;li&gt;Deciphering&lt;/li&gt;
&lt;li&gt;Deliberating&lt;/li&gt;
&lt;li&gt;Determining&lt;/li&gt;
&lt;li&gt;Dilly-dallying&lt;/li&gt;
&lt;li&gt;Discombobulating&lt;/li&gt;
&lt;li&gt;Doing&lt;/li&gt;
&lt;li&gt;Doodling&lt;/li&gt;
&lt;li&gt;Drizzling&lt;/li&gt;
&lt;li&gt;Ebbing&lt;/li&gt;
&lt;li&gt;Effecting&lt;/li&gt;
&lt;li&gt;Elucidating&lt;/li&gt;
&lt;li&gt;Embellishing&lt;/li&gt;
&lt;li&gt;Enchanting&lt;/li&gt;
&lt;li&gt;Envisioning&lt;/li&gt;
&lt;li&gt;Evaporating&lt;/li&gt;
&lt;li&gt;Fermenting&lt;/li&gt;
&lt;li&gt;Fiddle-faddling&lt;/li&gt;
&lt;li&gt;Finagling&lt;/li&gt;
&lt;li&gt;Flambéing&lt;/li&gt;
&lt;li&gt;Flibbertigibbeting&lt;/li&gt;
&lt;li&gt;Flowing&lt;/li&gt;
&lt;li&gt;Flummoxing&lt;/li&gt;
&lt;li&gt;Fluttering&lt;/li&gt;
&lt;li&gt;Forging&lt;/li&gt;
&lt;li&gt;Forming&lt;/li&gt;
&lt;li&gt;Frolicking&lt;/li&gt;
&lt;li&gt;Frosting&lt;/li&gt;
&lt;li&gt;Gallivanting&lt;/li&gt;
&lt;li&gt;Galloping&lt;/li&gt;
&lt;li&gt;Garnishing&lt;/li&gt;
&lt;li&gt;Generating&lt;/li&gt;
&lt;li&gt;Gesticulating&lt;/li&gt;
&lt;li&gt;Germinating&lt;/li&gt;
&lt;li&gt;Gitifying&lt;/li&gt;
&lt;li&gt;Grooving&lt;/li&gt;
&lt;li&gt;Gusting&lt;/li&gt;
&lt;li&gt;Harmonizing&lt;/li&gt;
&lt;li&gt;Hashing&lt;/li&gt;
&lt;li&gt;Hatching&lt;/li&gt;
&lt;li&gt;Herding&lt;/li&gt;
&lt;li&gt;Honking&lt;/li&gt;
&lt;li&gt;Hullaballooing&lt;/li&gt;
&lt;li&gt;Hyperspacing&lt;/li&gt;
&lt;li&gt;Ideating&lt;/li&gt;
&lt;li&gt;Imagining&lt;/li&gt;
&lt;li&gt;Improvising&lt;/li&gt;
&lt;li&gt;Incubating&lt;/li&gt;
&lt;li&gt;Inferring&lt;/li&gt;
&lt;li&gt;Infusing&lt;/li&gt;
&lt;li&gt;Ionizing&lt;/li&gt;
&lt;li&gt;Jitterbugging&lt;/li&gt;
&lt;li&gt;Julienning&lt;/li&gt;
&lt;li&gt;Kneading&lt;/li&gt;
&lt;li&gt;Leavening&lt;/li&gt;
&lt;li&gt;Levitating&lt;/li&gt;
&lt;li&gt;Lollygagging&lt;/li&gt;
&lt;li&gt;Manifesting&lt;/li&gt;
&lt;li&gt;Marinating&lt;/li&gt;
&lt;li&gt;Meandering&lt;/li&gt;
&lt;li&gt;Metamorphosing&lt;/li&gt;
&lt;li&gt;Misting&lt;/li&gt;
&lt;li&gt;Moonwalking&lt;/li&gt;
&lt;li&gt;Moseying&lt;/li&gt;
&lt;li&gt;Mulling&lt;/li&gt;
&lt;li&gt;Mustering&lt;/li&gt;
&lt;li&gt;Musing&lt;/li&gt;
&lt;li&gt;Nebulizing&lt;/li&gt;
&lt;li&gt;Nesting&lt;/li&gt;
&lt;li&gt;Newspapering&lt;/li&gt;
&lt;li&gt;Noodling&lt;/li&gt;
&lt;li&gt;Nucleating&lt;/li&gt;
&lt;li&gt;Orbiting&lt;/li&gt;
&lt;li&gt;Orchestrating&lt;/li&gt;
&lt;li&gt;Osmosing&lt;/li&gt;
&lt;li&gt;Perambulating&lt;/li&gt;
&lt;li&gt;Percolating&lt;/li&gt;
&lt;li&gt;Perusing&lt;/li&gt;
&lt;li&gt;Philosophising&lt;/li&gt;
&lt;li&gt;Photosynthesizing&lt;/li&gt;
&lt;li&gt;Pollinating&lt;/li&gt;
&lt;li&gt;Pondering&lt;/li&gt;
&lt;li&gt;Pontificating&lt;/li&gt;
&lt;li&gt;Pouncing&lt;/li&gt;
&lt;li&gt;Precipitating&lt;/li&gt;
&lt;li&gt;Prestidigitating&lt;/li&gt;
&lt;li&gt;Processing&lt;/li&gt;
&lt;li&gt;Proofing&lt;/li&gt;
&lt;li&gt;Propagating&lt;/li&gt;
&lt;li&gt;Puttering&lt;/li&gt;
&lt;li&gt;Puzzling&lt;/li&gt;
&lt;li&gt;Quantumizing&lt;/li&gt;
&lt;li&gt;Razzle-dazzling&lt;/li&gt;
&lt;li&gt;Razzmatazzing&lt;/li&gt;
&lt;li&gt;Recombobulating&lt;/li&gt;
&lt;li&gt;Reticulating&lt;/li&gt;
&lt;li&gt;Roosting&lt;/li&gt;
&lt;li&gt;Ruminating&lt;/li&gt;
&lt;li&gt;Sautéing&lt;/li&gt;
&lt;li&gt;Scampering&lt;/li&gt;
&lt;li&gt;Schlepping&lt;/li&gt;
&lt;li&gt;Scurrying&lt;/li&gt;
&lt;li&gt;Seasoning&lt;/li&gt;
&lt;li&gt;Shenaniganing&lt;/li&gt;
&lt;li&gt;Shimmying&lt;/li&gt;
&lt;li&gt;Simmering&lt;/li&gt;
&lt;li&gt;Skedaddling&lt;/li&gt;
&lt;li&gt;Sketching&lt;/li&gt;
&lt;li&gt;Slithering&lt;/li&gt;
&lt;li&gt;Smooshing&lt;/li&gt;
&lt;li&gt;Sock-hopping&lt;/li&gt;
&lt;li&gt;Spelunking&lt;/li&gt;
&lt;li&gt;Spinning&lt;/li&gt;
&lt;li&gt;Sprouting&lt;/li&gt;
&lt;li&gt;Stewing&lt;/li&gt;
&lt;li&gt;Sublimating&lt;/li&gt;
&lt;li&gt;Swirling&lt;/li&gt;
&lt;li&gt;Swooping&lt;/li&gt;
&lt;li&gt;Symbioting&lt;/li&gt;
&lt;li&gt;Synthesizing&lt;/li&gt;
&lt;li&gt;Tempering&lt;/li&gt;
&lt;li&gt;Thinking&lt;/li&gt;
&lt;li&gt;Thundering&lt;/li&gt;
&lt;li&gt;Tinkering&lt;/li&gt;
&lt;li&gt;Tomfoolering&lt;/li&gt;
&lt;li&gt;Topsy-turvying&lt;/li&gt;
&lt;li&gt;Transfiguring&lt;/li&gt;
&lt;li&gt;Transmuting&lt;/li&gt;
&lt;li&gt;Twisting&lt;/li&gt;
&lt;li&gt;Undulating&lt;/li&gt;
&lt;li&gt;Unfurling&lt;/li&gt;
&lt;li&gt;Unravelling&lt;/li&gt;
&lt;li&gt;Vibing&lt;/li&gt;
&lt;li&gt;Waddling&lt;/li&gt;
&lt;li&gt;Wandering&lt;/li&gt;
&lt;li&gt;Warping&lt;/li&gt;
&lt;li&gt;Whatchamacalliting&lt;/li&gt;
&lt;li&gt;Whirlpooling&lt;/li&gt;
&lt;li&gt;Whirring&lt;/li&gt;
&lt;li&gt;Whisking&lt;/li&gt;
&lt;li&gt;Wibbling&lt;/li&gt;
&lt;li&gt;Working&lt;/li&gt;
&lt;li&gt;Wrangling&lt;/li&gt;
&lt;li&gt;Zesting&lt;/li&gt;
&lt;li&gt;Zigzagging&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you don&#39;t remember seeing these anywhere, take a look at the screenshot below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Claude Spinner Verbs&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/claude-spinner-verbs/claude-spinner-verb.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Yes, this is shown when you ask Claude Code to do something and then it&#39;s working on it. I believe these spinner verbs are randomly selected from the above list and shown.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>OpenAI launches Codex plugin for Claude Code</title>
    <link href="https://deepakness.com/raw/openai-codex-plugin-for-claude-code/" />
    <updated>2026-03-31T06:03:16Z</updated>
    <id>https://deepakness.com/raw/openai-codex-plugin-for-claude-code/</id>
    <summary>Totally unexpected but OpenAI has launched a new plugin that lets you use Codex inside Claude Code.</summary>
    <content type="html">&lt;p&gt;OpenAI team has &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/dkundel/status/2038670330257109461&quot;&gt;created a Codex plugin&lt;/a&gt; for Claude Code that you can use to trigger Codex inside Claude Code. It&#39;s described as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use the Codex plugin for Claude Code to delegate tasks to Codex or have Codex review your changes using your ChatGPT subscription.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here&#39;s &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/openai/codex-plugin-cc&quot;&gt;the plugin on GitHub&lt;/a&gt; that you can use. This thing works with ChatGPT subscription (including the Free plan) or with an OpenAI API key, and it does count against your Codex usage limits. If you&#39;re looking to learn more about it, Vaibhav from OpenAI has written &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/reach_vb/status/2038670509768839458&quot;&gt;a detailed article&lt;/a&gt; about it that you can follow.&lt;/p&gt;
&lt;p&gt;Apart from this, Claude released computer use so there&#39;s &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/cocktailpeanut/status/2038682479897289089&quot;&gt;this joke&lt;/a&gt; going around on X, and it is funny.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Codex Anthropic use&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/openai-codex-plugin-for-claude-code/codex-anthropic-use.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;But jokes apart, this is going to be super helpful for code reviews. I am definitely using this.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Claude Code is hitting limits fast</title>
    <link href="https://deepakness.com/raw/claude-code-limits/" />
    <updated>2026-03-30T23:32:28Z</updated>
    <id>https://deepakness.com/raw/claude-code-limits/</id>
    <summary>After lots of users complained for a week about Claude Code hitting limits quickly, they&#39;re now finally investigating and working on it.</summary>
    <content type="html">&lt;p&gt;People have been complaining about Claude Code hitting limits quickly for almost a week, and now, finally, the Claude Code team has started to look into this and low-key admitted that this issue exists. Lydia from Claude Code team &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/lydiahallie/status/2038686571676008625&quot;&gt;posted this&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&#39;re aware people are hitting usage limits in Claude Code way faster than expected. Actively investigating, will share more when we have an update!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But why are they suddenly caring about this, and ignored everything previously? The reason is &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://www.reddit.com/r/ClaudeAI/comments/1s7mkn3/psa_claude_code_has_two_cache_bugs_that_can/&quot;&gt;this post on Reddit by /u/skibidi-toaleta-2137&lt;/a&gt;. The person reverse-engineered the Claude Code standalone binary and found out &lt;strong&gt;two serious bugs&lt;/strong&gt; which should be causing the issues.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Bug 1: Sentinel replacement in standalone binary breaks cache when conversation discusses billing internals&lt;/li&gt;
&lt;li&gt;Bug 2: --resume ALWAYS breaks cache (since v2.1.69)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The person has also shared workaround to avoid these issues, but I guess since the Claude team is already working on this, I will wait for a few hours till these gets resolved.&lt;/p&gt;
&lt;p&gt;All I can say is, thank you, stranger from Reddit.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Eating too much watermelon causes indigestion</title>
    <link href="https://deepakness.com/raw/watermelons-and-digestion/" />
    <updated>2026-03-30T03:25:18Z</updated>
    <id>https://deepakness.com/raw/watermelons-and-digestion/</id>
    <summary>Ate ~1.5kg of a watermelon at a time and then got a serious indigestion the next day, and had no idea about this.</summary>
    <content type="html">&lt;p&gt;I didn&#39;t know that eating too much watermelon can cause serious indigestion. The other day, I had ~1.5 kg of a watermelon at a single time (yes, I love them) and experienced digestion issues the next day.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Too much watermelons causing digestive issues&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/watermelons-and-digestion/watermelons-and-digestion.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Apparently, this is &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://www.verywellhealth.com/side-effects-of-watermelon-11778073&quot;&gt;a known fact&lt;/a&gt; and I had no idea about this, until my mom hinted and I checked online to learn this to be true.&lt;/p&gt;
&lt;p&gt;Lessons learned.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Gemini introduces import memory and chats feature</title>
    <link href="https://deepakness.com/raw/gemini-import-memory/" />
    <updated>2026-03-27T04:08:01Z</updated>
    <id>https://deepakness.com/raw/gemini-import-memory/</id>
    <summary>Just like Claude, now Gemini also lets you import memory as well as chats from ChatGPT, Claude, and other providers.</summary>
    <content type="html">&lt;p&gt;Earlier this month, &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/raw/import-memory-to-claude/&quot;&gt;Claude introduced&lt;/a&gt; the feature to import memory from other AI chatbots. Now, Gemini has also introduced a feature like that, as you see in the screenshot.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Import memory feature in Gemini&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/gemini-import-memory/gemini-import-memory.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;The process is simple, you just copy the provided prompt, paste into AI provider you&#39;re using, copy the response, put into Gemini, and save. And that&#39;s it, now Gemini knows everything that the prompt extracted from Claude, ChatGPT, or others.&lt;/p&gt;
&lt;p&gt;By the way, here&#39;s the huge prompt they provide:&lt;/p&gt;
&lt;pre class=&quot;language-markdown&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;You are helping me import context from one AI assistant to another. Your job is to go through our past conversations and sum up what you know about me.

In the output, please avoid using any first-person pronouns (I, my, me, mine) and any second-person pronouns (you, your, yours). Instead, refer to the individual you have learned about as &quot;the user&quot; or use neutral phrasing.

Preserve the user&#39;s words verbatim where possible, especially for instructions and preferences.

Categories (output in this order):
&lt;span class=&quot;token list punctuation&quot;&gt;1.&lt;/span&gt; Demographics Information: Preferred names, profession, education, and general residence.
&lt;span class=&quot;token list punctuation&quot;&gt;2.&lt;/span&gt; Interests &amp;amp; Preferences: Sustained, active engagements (not just owning an object or a one-time purchase).
&lt;span class=&quot;token list punctuation&quot;&gt;3.&lt;/span&gt; Relationships: Confirmed, sustained relationships.
&lt;span class=&quot;token list punctuation&quot;&gt;4.&lt;/span&gt; Dated Events, Projects &amp;amp; Plans: A log of significant, recent activities.
&lt;span class=&quot;token list punctuation&quot;&gt;5.&lt;/span&gt; Instructions: Rules I&#39;ve explicitly asked you to follow going forward, &quot;always do X&quot;, &quot;never do Y&quot;, and corrections to your behavior. Only include rules from stored memories, not from conversations.

Format:
Divide the content into the labeled section using the categories above. Try to include verbatim quotes from my prompts that justify each entry. Structure each entry using this format:
The user&#39;s name is &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;.
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Evidence: User said &quot;call me &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&quot;. Date: [YYYY-MM-DD].

Output:
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Format the final output summary as a text block.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I used this prompt on Claude and the response is extremely detailed, but contains a lot of personal information so I can&#39;t post here.&lt;/p&gt;
&lt;p&gt;And not just the memory, but it also lets you import chats from ChatGPT, Claude, or other providers, as you see the import chats feature in the screenshot above.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Import chats in Gemini&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/gemini-import-memory/gemini-import-chats.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;They also describe import chat process &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://support.google.com/gemini/answer/16868299&quot;&gt;in their documentation&lt;/a&gt;, as you see in the above screenshot. You can directly upload the ZIP file up to 5&amp;nbsp;GB in size.&lt;/p&gt;
&lt;p&gt;I think, this import chats feature is actually cool for people who are completely migrating to Gemini from ChatGPT, Claude, or other providers.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>LiteLLM Python library is compromised</title>
    <link href="https://deepakness.com/raw/litellm-is-compromised/" />
    <updated>2026-03-24T15:38:32Z</updated>
    <id>https://deepakness.com/raw/litellm-is-compromised/</id>
    <summary>LiteLLM v1.82.8 is compromised and it steals credentials and spreads to Kubernetes clusters.</summary>
    <content type="html">&lt;p&gt;Just learned that LiteLLM, &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/BerriAI/litellm&quot;&gt;a popular Python library&lt;/a&gt; that provides a unified interface to call multiple LLMs, has been compromised and is &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://futuresearch.ai/blog/litellm-pypi-supply-chain-attack/&quot;&gt;stealing sensitive info&lt;/a&gt; from users.&lt;/p&gt;
&lt;p&gt;The &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/hnykda/status/2036414330267193815&quot;&gt;post on X&lt;/a&gt; reads:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;LiteLLM HAS BEEN COMPROMISED, DO NOT UPDATE. We just discovered that LiteLLM pypi release 1.82.8. It has been compromised, it contains litellm_init.pth with base64 encoded instructions to send all the credentials it can find to remote server + self-replicate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It seems the entire GitHub repo is compromised as &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/BerriAI/litellm/issues/24512&quot;&gt;this issue #24512&lt;/a&gt; titled &quot;[Security]: CRITICAL: Malicious litellm_init.pth in litellm 1.82.8 — credential stealer&quot; was closed by the owner &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/BerriAI/litellm/issues/24512#event-23851126322&quot;&gt;saying &quot;not planned&quot;&lt;/a&gt;. It means the owner&#39;s GitHub account is hacked and the hacker marked this as solved. But good that it&#39;s &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/BerriAI/litellm/issues/24512#event-23853348625&quot;&gt;been reopened&lt;/a&gt;, and actively being discussed.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;What the LiteLLM malware does&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/litellm-is-compromised/litellm-malware.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;As explained in the &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://futuresearch.ai/blog/litellm-pypi-supply-chain-attack/&quot;&gt;FutureSearch article&lt;/a&gt;, the malware appears to be very sneaky and dangerous. So if you&#39;re affected with it, the current best option is to visit and browse through &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://github.com/BerriAI/litellm/issues/24512&quot;&gt;#24512&lt;/a&gt;, as the community is actively tracking the issue and trying to fix this.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;@krrishdholakia hacked by teampcp&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/litellm-is-compromised/teampcp-hacked.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Looks like the library was compromised after founder&#39;s GitHub profile was hacked by a group or whatever called &lt;code&gt;teampcp&lt;/code&gt;. Terrible (not in a good way).&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Peak design = AI Studio x Claude Code</title>
    <link href="https://deepakness.com/raw/aistudio-x-claude-code/" />
    <updated>2026-03-23T00:21:02Z</updated>
    <id>https://deepakness.com/raw/aistudio-x-claude-code/</id>
    <summary>Designing stuff in Google AI Studio and then giving the code to Claude Code to follow the design.</summary>
    <content type="html">&lt;p&gt;No matter what tool I have tried for great looking designs, Google&#39;s AI Studio always comes on top. Not to mention &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/DeepakNesss/status/2035672065219711390&quot;&gt;GPT-5.4 is the worst in design&lt;/a&gt;, Claude Code is slightly better, but Google AI Studio or even Stitch is the best.&lt;/p&gt;
&lt;p&gt;So... here is my current workflow for building websites:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get the design done and ready on Google AI Studio and download the code as ZIP (same design prompts work better on AI Studio)&lt;/li&gt;
&lt;li&gt;Initiate a project in a folder (currently, using Laravel for most websites, but Next.js or any other framework would work)&lt;/li&gt;
&lt;li&gt;Unzip the AI Studio design and put the folder in the main project root, rename it as &quot;inspiration&quot; or anything you like&lt;/li&gt;
&lt;li&gt;Ask Claude Code to take match the design as in the &quot;inspiration&quot; folder, but ask it follow the best practices of native Laravel, Astro, or whatever stack you&#39;re working in&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And done!&lt;/p&gt;
&lt;p&gt;See the Claude Code do the magic.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Scraping 250k+ URLs using Claude Code (via Telegram)</title>
    <link href="https://deepakness.com/raw/claude-code-250k-urls-scraping/" />
    <updated>2026-03-22T03:38:58Z</updated>
    <id>https://deepakness.com/raw/claude-code-250k-urls-scraping/</id>
    <summary>I completed a huge scraping project of 250,000+ URLs with the help of Claude Code, prompting it via Telegram.</summary>
    <content type="html">&lt;p&gt;This Saturday, I was about to leave for a movie with my friends and suddenly thought of experimenting with newly launched &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/trq212/status/2034761016320696565&quot;&gt;Claude Code channels&lt;/a&gt;. I set up Telegram to work with a Claude Code session, kept my laptop on, and then left for the movie, but when I was in the cab I started chatting about the scraping project and asked Claude to give me suggestions and ideas about how this will work.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Claude finalizing the scraping plan&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/claude-code-250k-urls-scraping/claude-making-scraping-plan.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;And by the time I reached, Claude was already setting up the project and ready to start the scraping process. I give the final confirmation and get busy watching the movie. When I checked my phone during the interval, it had sent me a bunch of messages and the process was still running. It had discovered 260k URLs to scrape and had already completed scraping 36k URLs as you see below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Claude sending scraping updates on Telegram&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/claude-code-250k-urls-scraping/claude-scraping-updates-telegram.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Whenever I messaged &quot;Progress?&quot; via Telegram, it quickly sent me a summary like above. The scraping process ran for ~8 hours, and it was still running when I returned home. And after a few hours, when the process was complete, it sent me this message confirming the completion.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scraping completed message from Claude&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/claude-code-250k-urls-scraping/scraping-complete.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Around ~10k URLs failed which is acceptable for a process this huge, but it had also failed to capture a few data points so I asked it to grab those as well and then the process again ran for ~3 hours. Finally, I had everything I needed. I, then, asked it to update the scraping script so we have the final polished data when we run the process the next time.&lt;/p&gt;
&lt;p&gt;All I would say is, thank you, Claude.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Cursor dodged the huge bullet about Kimi K2.5</title>
    <link href="https://deepakness.com/raw/cursor-kimi-k2-5/" />
    <updated>2026-03-20T22:45:59Z</updated>
    <id>https://deepakness.com/raw/cursor-kimi-k2-5/</id>
    <summary>People found out that Cursor&#39;s new Composer 2 model is pretrained on Moonshot&#39;s Kimi K2.5, and this could have become messy for Cursor.</summary>
    <content type="html">&lt;p&gt;Two days ago, Cursor &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/cursor_ai/status/2034668943676244133&quot;&gt;released the new Composer 2 model&lt;/a&gt; and the eval scores where were shown to be better than even Opus 4.6 (high). It was clear that the team did not train the model from the scratch, but Cursor did not mention anywhere which base model it is.&lt;/p&gt;
&lt;p&gt;But then &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/fynnso/status/2034706304875602030&quot;&gt;people found out&lt;/a&gt; it&#39;s the Kimi K2.5 model, and people started calling them out by mentioning that it&#39;s against Moonshot (the company behind Kimi models) terms of service to use the model for commercial purposes. This became interesting when several Moonshot folks started posting that Cursor did not come to them for licensing, as you see below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Moonshot Kimi deleted tweets about Cursor&#39;s Composer 2&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/cursor-kimi-k2-5/kimi-deleted-tweets.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;But then the most interesting part was, all the above tweets from Kimi you see were &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/love_deepseek/status/2034958589845283248&quot;&gt;suddenly deleted&lt;/a&gt;, and people started speculating – maybe &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/hancengiz/status/2034961923746267495&quot;&gt;Cursor paid Kimi&lt;/a&gt; for the license after posts went viral and more such theories.&lt;/p&gt;
&lt;p&gt;The real story came out when Lee Robinson from the Cursor team posted &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/leerob/status/2035035355364081694&quot;&gt;the clarification post&lt;/a&gt;. Initially, he did not mention the name Kimi K2.5 in the main post but then when people were calling them out, &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/leerob/status/2035050444347600936&quot;&gt;he admits&lt;/a&gt; that it was the Kimi K2.5 model, and quotes &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/Kimi_Moonshot/status/2035074972943831491&quot;&gt;this post from Kimi AI&lt;/a&gt; where they mention this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: Cursor accesses Kimi-k2.5 via @FireworksAI_HQ&#39; hosted RL and inference platform as part of an authorized commercial partnership.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So the whole story in simple terms is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cursor licenses the Kimi K2.5 model via inference partner FireworksAI (not via Kimi)&lt;/li&gt;
&lt;li&gt;Heavily pretrains the model and releases as Composer 2&lt;/li&gt;
&lt;li&gt;People find out that the underlying model is Kimi K2.5&lt;/li&gt;
&lt;li&gt;Kimi folks didn&#39;t know this, so they post on X&lt;/li&gt;
&lt;li&gt;Cursor reaches out to them privately explaining everything&lt;/li&gt;
&lt;li&gt;Kimi folks delete the tweet, and post the clarification&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Basically, no one was in the wrong here, and it&#39;s just an example of miscommunication, especially from Cursor&#39;s side. This could have gone very wrong for Cursor, but I&#39;m glad the situation is now under control.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Better way to implement mailto: links</title>
    <link href="https://deepakness.com/raw/mailto-links/" />
    <updated>2026-03-20T04:34:25Z</updated>
    <id>https://deepakness.com/raw/mailto-links/</id>
    <summary>I finally found better ways to implemented mailto: links, without compromising with the user experience.</summary>
    <content type="html">&lt;p&gt;Honestly, I don&#39;t like &lt;code&gt;mailto:&lt;/code&gt; links for myself because I use webmail and clicking on these links opens the default email app on my computer. However, I still had an email icon in the footer of &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/&quot;&gt;my personal site&lt;/a&gt;, but I changed that click on copy instead of a &lt;code&gt;mailto:&lt;/code&gt; link after coming across &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/martyamark/status/2033879722166263910&quot;&gt;this post&lt;/a&gt;. Basically, clicking on the envelope icon in the footer copied the email to the clipboard, and then it briefly showed a green checkmark.&lt;/p&gt;
&lt;p&gt;I thought this was provided a good user-experience and posted about this on my socials, &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://www.threads.com/@deepakness/post/DWC8r6wFU5c&quot;&gt;especially on Threads&lt;/a&gt;. But almost all the feedback where negative, suggesting that this is a bad idea, users won&#39;t know what just happened, as you see in the screenshot below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Better mailto: links&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/mailto-links/better-mailto.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;And they were all correct, it wasn&#39;t very clear about what just happened. I, then, thought about it and implemented the email thing differently. As you see in the screenshot below, started showing the full email in text and clicking on it copied the email to users&#39; clipboard.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Screenshot showing full email in text and clicking on it copies&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/mailto-links/full-email-copied.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;But I still wasn&#39;t satisfied with it so posted about this again on X, and then received &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/iannuttall/status/2034718448844951757&quot;&gt;this interesting recommendation&lt;/a&gt; about using the &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://mailgo.dev/docs/examples&quot;&gt;mailgo tool&lt;/a&gt; which is basically a new concept for &lt;code&gt;mailto&lt;/code&gt; and &lt;code&gt;tel&lt;/code&gt; links.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Screenshot showing how mailgo works&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/mailto-links/mailgo-screenshot.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can see in the screenshot that when I clicked on the &lt;code&gt;mailto:&lt;/code&gt; link, it showed me a bunch of options instead of just opening the default email app or copying the email to the clipboard directly. I tried clicking on &lt;strong&gt;Open in Gmail&lt;/strong&gt;, &lt;strong&gt;copy&lt;/strong&gt;, etc. options and they all work as expected.&lt;/p&gt;
&lt;p&gt;But the problem is, the &lt;strong&gt;mailgo project&lt;/strong&gt; isn&#39;t maintained anymore, and there&#39;s no point in adding a dead dependency to my project. So... I built this from scratch, and it was very simple to do so.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The current solution I built from scratch&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/mailto-links/current-solution.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here&#39;s how this is implemented, the one you see in the screenshot above:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email-wrap&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value javascript language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parentElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;classList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toggle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;open&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- envelope icon --&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value javascript language-javascript&quot;&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clipboard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;me@deepakness.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Email copied!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Copy me@deepakness.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      Copy me@deepakness.com
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://mail.google.com/mail/?view=cm&amp;amp;to=me@deepakness.com&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      Open in Gmail
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mailto:me@deepakness.com&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Open default client&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And a tiny script to close the popup when clicking outside or pressing Escape:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;closest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#email-wrap&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;email-wrap&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;classList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;open&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you would need some basic CSS to make it look good.&lt;/p&gt;
&lt;p&gt;That&#39;s it.&lt;/p&gt;
&lt;p&gt;This simple implementation works well, until I find a better solution for this.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>arXiv now has a MCP server</title>
    <link href="https://deepakness.com/raw/arxiv-mcp/" />
    <updated>2026-03-19T03:32:15Z</updated>
    <id>https://deepakness.com/raw/arxiv-mcp/</id>
    <summary>Connect the arXiv MCP server to AI applications, agents, and workflows to search papers, analyze, explore, and synthesize research insights.</summary>
    <content type="html">&lt;p&gt;arXiv &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/askalphaxiv/status/2034003206217601375&quot;&gt;has a new MCP server&lt;/a&gt; that you can connect to your AI applications, agents, and workflows to search papers, analyze PDFs, explore codebases, and synthesize research insights. From their docs, below are the &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://www.alphaxiv.org/docs/mcp&quot;&gt;available tools in the MCP&lt;/a&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Embedding similarity search&lt;/li&gt;
&lt;li&gt;Full-text papers search&lt;/li&gt;
&lt;li&gt;Agentic paper retrieval&lt;/li&gt;
&lt;li&gt;Get paper content&lt;/li&gt;
&lt;li&gt;Answer PDF queries&lt;/li&gt;
&lt;li&gt;Read files from paper&#39;s GitHub repo&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I think, this can be important for researchers and engineers, as their AI agent will now have access to all relevant research papers. Earlier, agents could search for papers via search engines, but I guess that had lots of errors and sometimes even returned broken URLs. And that wouldn&#39;t be the case with the MCP server.&lt;/p&gt;
&lt;p&gt;I installed this to Claude Code by running the following command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;claude mcp &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--transport&lt;/span&gt; http alphaxiv https://api.alphaxiv.org/mcp/v1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And I had to authenticate by running the &lt;code&gt;/mcp&lt;/code&gt; command inside Claude, that looked like the below screenshot:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Installing arXiv new MCP server to Claude Code&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/arxiv-mcp/arxiv-mcp-install.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;And then it was working as expected.&lt;/p&gt;
&lt;p&gt;I&#39;m still exploring this, and will share more if I learn something noteworthy.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>OpenAI launches GPT-5.4 mini and nano</title>
    <link href="https://deepakness.com/raw/gpt-5-4-mini-nano/" />
    <updated>2026-03-17T23:56:54Z</updated>
    <id>https://deepakness.com/raw/gpt-5-4-mini-nano/</id>
    <summary>The new GPT-5.4 mini and nano models are cheaper than the larger GPT-5.4 models, but costlier than previous mini and nano models.</summary>
    <content type="html">&lt;p&gt;After 2 weeks of the &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/raw/gpt-5-4/&quot;&gt;GPT-5.4 launch&lt;/a&gt;, OpenAI &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/OpenAIDevs/status/2033953815834333608&quot;&gt;just launched&lt;/a&gt; the &lt;code&gt;mini&lt;/code&gt; and &lt;code&gt;nano&lt;/code&gt; versions of GPT-5.4, and it&#39;s already &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://openai.com/index/introducing-gpt-5-4-mini-and-nano/&quot;&gt;available in ChatGPT, Codex, and via the API&lt;/a&gt;. And as self-reported by OpenAI, these GPT-5.4 mini and nano models are very close to the larger GPT-5.4 model.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Evals - GPT-5.4 vs mini vs nano&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/gpt-5-4-mini-nano/gpt-5-4-mini-nano-evals.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;I was reading Simon&#39;s post about the new models, he ran some experiments about describing images using the &lt;code&gt;GPT-5.4 nano&lt;/code&gt; model and gives this estimate:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[...] describing every single photo in my 76,000 photo collection would cost around $52.44.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And from my tests as well, the models are fairly capable for simple repetitive tasks. But as compared to previous GPT-5 mini and nano models, they are costlier. You can check out the below table for comparison:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input Price (per 1M tokens)&lt;/th&gt;
&lt;th&gt;Output Price (per 1M tokens)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5 mini&lt;/td&gt;
&lt;td&gt;$0.25&lt;/td&gt;
&lt;td&gt;$2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5 nano&lt;/td&gt;
&lt;td&gt;$0.05&lt;/td&gt;
&lt;td&gt;$0.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GPT-5.4 mini&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0.75  &lt;code&gt;3x costlier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$4.50  &lt;code&gt;2.25x costlier&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GPT-5.4 nano&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0.20  &lt;code&gt;4x costlier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$2.25  &lt;code&gt;5.6x costlier&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;But not to mention that the new mini and nano models are far more capable than the previous mini and nano models.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Just ask and Codex can now spin up subagents</title>
    <link href="https://deepakness.com/raw/codex-subagents/" />
    <updated>2026-03-17T02:43:35Z</updated>
    <id>https://deepakness.com/raw/codex-subagents/</id>
    <summary>OpenAI just launched subagents feature in Codex and it&#39;s awesome, and faster.</summary>
    <content type="html">&lt;p&gt;I tried the OpenAI&#39;s &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://x.com/OpenAIDevs/status/2033636701848174967&quot;&gt;newly launched feature&lt;/a&gt; subagents for Codex and it&#39;s awesome. I tried it via the Codex app on macOS, and the UI looks good as well.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A screenshot of multiple subagents working in Codex app&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/codex-subagents/codex-subagents-working.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Although, spawning subagents consumes much more tokens as compared to a single agent for the same task, it does work faster as multiple agents are working on different asked tasks in parallel. By the way, the agent only spawns subagent(s) when you specifically ask it to. Codex docs &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://developers.openai.com/codex/subagents&quot;&gt;have much more info&lt;/a&gt; about this and other related things.&lt;/p&gt;
&lt;p&gt;I also learned from &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://simonwillison.net/2026/Mar/16/codex-subagents/&quot;&gt;the Simon&#39;s post&lt;/a&gt; that Codex also lets you define and use custom agents:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Codex also lets you define custom agents as TOML files in ~/.codex/agents/. These can have custom instructions and be assigned to use specific models - including gpt-5.3-codex-spark if you want some raw speed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For your info, the subagents feature is only new to Codex as it&#39;s already available in Claude Code, Gemini, Cursor, OpenCode, etc.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Pi powered via the Wi-Fi Router</title>
    <link href="https://deepakness.com/raw/router-powers-pi/" />
    <updated>2026-03-15T00:58:16Z</updated>
    <id>https://deepakness.com/raw/router-powers-pi/</id>
    <summary>Powering my Raspberry Pi 4B directly via the Wifi Router using USB port.</summary>
    <content type="html">&lt;p&gt;&lt;img alt=&quot;Wifi Router powers Raspberry Pi&quot; decoding=&quot;async&quot; src=&quot;https://assets.deepakness.com/raw/router-powers-pi/router-powering-pi.jpg&quot;&gt;&lt;/p&gt;
&lt;p&gt;I was using a power adapter to power my Raspberry Pi 4B device, but then I noticed a USB port on my Wi-Fi router and then connected the Pi directly to it. And it&#39;s &lt;a rel=&quot;noreferrer&quot; target=&quot;_blank&quot; href=&quot;https://deepakness.com/blog/freshrss-on-pi/&quot;&gt;working as expected&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I will also soon connect the Pi via a LAN cable to the wifi router for faster internet.&lt;/p&gt;
</content>
  </entry>
</feed>
