{"authors":[{"avatar":"https://philliant.com/img/spongebob.jpg","name":"philip mathew hern","url":"https://linkedin.com/in/philipmathewhern"}],"description":"notes, projects, and writing by philip mathew hern","feed_url":"https://philliant.com/feed.json","home_page_url":"https://philliant.com/","items":[{"content_html":"\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethe future of data engineering workflows with ai is about moving from manual coding to intelligent orchestration. ai agents will handle boilerplate code, pipeline generation, and data quality checks, allowing data engineers to focus on architecture, governance, and business value.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eaudience: data engineers, analytics engineers, data architects, and technical leaders.\u003c/li\u003e\n\u003cli\u003eprerequisites: an understanding of modern data stack concepts and basic ai principles.\u003c/li\u003e\n\u003cli\u003ewhen to use this guide: when planning your data strategy and evaluating how to integrate ai into your engineering practices.\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhy this matters\n    \u003cdiv id=\"why-this-matters\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#why-this-matters\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethe volume and complexity of data are growing faster than engineering teams can scale. relying solely on manual workflows leads to bottlenecks, technical debt, and delayed insights. embracing ai is not just about efficiency, it is a strategic imperative to remain competitive.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003estep-by-step\n    \u003cdiv id=\"step-by-step\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#step-by-step\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003e1) define the starting point\n    \u003cdiv id=\"1-define-the-starting-point\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#1-define-the-starting-point\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003etraditionally, data engineering has been a highly manual discipline. engineers spend countless hours writing sql, configuring orchestrators like airflow, and debugging failed pipelines. this approach is brittle and scales poorly as the organization grows.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003e2) apply the change\n    \u003cdiv id=\"2-apply-the-change\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#2-apply-the-change\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethe integration of ai changes this paradigm. large language models can now generate complex sql queries, translate between dialects, and even suggest optimal data models based on source schemas. ai agents can monitor pipeline health, automatically retry transient failures, and alert engineers only when human intervention is necessary. this shift transforms the engineer from a coder into a system architect.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003e3) validate the result\n    \u003cdiv id=\"3-validate-the-result\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#3-validate-the-result\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethe impact of this transformation is measurable. development cycles shorten, data quality improves through automated testing, and the overall reliability of the platform increases. engineers spend less time firefighting and more time building scalable, resilient architectures that drive business decisions.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat is the most important caveat?\n    \u003cdiv id=\"what-is-the-most-important-caveat\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-is-the-most-important-caveat\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eai is a tool, not a replacement for fundamental engineering principles. you still need a strong understanding of data modeling, governance, and security to build a robust platform.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat should i do first?\n    \u003cdiv id=\"what-should-i-do-first\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-should-i-do-first\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003estart by identifying the most repetitive tasks in your workflow, such as writing documentation or basic transformations. experiment with ai tools to automate these specific areas before attempting to overhaul your entire architecture.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://a16z.com/2020/10/15/the-emerging-architectures-for-modern-data-infrastructure/\"  target=\"_blank\" rel=\"noreferrer\"\u003ethe modern data stack\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260318-from-prototype-to-production-ai/\" \u003efrom prototype to production ai\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-04-03T00:44:14Z","date_published":"2026-04-03T00:44:14Z","id":"https://philliant.com/posts/20260402-the-future-of-data-engineering-workflows-with-ai/","summary":"data engineering is evolving rapidly with the integration of artificial intelligence. i will explore how ai agents, large language models, and automated workflows are transforming the way we build, maintain, and scale data platforms.","tags":["data engineering","ai","workflows","future"],"title":"the future of data engineering workflows with ai","url":"https://philliant.com/posts/20260402-the-future-of-data-engineering-workflows-with-ai/"},{"content_html":"\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ewriting dbt tests and documentation is often the most neglected part of data engineering. i use cursor and custom ai agents to automate this process by reading my sql models, inferring the business logic, and generating the corresponding yaml files. this ensures high-quality data pipelines without the manual overhead.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eaudience: data engineers, analytics engineers, and developers using dbt\u003c/li\u003e\n\u003cli\u003eprerequisites: basic knowledge of dbt, sql, and cursor\u003c/li\u003e\n\u003cli\u003ewhen to use this guide: when you want to scale your data engineering practices and reduce the time spent on writing boilerplate yaml\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhy this matters\n    \u003cdiv id=\"why-this-matters\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#why-this-matters\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003edocumentation and testing are critical for data trust, but they are tedious to write manually. when these steps are skipped, data quality suffers and debugging becomes a nightmare. by automating this with ai, you get the benefits of rigorous testing and clear documentation while freeing up your time for higher-value architectural work.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003estep-by-step\n    \u003cdiv id=\"step-by-step\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#step-by-step\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003e1) define the starting point\n    \u003cdiv id=\"1-define-the-starting-point\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#1-define-the-starting-point\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003emost data engineers start with a raw sql model and a blank slate for their \u003ccode\u003eschema.yml\u003c/code\u003e file. the traditional approach requires manually typing out every column name, description, and test. this is prone to human error and inconsistency, plus almost always falls out of sync with current models with the first change.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003e2) apply the change\n    \u003cdiv id=\"2-apply-the-change\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#2-apply-the-change\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ei use cursor to bridge this gap. by creating specific ai rules and skills, i can highlight a dbt model and ask the agent to generate the documentation. the agent reads the sql, understands the joins and transformations, and produces a complete yaml file with standard tests like \u003ccode\u003enot_null\u003c/code\u003e and \u003ccode\u003eunique\u003c/code\u003e. it can even infer complex relationships and suggest custom tests based on the data domain.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003e3) validate the result\n    \u003cdiv id=\"3-validate-the-result\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#3-validate-the-result\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eonce the ai generates the yaml, i review it for accuracy. i then run \u003ccode\u003edbt test\u003c/code\u003e and \u003ccode\u003edbt docs generate\u003c/code\u003e to ensure everything compiles correctly. the ai rarely makes syntax errors, so the validation step is mostly about confirming the business logic aligns with the documentation.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat is the most important caveat?\n    \u003cdiv id=\"what-is-the-most-important-caveat\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-is-the-most-important-caveat\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eyou must still review the generated output. ai is excellent at scaffolding and inferring patterns, but it does not possess the full business context that you do.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat should i do first?\n    \u003cdiv id=\"what-should-i-do-first\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-should-i-do-first\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003estart by creating a simple cursor skill that defines your team\u0026rsquo;s standards for dbt documentation. feed it a few examples of your best \u003ccode\u003eschema.yml\u003c/code\u003e files so it learns your preferred style.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt documentation\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260313-my-cursor-setup/\" \u003emy cursor setup\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-04-03T00:44:14Z","date_published":"2026-04-03T00:44:14Z","id":"https://philliant.com/posts/20260402-how-i-use-cursor-and-ai-agents-to-write-dbt-tests-and-documentation/","summary":"writing dbt tests and documentation is often the most neglected part of data engineering. i will show you how i use cursor and ai agents to automate this process, ensuring high-quality data pipelines without the manual overhead.","tags":["dbt","cursor","ai","data engineering"],"title":"how i use cursor and ai agents to write dbt tests and documentation","url":"https://philliant.com/posts/20260402-how-i-use-cursor-and-ai-agents-to-write-dbt-tests-and-documentation/"},{"content_html":"\n\u003ch2 class=\"relative group\"\u003ethe value of early adoption\n    \u003cdiv id=\"the-value-of-early-adoption\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-value-of-early-adoption\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei have always found a unique kind of energy in being an early adopter. when a new tool emerges, especially something as transformative as cursor and artificial intelligence, diving in headfirst is not just about personal efficiency. it is about understanding the landscape before the map is fully drawn. by spending the hours required to become a high-level user, i build a deep familiarity with the edges of what the technology can do.\u003c/p\u003e\n\u003cp\u003ethis mastery translates directly into value for my colleagues. when you understand the high-level nuance of a complex tool, you naturally become the point person for your team. people have onboarding questions, they hit roadblocks, and they need someone who has already navigated those early frustrations. being that resource is incredibly rewarding. it shifts my role from an individual contributor to a multiplier, helping the entire team elevate their workflow and avoid the pitfalls i have already solved.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ethe responsibility to share\n    \u003cdiv id=\"the-responsibility-to-share\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-responsibility-to-share\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethis dynamic reminds me of a principle i have heard often over the years regarding the importance of using your voice and your platform to share. this is exactly why i started this website. i wanted a dedicated space to share my voice, my knowledge, my opinions, my experience, and the solutions i have discovered along the way.\u003c/p\u003e\n\u003cp\u003ewhen you hold onto knowledge, its impact is limited to your own output. when you share it, the impact scales infinitely. writing about these tools, documenting my workflows, and answering the nuanced questions my colleagues ask are all extensions of the same core belief. knowledge is meant to be distributed.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003estepping into mentorship\n    \u003cdiv id=\"stepping-into-mentorship\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#stepping-into-mentorship\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei have reached a point of mastery and experience where the natural next step for me is to mentor others and deliberately increase my visibility and presence. it is no longer enough to simply be good at what i do behind the scenes. the real work now is in lifting others up.\u003c/p\u003e\n\u003cp\u003ein fact, i am starting to feel the weight of this realization. it feels almost selfish not to share what i have learned. when you spend years honing a craft or mastering a paradigm-shifting tool like ai-assisted development, you accumulate a wealth of invisible context. keeping that context locked away serves no one. stepping into a mentorship role, both directly with my colleagues and publicly through this platform, is how i honor the effort it took to gain that experience in the first place.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003elooking forward\n    \u003cdiv id=\"looking-forward\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#looking-forward\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003emy goal is to continue exploring the bleeding edge of these tools, but with a renewed focus on how i can translate those discoveries into accessible guidance for others. whether it is through answering a quick onboarding question about cursor, writing a detailed guide on this site, or simply being a sounding board for a colleague, the objective remains the same. i want to use my experience to make the path easier for those who follow.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efurther reading\n    \u003cdiv id=\"further-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#further-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://docs.cursor.com/\"  target=\"_blank\" rel=\"noreferrer\"\u003ecursor documentation\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated on this site\n    \u003cdiv id=\"related-on-this-site\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-on-this-site\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/\" \u003epost title\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-04-02T12:11:05Z","date_published":"2026-04-02T12:11:05Z","id":"https://philliant.com/posts/20260402-sharing-is-caring/","summary":"mastering emerging tools like cursor and ai is only the first step. true value comes from becoming a point person for your team, sharing your voice, and mentoring others through the nuances of adoption.","tags":["mentorship","ai","cursor","early adoption","leadership"],"title":"sharing is caring","url":"https://philliant.com/posts/20260402-sharing-is-caring/"},{"content_html":"\n\u003ch2 class=\"relative group\"\u003ethesis\n    \u003cdiv id=\"thesis\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#thesis\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei keep pondering lately, what are we actually defending when we say \u0026ldquo;ai art is not real art\u0026rdquo;?\u003c/p\u003e\n\u003cp\u003ei do not have a final position yet. i am writing this to think in public, not to close the debate.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003econtext\n    \u003cdiv id=\"context\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#context\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ewhile driving on a family vacation, i asked my wife to fulfill her duty as the passenger and dj some motown bangers. she searched on spotify and found something that seemed to fit the bill. most of the songs were recognizable, memories from my childhood, riding in the backseat listening to my parents\u0026rsquo; favorites. however, the first song on the playlist was by an artist called the \u003cstrong\u003e19s soulers\u003c/strong\u003e, which was an artist i did not recognize. this was a user created playlist so not everything might fit perfectly into the motown mold i was asking for, and that was ok. the song started and it was \u003cstrong\u003eSOOO\u003c/strong\u003e good. \u003cstrong\u003eTOO\u003c/strong\u003e good. i had my suspicions, but the music caught me so hard that i completely forgot. i asked my boys in the back seat to look up the artist and they did not even search and just responded \u0026ldquo;AI DAD - IT IS AI\u0026rdquo;. i felt so many conflicting emotions, including one of pride that my boys could tell the difference and they have some defense against being fooled.\u003c/p\u003e\n\u003cp\u003ethe conversation around ai-generated images and music feels hotter every week, especially when a new ai music act gets attention or a contract. the reaction is often immediate and predictable outrage, fear, dismissal, and arguments about stolen style.\u003c/p\u003e\n\u003cp\u003eat the same time, many of us use ai to help write code, review pull requests, or shape architecture notes without the same emotional response. that contrast is interesting to me.\u003c/p\u003e\n\u003cp\u003eif i call code a craft, and sometimes an art form, then why does ai help feel acceptable there for so many people, but unacceptable when the ai helps write song lyrics? and if code can be expressive, why is the outrage concentrated in painting, illustration, and music.\u003c/p\u003e\n\u003cp\u003emy code has my fingerprints all over it, just as much as this website and the way i speak and write. it defintely qualifies as expressive. i make stylistic, logic, function, etc. choices that suit my style. how is this different from writing a book? but if you asked which one is acceptable to use ai and which one is not, i could guess your answer 99% of the time.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eargument\n    \u003cdiv id=\"argument\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#argument\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei see a few possible reasons, and none of them feel complete on their own:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003evisual art and music are tied to identity in a very direct way\u003c/li\u003e\n\u003cli\u003eaudiences often connect to the \u0026ldquo;maker story\u0026rdquo;, not only the artifact\u003c/li\u003e\n\u003cli\u003ecreative labor markets in those fields already felt fragile before ai\u003c/li\u003e\n\u003cli\u003esoftware teams have normalized tool-assisted output for decades\u003c/li\u003e\n\u003cli\u003ecode is often judged by function first, while art is judged by intention and feeling\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003estill, even with those differences, i cannot shake the inconsistency.\u003c/p\u003e\n\u003cp\u003ewhen i use ai in code, i still feel like the author because i set constraints, reject bad output, and own the result. i do not think that is very different from guiding a visual generator, editing outputs, and curating a final piece. maybe the difference is only social permission, not creative mechanics.\u003c/p\u003e\n\u003cp\u003ethis question also links to my concern about ownership in \u003ca href=\"/posts/20260326-the-danger-of-trusting-the-ai-agent/\" \u003ethe danger of trusting the ai agent\u003c/a\u003e, where speed is useful but responsibility still has to stay human.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003etension or counterpoint\n    \u003cdiv id=\"tension-or-counterpoint\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#tension-or-counterpoint\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethere is also a strong counterpoint i take seriously: in code, wrong answers fail in visible ways. tests fail, services break, users complain, and teams can trace accountability. in art, value is less binary, and that makes authorship feel more central and more vulnerable.\u003c/p\u003e\n\u003cp\u003eanother counterpoint is economic, not philosophical. people may not be reacting to \u0026ldquo;is this art\u0026rdquo; at all. they may be reacting to \u0026ldquo;will this replace my livelihood\u0026rdquo;.\u003c/p\u003e\n\u003cp\u003eboth of those points feel real to me.\u003c/p\u003e\n\u003cp\u003eand i think the later point is one worth exploring because the wide-spread availability of ai has \u0026ldquo;democratized\u0026rdquo; creativity, technical endeavors, etc. for people who might have great ideas, but not the musical or technical skill to carry out the plan. well, now they do. and that instant competition that was not present before can certainly feel intimidating and encroaching.\u003c/p\u003e\n\u003cp\u003ei am currently mostly pro-ai, but with caution. we should have caution regarding how the models are being trained (and on what data) and regulated. we should exercise caution surrounding \u003cem\u003ewho\u003c/em\u003e is doing the regulating, as well. ai is a powerful assistant, and as we all know from spiderman, with great power comes great responsibility.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eclosing\n    \u003cdiv id=\"closing\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#closing\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei am left with questions, not conclusions.\u003c/p\u003e\n\u003cp\u003emaybe we value human touch most where we believe the human story is the product. maybe we accept ai more where we believe the product is utility. maybe those boundaries are changing and we are all reacting in real time.\u003c/p\u003e\n\u003cp\u003efor now, i am trying to keep the question open\u0026hellip;..when ai is part of the process, what still makes something mine, yours, or ours?\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efurther reading\n    \u003cdiv id=\"further-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#further-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.copyright.gov/ai/\"  target=\"_blank\" rel=\"noreferrer\"\u003ecopyright and artificial intelligence, u.s. copyright office\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Generative_art\"  target=\"_blank\" rel=\"noreferrer\"\u003egenerative art\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Computer_music\"  target=\"_blank\" rel=\"noreferrer\"\u003ecomputer music\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated on this site\n    \u003cdiv id=\"related-on-this-site\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-on-this-site\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260318-from-prototype-to-production-ai/\" \u003efrom prototype to production: my early adopter view of ai\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260326-the-danger-of-trusting-the-ai-agent/\" \u003ethe danger of trusting the ai agent\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/series/commentary/\" \u003ecommentary series\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-30T23:38:30Z","date_published":"2026-03-30T23:38:30Z","id":"https://philliant.com/posts/20260330-what-is-art/","summary":"i do not have a clean answer. i am trying to understand why ai-assisted code can feel normal while ai-assisted painting or music can trigger backlash, and what that says about authorship, labor, and value.","tags":["ai","art","creativity","music","code","authorship"],"title":"what is art?","url":"https://philliant.com/posts/20260330-what-is-art/"},{"content_html":"\u003cp\u003ewe all know testing is valuable, but almost all dbt projects still underinvest in it. i am guilty of this, shipping the model, promising i will add tests later, then moving on to the next urgent request.\u003c/p\u003e\n\u003cp\u003ethat pattern feels fast in the moment, but it is expensive over time. dbt tests are one of the easiest ways to protect trust in your data, and the setup cost is usually smaller than people expect.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003edbt tests are assertions about your data that run inside your transformation workflow. they verify assumptions like uniqueness, non-null keys, valid categorical values, and referential integrity. when a test fails, dbt surfaces the exact failing records so you can debug quickly. if you are new to the feature, start with the official \u003ca href=\"https://docs.getdbt.com/docs/build/data-tests\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt data tests documentation\u003c/a\u003e and add a few high-signal tests to your most consumed models first.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eanalytics engineers who already build dbt models but still rely on manual spot checks\u003c/li\u003e\n\u003cli\u003edata teams that have recurring data quality incidents in dashboards or reports\u003c/li\u003e\n\u003cli\u003eanyone who wants a practical starting point instead of a perfect testing framework\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhy this matters\n    \u003cdiv id=\"why-this-matters\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#why-this-matters\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethe cost of bad data is usually delayed, not immediate. a broken metric can sit in production for days before someone notices, and by then that number has already been used in a deck, decision, or leadership update.\u003c/p\u003e\n\u003cp\u003ethe frustrating part is that most of these issues are predictable. duplicate primary keys, null foreign keys, unexpected status values, and invalid date ranges are all common failures. dbt tests can catch these early, near the model that introduced the issue.\u003c/p\u003e\n\u003cp\u003ei also think testing helps teams move faster, not slower. when tests are in place, i can refactor a model with more confidence because i have a safety net. without tests, every change feels risky and review cycles become slower because everyone is relying on intuition.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003estep-by-step\n    \u003cdiv id=\"step-by-step\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#step-by-step\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003e1) define the starting point\n    \u003cdiv id=\"1-define-the-starting-point\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#1-define-the-starting-point\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003epick one model that is heavily consumed, for example an order fact table or a customer dimension. identify three assumptions that must always be true:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ethe model key is unique\u003c/li\u003e\n\u003cli\u003eimportant keys are never null\u003c/li\u003e\n\u003cli\u003estatus fields only contain known values\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ethen encode those assumptions directly in your yml.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003e2) apply the change\n    \u003cdiv id=\"2-apply-the-change\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#2-apply-the-change\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003estart with generic tests in your schema file.\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"m\"\u003e2\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"nt\"\u003emodels\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003efct_orders\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003ecolumns\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eorder_id\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003etests\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e          \u003c/span\u003e- \u003cspan class=\"l\"\u003enot_null\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e          \u003c/span\u003e- \u003cspan class=\"l\"\u003eunique\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003ecustomer_id\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003etests\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e          \u003c/span\u003e- \u003cspan class=\"l\"\u003enot_null\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e          \u003c/span\u003e- \u003cspan class=\"nt\"\u003erelationships\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e              \u003c/span\u003e\u003cspan class=\"nt\"\u003eto\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eref(\u0026#39;dim_customers\u0026#39;)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e              \u003c/span\u003e\u003cspan class=\"nt\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003ecustomer_id\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eorder_status\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003etests\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e          \u003c/span\u003e- \u003cspan class=\"nt\"\u003eaccepted_values\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e              \u003c/span\u003e\u003cspan class=\"nt\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;placed\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;shipped\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;cancelled\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;returned\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003ethis single block gives you strong baseline coverage:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003enot_null\u003c/code\u003e protects required fields\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eunique\u003c/code\u003e protects grain\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003erelationships\u003c/code\u003e protects joins and referential integrity\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eaccepted_values\u003c/code\u003e protects enum-like business states\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003enext, add one singular test for a business rule that generic tests cannot express cleanly.\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e-- tests/orders_non_negative_amount.sql\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eSELECT\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003eorder_id\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003eorder_amount\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eFROM\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"err\"\u003e{{\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eref\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;fct_orders\u0026#39;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"err\"\u003e}}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eWHERE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eorder_amount\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003ethis test fails only when the query returns rows. singular tests are ideal for custom rules like range checks, cross-column logic, and impossible combinations.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003e3) validate the result\n    \u003cdiv id=\"3-validate-the-result\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#3-validate-the-result\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003erun tests in a tight loop while you are developing:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003edbt \u003cspan class=\"nb\"\u003etest\u003c/span\u003e --select fct_orders\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003efor a broader gate in CI or before merging, run:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003edbt build --select fct_orders+\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003e\u003ccode\u003edbt build\u003c/code\u003e runs models and tests together, which is useful when you want to validate both transformation logic and data quality in one pass. the \u003ccode\u003e+\u003c/code\u003e after the model name tells dbt to also run any downstream models according to the dag to make sure dependencies also pass.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ea practical prioritization rule\n    \u003cdiv id=\"a-practical-prioritization-rule\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#a-practical-prioritization-rule\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ewhen time is limited, i prioritize tests in this order:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003ekey integrity on high-consumption models (\u003ccode\u003eunique\u003c/code\u003e plus \u003ccode\u003enot_null\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003eforeign key integrity (\u003ccode\u003erelationships\u003c/code\u003e) on joins that power dashboards\u003c/li\u003e\n\u003cli\u003econtrolled fields (\u003ccode\u003eaccepted_values\u003c/code\u003e) where business logic depends on a finite set of values\u003c/li\u003e\n\u003cli\u003eone custom singular test for the highest-risk metric or business rule\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003ethis sequence catches a large share of real incidents with minimal setup.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat should i test first in a mature project with little coverage?\n    \u003cdiv id=\"what-should-i-test-first-in-a-mature-project-with-little-coverage\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-should-i-test-first-in-a-mature-project-with-little-coverage\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003estart where breakage is most expensive, not where modeling is most elegant. choose one or two heavily consumed models and add key integrity plus relationships first. then add one singular test for the business rule that has caused the most historical pain.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003edo dbt tests slow down delivery?\n    \u003cdiv id=\"do-dbt-tests-slow-down-delivery\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#do-dbt-tests-slow-down-delivery\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethey add some upfront work, but they usually reduce cycle time later. test failures are cheaper during development than after release, and tests make refactors safer because you can verify assumptions continuously instead of rediscovering issues in production.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/docs/build/data-tests\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt docs, data tests\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/reference/resource-properties/data-tests\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt docs, test properties\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/best-practices/writing-custom-generic-tests\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt docs, writing custom generic data tests\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260330-dbt-docs/\" \u003edbt docs\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/series/dbt/\" \u003edbt series\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-30T23:34:36Z","date_published":"2026-03-30T23:34:36Z","id":"https://philliant.com/posts/20260330-dbt-tests/","summary":"dbt tests are one of the highest-leverage habits in analytics engineering, but they are often underfunded in real projects. this post explains how i use generic and singular tests, what to prioritize first, and a few practical examples you can copy today.","tags":["dbt","testing","data-quality","analytics-engineering","data-engineering"],"title":"dbt tests","url":"https://philliant.com/posts/20260330-dbt-tests/"},{"content_html":"\u003cp\u003emost data engineers i know will spend hours getting a model right, then skip the one step that makes it discoverable to everyone else. dbt docs are that step, and they are worth the effort.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003edbt docs is a built-in feature that generates a browsable website from your dbt project. it pulls descriptions from your yml files, renders a searchable model catalog, and draws a lineage graph showing how every model connects. running \u003ccode\u003edbt docs generate\u003c/code\u003e followed by \u003ccode\u003edbt docs serve\u003c/code\u003e gives you a local site instantly. the real payoff is that teammates who never open your sql files can still understand what each model does, what columns it exposes, and where the data comes from. this is especially useful to downstream consumers of your objects because they can see the exact format of the object, including column names and data types, etc.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003edata engineers who use dbt but skip writing descriptions\u003c/li\u003e\n\u003cli\u003eanalysts, product managers, or business users who need to understand available data without reading sql\u003c/li\u003e\n\u003cli\u003eteam leads looking for a low-effort way to make data structures discoverable\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhy this matters\n    \u003cdiv id=\"why-this-matters\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#why-this-matters\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ewhen you build a dbt project, the models represent real business concepts. customers, products, sales, inventory, whatever the domain is. the people who consume those models in dashboards or reports often have no involvement in building them and no reason to read raw sql.\u003c/p\u003e\n\u003cp\u003ewithout documentation, those consumers rely on tribal knowledge, slack messages, and guesswork. that does not scale. dbt docs solve this by turning the metadata you already maintain (yml files, project config, source definitions) into a navigable reference that anyone on the team can use. the effort to write a good description is small, and the compound value to the rest of the organization grows with every model you add.\u003c/p\u003e\n\u003cp\u003ei think of it like this: if i write a model and do not document it, the only person who truly understands it is me, and even that fades after a few months. if i write a two-sentence description and add column-level context, that knowledge lives in the project permanently and serves everyone who touches the data.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhat dbt docs generates\n    \u003cdiv id=\"what-dbt-docs-generates\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-dbt-docs-generates\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ewhen you run \u003ccode\u003edbt docs generate\u003c/code\u003e, dbt produces two main artifacts in your \u003ccode\u003etarget/\u003c/code\u003e directory:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003emanifest.json\u003c/strong\u003e contains the full project graph, including every model, source, seed, snapshot, and macro, along with their descriptions, tags, and configuration\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ecatalog.json\u003c/strong\u003e contains the schema-level metadata pulled from your warehouse, including column names, data types, and row counts\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003etogether with a bundled \u003ccode\u003eindex.html\u003c/code\u003e, these files power a static site that you can open locally with \u003ccode\u003edbt docs serve\u003c/code\u003e or host anywhere that serves static files.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ethe site includes\n    \u003cdiv id=\"the-site-includes\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-site-includes\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003ea searchable list of every model and data source in your project\u003c/li\u003e\n\u003cli\u003emodel-level and column-level descriptions pulled from your yml files\u003c/li\u003e\n\u003cli\u003ethe full sql compiled for each model (in each environment)\u003c/li\u003e\n\u003cli\u003ea lineage graph (dag - directed acyclic graph) that shows upstream sources, intermediate models, and downstream consumers for any selected node\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ethe lineage graph is especially useful when someone asks \u0026ldquo;where does this column come from\u0026rdquo; or \u0026ldquo;what breaks if i change this source table\u0026rdquo;. instead of tracing through sql files manually, the graph answers it visually.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ehow to document your models\n    \u003cdiv id=\"how-to-document-your-models\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#how-to-document-your-models\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003edbt reads documentation from yml files that live alongside your models. you are probably already using these for configuration and \u003ca href=\"/posts/20260328-what-is-sql-and-why-it-still-works/\" \u003esource definitions\u003c/a\u003e, so adding descriptions is a natural extension.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003emodel and column descriptions in yml\n    \u003cdiv id=\"model-and-column-descriptions-in-yml\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#model-and-column-descriptions-in-yml\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethe most common approach is adding \u003ccode\u003edescription\u003c/code\u003e fields directly in your yml files. here is what that looks like for a view in an information delivery layer:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"m\"\u003e2\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"nt\"\u003emodels\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eORDER_SUMMARY_V\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003edescription\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"sd\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e      aggregated view of customer orders with totals and status\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e      breakdowns, consumed by the reporting dashboard and the\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e      customer details page in the application.\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003ecolumns\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eCUSTOMER_ID\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003edescription\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;unique identifier for the customer\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eTOTAL_ORDERS\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003edescription\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;count of all orders placed by this customer\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eTOTAL_SPEND\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003edescription\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;sum of order amounts across all completed orders\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eLAST_ORDER_DATE\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003edescription\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;most recent order date for this customer\u0026#34;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003eevery model and every column can have a description. the more specific you are, the more useful the generated docs become. \u0026ldquo;id\u0026rdquo; as a column description does not help anyone. \u0026ldquo;unique identifier for the customer, sourced from the application database\u0026rdquo; does.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003esource descriptions\n    \u003cdiv id=\"source-descriptions\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#source-descriptions\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003esources benefit from the same treatment. when your project ingests raw data from an external system, describing those sources in your shared sources file makes the lineage graph meaningful from the very first node:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"m\"\u003e2\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"nt\"\u003esources\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eRAW_ORDERS\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003edescription\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;raw order data ingested from the transactional database via kafka\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003edatabase\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eANALYTICS_DEV_DB\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003eschema\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eRAW_DATA\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003etables\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eORDERS\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003edescription\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;one row per order, includes order status and timestamps\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eORDER_ITEMS\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003edescription\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;line items for each order, one row per product per order\u0026#34;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003edoc blocks for longer descriptions\n    \u003cdiv id=\"doc-blocks-for-longer-descriptions\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#doc-blocks-for-longer-descriptions\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ewhen a model needs more than a sentence or two of context, dbt supports doc blocks. these are markdown files (\u003ccode\u003e.md\u003c/code\u003e) that live in your project and can be referenced from yml descriptions:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-markdown\" data-lang=\"markdown\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e{% docs order_summary_description %}\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ethis view surfaces the aggregated order history for each customer.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eit joins the hub, satellite, and link tables from the refined data\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003elayer to produce a single wide row per customer.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gs\"\u003e**grain:**\u003c/span\u003e one row per customer.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gs\"\u003e**consumers:**\u003c/span\u003e reporting dashboard, customer details api endpoint.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e{% enddocs %}\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003ethen in your yml:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003emodels\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eORDER_SUMMARY_V\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003edescription\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;{{ doc(\u0026#34;order_summary_description\u0026#34;) }}\u0026#39;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003edoc blocks are useful when the context is long enough that embedding it inline in yaml becomes awkward. they also let you reuse the same description across multiple references if needed.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ea few useful options in dbt docs\n    \u003cdiv id=\"a-few-useful-options-in-dbt-docs\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#a-few-useful-options-in-dbt-docs\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003epersist_docs\n    \u003cdiv id=\"persist_docs\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#persist_docs\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eby default, dbt docs only live in the generated static site. if you want the descriptions to also appear in your warehouse catalog (so someone querying \u003ca href=\"/posts/20260328-the-difference-between-snowflake-and-the-other-databases/\" \u003esnowflake\u003c/a\u003e information_schema can see them), you can enable \u003ccode\u003epersist_docs\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003emodels\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"nt\"\u003emy_data_product\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003e+persist_docs\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"nt\"\u003erelation\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"nt\"\u003ecolumns\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003ewith this enabled, \u003ccode\u003edbt run\u003c/code\u003e pushes your yml descriptions into the \u003ccode\u003eCOMMENT\u003c/code\u003e property on the table or view and on each column in the warehouse. this is valuable because it means the documentation is available even outside the dbt docs site, directly in the database catalog that tools like snowflake and bi platforms already read.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ethe lineage graph\n    \u003cdiv id=\"the-lineage-graph\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-lineage-graph\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethe generated site includes an interactive dag that visualizes every model, source, and their connections. you can click on any node to see its upstream dependencies and downstream consumers. this is one of the most powerful features in dbt docs because it makes the data flow tangible for people who do not read sql (or maybe they just do not have access to your workspace, but still have a need to understand it).\u003c/p\u003e\n\u003cp\u003ewhen you have a project with dozens or hundreds of models organized into layers (raw, refined, business, information delivery), the lineage graph shows how a raw source table flows through transformations into the final views that analysts query. it replaces the need for manually maintained architecture diagrams that go stale the moment someone adds a new model.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003eexposures\n    \u003cdiv id=\"exposures\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#exposures\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eexposures let you document where your dbt models are consumed outside of dbt. dashboards, applications, api endpoints, anything downstream. defining them makes the lineage graph extend beyond the dbt project boundary:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003eexposures\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003ecustomer_dashboard\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003edashboard\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003edescription\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;executive dashboard showing customer order trends and retention\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003edepends_on\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"l\"\u003eref(\u0026#39;ORDER_SUMMARY_V\u0026#39;)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"l\"\u003eref(\u0026#39;CUSTOMER_RETENTION_V\u0026#39;)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003eowner\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eanalytics team\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"nt\"\u003eemail\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eanalytics@example.com\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003eexposures show up in the lineage graph as leaf nodes, making it clear which models are actively consumed and by what. this is helpful when you are deciding whether it is safe to refactor or deprecate a model.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ehosting dbt docs on github pages\n    \u003cdiv id=\"hosting-dbt-docs-on-github-pages\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#hosting-dbt-docs-on-github-pages\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003erunning \u003ccode\u003edbt docs serve\u003c/code\u003e is great for local browsing, but the real value comes from hosting the site where the whole team can access it without installing dbt or cloning the repo. github pages is a straightforward, free option for this.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ehow it works\n    \u003cdiv id=\"how-it-works\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#how-it-works\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eafter \u003ccode\u003edbt docs generate\u003c/code\u003e runs, the \u003ccode\u003etarget/\u003c/code\u003e directory contains everything needed to serve the site: \u003ccode\u003eindex.html\u003c/code\u003e, \u003ccode\u003emanifest.json\u003c/code\u003e, and \u003ccode\u003ecatalog.json\u003c/code\u003e. you copy those files to a branch or directory that github pages serves, and the docs are live.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ea basic github actions workflow\n    \u003cdiv id=\"a-basic-github-actions-workflow\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#a-basic-github-actions-workflow\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ehere is a minimal workflow that generates the docs on every push to main and deploys them to github pages:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003edeploy dbt docs\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"nt\"\u003eon\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"nt\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003ebranches\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"l\"\u003emain]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"nt\"\u003epermissions\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"nt\"\u003econtents\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eread\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"nt\"\u003epages\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003ewrite\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"nt\"\u003eid-token\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003ewrite\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"nt\"\u003ejobs\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"nt\"\u003edeploy\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003eruns-on\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eubuntu-latest\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003eenvironment\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003egithub-pages\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"nt\"\u003eurl\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003e${{ steps.deployment.outputs.page_url }}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003esteps\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003euses\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eactions/checkout@v4\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eset up python\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003euses\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eactions/setup-python@v5\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003ewith\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e          \u003c/span\u003e\u003cspan class=\"nt\"\u003epython-version\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;3.11\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003einstall dbt\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003epip install dbt-snowflake\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003egenerate docs\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003edbt docs generate --profiles-dir .\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003eworking-directory\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003emy_dbt_project\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003eenv\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e          \u003c/span\u003e\u003cspan class=\"nt\"\u003eDBT_SNOWFLAKE_ACCOUNT\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003e${{ secrets.SNOWFLAKE_ACCOUNT }}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e          \u003c/span\u003e\u003cspan class=\"nt\"\u003eDBT_SNOWFLAKE_USER\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003e${{ secrets.SNOWFLAKE_USER }}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e          \u003c/span\u003e\u003cspan class=\"nt\"\u003eDBT_SNOWFLAKE_PASSWORD\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003e${{ secrets.SNOWFLAKE_PASSWORD }}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eprepare pages artifact\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"sd\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e          mkdir -p pages\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e          cp my_dbt_project/target/index.html pages/\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e          cp my_dbt_project/target/manifest.json pages/\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e          cp my_dbt_project/target/catalog.json pages/\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eupload pages artifact\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003euses\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eactions/upload-pages-artifact@v3\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003ewith\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e          \u003c/span\u003e\u003cspan class=\"nt\"\u003epath\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003epages\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003edeploy to github pages\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003eid\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003edeployment\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003euses\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eactions/deploy-pages@v4\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003eonce this runs, your dbt docs are available at \u003ccode\u003ehttps://\u0026lt;org\u0026gt;.github.io/\u0026lt;repo\u0026gt;/\u003c/code\u003e and automatically update every time someone merges to main. no one needs to install anything or run any commands to browse the documentation.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ekeep the credentials out of the repo\n    \u003cdiv id=\"keep-the-credentials-out-of-the-repo\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#keep-the-credentials-out-of-the-repo\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethe workflow above uses github secrets for warehouse credentials. never commit profiles with real credentials. use environment variables or a ci-specific \u003ccode\u003eprofiles.yml\u003c/code\u003e that references secrets, and make sure your \u003ccode\u003e.gitignore\u003c/code\u003e excludes any local profiles that contain actual passwords or tokens.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003edo i need to write descriptions for every column?\n    \u003cdiv id=\"do-i-need-to-write-descriptions-for-every-column\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#do-i-need-to-write-descriptions-for-every-column\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eyou do not need to, but the columns that matter most to consumers deserve it. at minimum, describe the primary key, any business key, and any column whose meaning is not obvious from the name alone. over time, filling in the rest pays off as the team grows.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ecan i generate docs without connecting to the warehouse?\n    \u003cdiv id=\"can-i-generate-docs-without-connecting-to-the-warehouse\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#can-i-generate-docs-without-connecting-to-the-warehouse\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003e\u003ccode\u003edbt docs generate\u003c/code\u003e pulls catalog metadata from the warehouse, so it does need a connection. however, if you already have a \u003ccode\u003ecatalog.json\u003c/code\u003e from a previous run, you can serve the site locally with just those files.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ehow is this different from a wiki or confluence page?\n    \u003cdiv id=\"how-is-this-different-from-a-wiki-or-confluence-page\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#how-is-this-different-from-a-wiki-or-confluence-page\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003edbt docs stay in sync with your code automatically. a wiki page about your data model goes stale the moment someone adds a column or renames a table. dbt docs regenerate from the source of truth (your yml files and your warehouse) every time you run the command, so the documentation and the code never drift apart.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/docs/collaborate/documentation\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt docs overview (dbt documentation)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/reference/commands/cmd-docs\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt docs generate command\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/reference/resource-configs/persist_docs\"  target=\"_blank\" rel=\"noreferrer\"\u003epersist_docs config\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/docs/build/exposures\"  target=\"_blank\" rel=\"noreferrer\"\u003eexposures (dbt documentation)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.github.com/en/pages\"  target=\"_blank\" rel=\"noreferrer\"\u003egithub pages documentation\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/series/dbt/\" \u003edbt series\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260328-what-is-sql-and-why-it-still-works/\" \u003ewhat is sql, and why it still works\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260328-the-difference-between-snowflake-and-the-other-databases/\" \u003ethe difference between snowflake and the \u0026ldquo;other\u0026rdquo; databases\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-30T11:39:08Z","date_published":"2026-03-30T11:39:08Z","id":"https://philliant.com/posts/20260330-dbt-docs/","summary":"dbt docs are one of the most overlooked features in a dbt project, but they are one of the most valuable for teammates who consume data without building it. i walk through how they work, what options matter, and how to host them for free on github pages.","tags":["dbt","documentation","data-engineering","github-pages","snowflake"],"title":"dbt docs","url":"https://philliant.com/posts/20260330-dbt-docs/"},{"content_html":"\u003cp\u003ei wanted this to be an entry point for the \u003ccode\u003esql\u003c/code\u003e series, a clear \u0026ldquo;what is sql\u0026rdquo; reference you can scan quickly and return to later. even with constant technology shifts, relational databases and \u003ccode\u003esql\u003c/code\u003e still anchor a huge part of modern software and analytics.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003esql is the language most relational databases use to define, read, update, and manage data. it is declarative, which means i describe the result i want and the database engine decides how to execute it efficiently. this model has held up for decades because sql is expressive, portable, and understandable. vendor dialects differ, but the core grammar is still recognizable almost everywhere.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003epeople new to data and databases who want a quick introduction\u003c/li\u003e\n\u003cli\u003edevelopers who use databases daily but never got the historical context\u003c/li\u003e\n\u003cli\u003eanalysts and engineers deciding when sql is the right tool\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhat sql is\n    \u003cdiv id=\"what-sql-is\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-sql-is\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eat its core, sql works on tables made of rows and columns. tables are connected by keys, and queries combine or reshape those tables to answer questions.\u003c/p\u003e\n\u003cp\u003esql usually appears in four practical categories:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003equerying data\u003c/strong\u003e with \u003ccode\u003eselect\u003c/code\u003e, \u003ccode\u003ewhere\u003c/code\u003e, \u003ccode\u003ejoin\u003c/code\u003e, \u003ccode\u003egroup by\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003emodifying data\u003c/strong\u003e with \u003ccode\u003einsert\u003c/code\u003e, \u003ccode\u003eupdate\u003c/code\u003e, \u003ccode\u003edelete\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003edefining structures\u003c/strong\u003e with \u003ccode\u003ecreate table\u003c/code\u003e, \u003ccode\u003ealter table\u003c/code\u003e, \u003ccode\u003ecreate view\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003econtrolling access and safety\u003c/strong\u003e with \u003ccode\u003egrant\u003c/code\u003e, \u003ccode\u003erevoke\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ethe most important mindset shift is this: sql is set-based and declarative, not loop-first and imperative.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ea short history of sql\n    \u003cdiv id=\"a-short-history-of-sql\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#a-short-history-of-sql\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003esql has been around for more than 50 years, and that long runway is one reason it feels \u0026ldquo;locked in\u0026rdquo; as a standard.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e1970\u003c/strong\u003e: edgar f. codd publishes the relational model at ibm\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003emid 1970s\u003c/strong\u003e: ibm researchers develop sequel, which later becomes sql\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e1979\u003c/strong\u003e: oracle ships one of the first commercial sql database implementations\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e1986\u003c/strong\u003e: ansi publishes the first sql standard (i personally \u003cstrong\u003eONLY\u003c/strong\u003e write ansi standard for maximum portability)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e1990s to 2000s\u003c/strong\u003e: major vendors expand features and performance, while the core language stays recognizable\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003etoday\u003c/strong\u003e: sql powers operational databases, analytics warehouses, bi tools, and transformation frameworks\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhy sql is important\n    \u003cdiv id=\"why-sql-is-important\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#why-sql-is-important\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003esql is still important for practical reasons, not nostalgia.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eit is a common language shared by developers, analysts, and data engineers\u003c/li\u003e\n\u003cli\u003eit is standard enough that skills transfer across many systems\u003c/li\u003e\n\u003cli\u003eit lets database engines optimize queries with indexes and planners\u003c/li\u003e\n\u003cli\u003eit models relationships clearly through keys and joins\u003c/li\u003e\n\u003cli\u003eit supports transactional consistency for critical business data\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003efor me, one of the biggest advantages is ease of learning. for common querying and reporting tasks, sql usually has a lower starting barrier than learning a full general-purpose programming language like python.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhen and where to use sql\n    \u003cdiv id=\"when-and-where-to-use-sql\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#when-and-where-to-use-sql\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003esql fits especially well in these environments:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eapplication databases\u003c/strong\u003e like postgresql, mysql, and sql server for transactional systems\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eanalytics platforms\u003c/strong\u003e like snowflake, where large-scale reporting and transformation matter most, i cover that context more in \u003ca href=\"/posts/20260328-the-difference-between-snowflake-and-the-other-databases/\" \u003ethe difference between snowflake and the \u0026ldquo;other\u0026rdquo; databases\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003edata transformation workflows\u003c/strong\u003e where repeatable models and tests are required\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ereporting and business intelligence\u003c/strong\u003e when teams need consistent, auditable metrics\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003esql is usually not the best first tool for heavy imperative algorithms, event orchestration, or specialized graph traversal.\u003c/p\u003e\n\u003cp\u003eif you want a practical comparison between snowflake and operational database systems, i break that down in \u003ca href=\"/posts/20260328-the-difference-between-snowflake-and-the-other-databases/\" \u003ethe difference between snowflake and the \u0026ldquo;other\u0026rdquo; databases\u003c/a\u003e.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ekey features worth knowing early\n    \u003cdiv id=\"key-features-worth-knowing-early\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#key-features-worth-knowing-early\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ejoins\u003c/strong\u003e to combine related entities through keys\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eaggregations\u003c/strong\u003e (\u003ccode\u003esum\u003c/code\u003e, \u003ccode\u003ecount\u003c/code\u003e, \u003ccode\u003eavg\u003c/code\u003e) to move from row-level detail to summaries\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ewindow functions\u003c/strong\u003e for ranking, running totals, and partitioned calculations\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003etransactions\u003c/strong\u003e for safe multi-step writes (\u003ccode\u003ebegin\u003c/code\u003e, \u003ccode\u003ecommit\u003c/code\u003e, \u003ccode\u003erollback\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003econstraints\u003c/strong\u003e (primary keys, foreign keys, uniqueness) to enforce data quality\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eviews and ctes\u003c/strong\u003e to make complex logic readable and reusable\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ea few simple examples\n    \u003cdiv id=\"a-few-simple-examples\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#a-few-simple-examples\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003efilter rows\n    \u003cdiv id=\"filter-rows\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#filter-rows\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eSELECT\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eorder_id\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eorder_date\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003etotal_amount\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eFROM\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eorders\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eWHERE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eorder_date\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nb\"\u003eDATE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;2026-01-01\u0026#39;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003ejoin related data\n    \u003cdiv id=\"join-related-data\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#join-related-data\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eSELECT\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecustomer_name\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eorder_id\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003etotal_amount\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eFROM\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eorders\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eJOIN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecustomers\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eON\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecustomer_id\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecustomer_id\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003eaggregate to a useful metric\n    \u003cdiv id=\"aggregate-to-a-useful-metric\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#aggregate-to-a-useful-metric\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eSELECT\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003ecustomer_id\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"k\"\u003eSUM\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003etotal_amount\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eAS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etotal_spend\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eFROM\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eorders\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eGROUP\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eBY\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecustomer_id\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eORDER\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eBY\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etotal_spend\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eDESC\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003euse a transaction for safe updates\n    \u003cdiv id=\"use-a-transaction-for-safe-updates\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#use-a-transaction-for-safe-updates\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eBEGIN\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eUPDATE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eaccounts\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eSET\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebalance\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebalance\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e100\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eWHERE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eaccount_id\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eUPDATE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eaccounts\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eSET\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebalance\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebalance\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e100\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eWHERE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eaccount_id\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eCOMMIT\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003eis sql the same thing as a database?\n    \u003cdiv id=\"is-sql-the-same-thing-as-a-database\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#is-sql-the-same-thing-as-a-database\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eno. sql is a language, and a database engine is the system that executes it. two engines can both support sql while differing in extensions, performance behavior, and tooling.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat is the fastest way to get good at sql?\n    \u003cdiv id=\"what-is-the-fastest-way-to-get-good-at-sql\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-is-the-fastest-way-to-get-good-at-sql\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ei suggest learning in this order: filtering, joins, aggregation, then window functions. if you can always explain the grain of one row in your result, your queries become much easier to trust.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhen should i think twice about using sql?\n    \u003cdiv id=\"when-should-i-think-twice-about-using-sql\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#when-should-i-think-twice-about-using-sql\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eif your core problem is orchestration, low-latency event handling, or algorithm-heavy logic, sql alone is usually not enough. in those cases, use sql for data access and pair it with application or workflow code.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/SQL\"  target=\"_blank\" rel=\"noreferrer\"\u003esql (wikipedia)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/SEQUEL_%28programming_language%29\"  target=\"_blank\" rel=\"noreferrer\"\u003esequel (programming language)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/ISO/IEC_9075\"  target=\"_blank\" rel=\"noreferrer\"\u003eiso/iec 9075 (sql standard)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/History_of_SQL\"  target=\"_blank\" rel=\"noreferrer\"\u003ehistory of sql standards (wikipedia)\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/series/sql/\" \u003esql series\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260328-the-difference-between-snowflake-and-the-other-databases/\" \u003ethe difference between snowflake and the \u0026ldquo;other\u0026rdquo; databases\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260324-left-join-effective-satellite-cte/\" \u003eleft join an effective satellite without duplicating rows (use a cte)\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-28T12:48:02Z","date_published":"2026-03-28T12:48:02Z","id":"https://philliant.com/posts/20260328-what-is-sql-and-why-it-still-works/","summary":"i break down sql in plain language: what it is, how it evolved over five decades, which problems it solves best, and the core features that keep it relevant","tags":["sql","databases","relational databases","history","querying"],"title":"what is sql, and why it still works","url":"https://philliant.com/posts/20260328-what-is-sql-and-why-it-still-works/"},{"content_html":"\u003cp\u003ewhen you first step into data engineering, the sheer number of database options can be overwhelming. i spend a lot of my time working in snowflake, but it is definitely not the only tool in the shed.\u003c/p\u003e\n\u003cp\u003eto build a solid data platform, you have to understand where your data comes from and how different systems handle it. i want to break down how snowflake compares to two other popular systems you will encounter often: relational engines such as amazon rds and nosql patterns such as amazon dynamodb.\u003c/p\u003e\n\u003cp\u003ethis is a basic guide written from a data engineer\u0026rsquo;s perspective. i will point out the similarities, the differences, and when you should use each one.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ethe contenders\n    \u003cdiv id=\"the-contenders\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-contenders\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ebefore we compare them, let us define what we are looking at:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003esnowflake\u003c/strong\u003e: a cloud-native data warehouse built for analytics (olap - online analytical processing). storage and compute are separate, so you pay for each part independently\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eamazon rds\u003c/strong\u003e: a managed relational database service that runs engines like postgresql, mysql, sql server, and oracle. it is built for transactional app workloads (oltp - online transactional processing)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eamazon dynamodb\u003c/strong\u003e: a fully managed nosql key-value and document store built for very low-latency lookups at high scale\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003esimilarities and differences\n    \u003cdiv id=\"similarities-and-differences\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#similarities-and-differences\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eat a high level, snowflake and rds both use sql, which makes them feel familiar. dynamodb is api-first for key-value access. it also offers partiql support, but it does not behave like a relational sql engine with joins and broad ad hoc querying.\u003c/p\u003e\n\u003cp\u003ethe biggest architectural difference is how they handle storage and compute.\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003efeature\u003c/th\u003e\n          \u003cth\u003esnowflake\u003c/th\u003e\n          \u003cth\u003eamazon RDS\u003c/th\u003e\n          \u003cth\u003eamazon dynamodb\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eprimary use case\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003eanalytics and reporting (olap)\u003c/td\u003e\n          \u003ctd\u003eapplication backends (oltp)\u003c/td\u003e\n          \u003ctd\u003ehigh-scale key-value applications\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003equery language\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003esql (warehouse dialect)\u003c/td\u003e\n          \u003ctd\u003esql (engine-specific)\u003c/td\u003e\n          \u003ctd\u003eapi-first (partiql support)\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003earchitecture\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003estorage and compute decoupled\u003c/td\u003e\n          \u003ctd\u003estorage and compute coupled\u003c/td\u003e\n          \u003ctd\u003edistributed key-value store\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003edata structure\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003etables and semi-structured data\u003c/td\u003e\n          \u003ctd\u003erelational tables\u003c/td\u003e\n          \u003ctd\u003ekey-value and document items\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eindexes\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003emicro-partition pruning metadata\u003c/td\u003e\n          \u003ctd\u003euser-managed indexes\u003c/td\u003e\n          \u003ctd\u003epartition and sort keys\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003esnowflake does not require traditional user-managed indexes for most workloads. it uses micro-partitions and pruning metadata. in rds, you usually create and manage indexes manually to keep queries fast. dynamodb pushes you to define access patterns up front using partition and sort keys.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003escalability: small, big, and the limits\n    \u003cdiv id=\"scalability-small-big-and-the-limits\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#scalability-small-big-and-the-limits\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003escalability means something completely different depending on which database you are talking about.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003esnowflake\n    \u003cdiv id=\"snowflake\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#snowflake\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003esnowflake scales compute and storage independently. storage is backed by cloud object storage, so it is effectively unbounded for most teams. you can store petabytes of data without thinking about disks.\u003c/p\u003e\n\u003cp\u003ecompute is handled by virtual warehouses, which come in t-shirt sizes from x-small to 6x-large. if a query is too slow, you can use a larger warehouse. if you have too many concurrent users, you can add clusters.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003esmall\u003c/strong\u003e: gigabytes of data running on an x-small warehouse\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ebig\u003c/strong\u003e: petabytes of data running on a 4x-large warehouse\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003elimits\u003c/strong\u003e: practically none for storage; compute is limited only by your budget\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch3 class=\"relative group\"\u003eamazon RDS\n    \u003cdiv id=\"amazon-rds\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#amazon-rds\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003erds usually scales write capacity vertically by moving to a larger instance class. depending on engine and change type, this can trigger a restart or failover window. you can also scale read traffic horizontally with read replicas.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003esmall\u003c/strong\u003e: a few gigabytes on a \u003ccode\u003et3.micro\u003c/code\u003e instance\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ebig\u003c/strong\u003e: several terabytes on a massive \u003ccode\u003em6g.16xlarge\u003c/code\u003e instance\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003elimits\u003c/strong\u003e: many engines cap around 64 terabytes per instance (roughly 64 tib), and you still hit single-instance ceilings on cpu, memory, and concurrent connections\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch3 class=\"relative group\"\u003eamazon dynamodb\n    \u003cdiv id=\"amazon-dynamodb\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#amazon-dynamodb\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003edynamodb scales horizontally and automatically. it partitions your data across many servers behind the scenes.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003esmall\u003c/strong\u003e: a few megabytes with single-digit read/write capacity units\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ebig\u003c/strong\u003e: hundreds of terabytes handling millions of requests per second\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003elimits\u003c/strong\u003e: very high scale for key-value access, but full-table scans and broad analytical queries are usually expensive and inefficient\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003eease of learning curve and use\n    \u003cdiv id=\"ease-of-learning-curve-and-use\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#ease-of-learning-curve-and-use\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eas a data engineer, the learning curve dictates how fast you can deliver value.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003esnowflake (easiest for analysts)\n    \u003cdiv id=\"snowflake-easiest-for-analysts\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#snowflake-easiest-for-analysts\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eif you know sql, you can use snowflake quickly. the learning curve is low because there is very little infrastructure to manage. you do not worry about vacuuming tables, managing indexes, or tuning memory pools. you mostly load data and query it.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003eamazon RDS (moderate)\n    \u003cdiv id=\"amazon-rds-moderate\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#amazon-rds-moderate\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003erds is easy to start with because postgresql and mysql are industry standards. however, the learning curve gets steep when you hit scale. you have to read query plans, manage indexes, handle connection pooling, and tune database parameters.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003eamazon dynamodb (steepest for modeling)\n    \u003cdiv id=\"amazon-dynamodb-steepest-for-modeling\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#amazon-dynamodb-steepest-for-modeling\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003edynamodb has a notoriously steep learning curve for data modeling. because it is not a relational join engine, you usually model around known access patterns (often with single-table design). if those patterns change later, you may need redesign work and backfills.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhen to use each\n    \u003cdiv id=\"when-to-use-each\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#when-to-use-each\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003echoosing the right database is about matching the tool to the workload.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003euse snowflake when:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eyou need to analyze massive amounts of data\u003c/li\u003e\n\u003cli\u003eyou are building dashboards, reports, or a data warehouse\u003c/li\u003e\n\u003cli\u003eyou need to join data from many different sources\u003c/li\u003e\n\u003cli\u003eyour queries read millions of rows at a time\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003euse amazon RDS when:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eyou are building a standard web application\u003c/li\u003e\n\u003cli\u003eyou need strong transactional guarantees (ACID compliance)\u003c/li\u003e\n\u003cli\u003eyour queries typically look up or update a single row or a small batch of rows\u003c/li\u003e\n\u003cli\u003eyour core workload is transactional and fits a single relational instance pattern, even as it grows into multi-terabyte range\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003euse amazon dynamodb when:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eyou are building a shopping cart, session store, or gaming leaderboard\u003c/li\u003e\n\u003cli\u003eyou need guaranteed single-digit millisecond response times\u003c/li\u003e\n\u003cli\u003eyou have massive, unpredictable spikes in traffic\u003c/li\u003e\n\u003cli\u003eyou do not need to run complex analytical queries\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eas a data engineer, your job is often to extract data from operational systems (like rds and dynamodb) and load it into an analytical system (like snowflake). that is what allows the business to understand what is happening.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://docs.snowflake.com/\"  target=\"_blank\" rel=\"noreferrer\"\u003esnowflake documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.aws.amazon.com/rds/\"  target=\"_blank\" rel=\"noreferrer\"\u003eamazon RDS documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.aws.amazon.com/dynamodb/\"  target=\"_blank\" rel=\"noreferrer\"\u003eamazon dynamodb documentation\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/series/snowflake/\" \u003esnowflake series\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-28T11:49:27Z","date_published":"2026-03-28T11:49:27Z","id":"https://philliant.com/posts/20260328-the-difference-between-snowflake-and-the-other-databases/","summary":"when you first step into data engineering, the sheer number of database options can be overwhelming. i break down how snowflake compares to traditional relational databases like rds and nosql options like dynamodb, focusing on when to use each and how they scale.","tags":["snowflake","rds","dynamodb","databases","data-engineering"],"title":"the difference between snowflake and the \"other\" databases","url":"https://philliant.com/posts/20260328-the-difference-between-snowflake-and-the-other-databases/"},{"content_html":"\n\u003ch2 class=\"relative group\"\u003ethesis\n    \u003cdiv id=\"thesis\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#thesis\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei think adaptability is one of the most useful skills to develop, and its value keeps rising. ai and agents are changing workflows faster than most teams can document them. people who adjust quickly, while staying clear about outcomes, will keep moving when others stall.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003econtext\n    \u003cdiv id=\"context\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#context\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ewidespread ai adoption is pushing change into almost every part of work. tasks are getting split differently, handoffs are being redefined, and the idea of \u0026ldquo;the normal way\u0026rdquo; has a shorter shelf life every month.\u003c/p\u003e\n\u003cp\u003ethis pace is not only a work story. speed and connectivity shape family logistics, routines, and attention in daily life too. the same mental flexibility that helps at work helps at home, in travel, and during any week that does not look like the one before it.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eargument\n    \u003cdiv id=\"argument\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#argument\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei am writing this from a very rural location, far from my normal office setup. i have no cell service except a satellite connection that can send slow texts, and the wifi is around 10 mbps down on a good day, shared across the whole family. that setup forced me to plan work in batches and communicate constraints early. it is a useful reminder that conditions change, but the work still has to get done.\u003c/p\u003e\n\u003cp\u003efor me, adaptability in practice looks like a few simple moves:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eshifting to an offline-first workflow when connectivity is inconsistent\u003c/li\u003e\n\u003cli\u003eprioritizing high-leverage tasks before synchronous calls\u003c/li\u003e\n\u003cli\u003ecommunicating constraints early so expectations stay realistic\u003c/li\u003e\n\u003cli\u003ebatching sync-heavy work into the most stable bandwidth windows\u003c/li\u003e\n\u003cli\u003echoosing tools that degrade gracefully instead of failing hard\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ethis is also why i care so much about clear ownership when using ai. adaptable does not mean random. it means adjusting method while protecting intent, quality, and accountability in a rapidly changing workplace (and world). this is a theme i also touched on in \u003ca href=\"/posts/20260326-the-danger-of-trusting-the-ai-agent/\" \u003ethe danger of trusting the ai agent\u003c/a\u003e.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003etension or counterpoint\n    \u003cdiv id=\"tension-or-counterpoint\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#tension-or-counterpoint\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethere is a valid concern here: constant adaptation can turn into reactive thrashing. not every new tool deserves adoption, and not every workflow change creates real value.\u003c/p\u003e\n\u003cp\u003ethe balance i aim for is to adapt principles faster than (or at least as fast as) tools. if i stay anchored on outcomes, quality, and ownership, i can (hopefully) swap tactics without losing direction.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eclosing\n    \u003cdiv id=\"closing\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#closing\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei do not see adaptability as a soft trait anymore. i see it as operational leverage. it helps me keep momentum when the environment is unstable, when tools change quickly, or when ideal conditions are not available.\u003c/p\u003e\n\u003cp\u003egoing forward, i expect this to matter even more. the people and teams that learn quickly, reframe constraints, and keep moving with clarity will have a durable advantage.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efurther reading\n    \u003cdiv id=\"further-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#further-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Adaptability\"  target=\"_blank\" rel=\"noreferrer\"\u003eadaptability\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Organizational_agility\"  target=\"_blank\" rel=\"noreferrer\"\u003eorganizational agility\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated on this site\n    \u003cdiv id=\"related-on-this-site\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-on-this-site\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260326-the-danger-of-trusting-the-ai-agent/\" \u003ethe danger of trusting the ai agent\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/series/commentary/\" \u003ecommentary series\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-27T16:45:05Z","date_published":"2026-03-27T16:45:05Z","id":"https://philliant.com/posts/20260327-adaptability/","summary":"ai and agents are accelerating how quickly work changes, and that pressure is showing up far beyond tech. i am seeing it directly while working with almost no cell signal and shared low-bandwidth internet, and it keeps reminding me that adaptability is a compounding skill.","tags":["adaptability","ai","work","change"],"title":"adaptability","url":"https://philliant.com/posts/20260327-adaptability/"},{"content_html":"\u003cp\u003ei love how fast ai agents can move, but i have learned that speed without ownership can become expensive very quickly. if i let an agent operate in an area i do not understand deeply, i can end up with changes i cannot explain, verify, or recover confidently.\u003c/p\u003e\n\u003cp\u003ethis is the darker side of the acceleration story i wrote about in \u003ca href=\"/posts/from-prototype-to-production-ai/\" \u003efrom prototype to production: my early adopter view of ai\u003c/a\u003e: ai can \u003cstrong\u003ecompress execution time\u003c/strong\u003e, but it can also \u003cstrong\u003egreatly expand confusion\u003c/strong\u003e if my boundaries are weak.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eif i trust the ai fully in a domain i do not understand, i am borrowing speed against future troubleshooting debt. the agent can still produce plausible progress, but when something breaks, i pay the bill because i do not have the mental model to debug with confidence. my rule now is simple: ai can do my work faster, but it should only do work i truly understand and could perform on my own.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003epeople using agents for coding, data, or operations tasks\u003c/li\u003e\n\u003cli\u003eanyone who has watched an agent \u0026ldquo;do a lot\u0026rdquo; but struggled to explain what actually changed\u003c/li\u003e\n\u003cli\u003eteams where responsibilities cross domains and ownership can get blurry\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhy this matters\n    \u003cdiv id=\"why-this-matters\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#why-this-matters\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eautomation bias is real. when the output looks polished, it is easy to accept it before understanding it. that is manageable in low-risk tasks, but dangerous in high-impact systems where small assumptions can trigger hard-to-trace regressions.\u003c/p\u003e\n\u003cp\u003ethe hidden cost is confidence drift. git can say everything is clean while my own understanding says something feels off. when that gap appears, stress goes up, debugging slows down, and trust in the workflow drops.\u003c/p\u003e\n\u003cp\u003eand one other note to be fair is that in this case, i tried to use a faster, smaller agent to do work that i should have routed to a stronger, deeper thinking model. i was in a hurry and paid for it. remember the tried and true racing phrase \u0026ldquo;slow is smooth, smooth is fast\u0026rdquo;.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ethe failure mode i hit\n    \u003cdiv id=\"the-failure-mode-i-hit\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-failure-mode-i-hit\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei asked an agent to diagnose an error in an area where i did not have strong depth. during the run, it created files to handle the issue. later, it removed those same files because they were not referenced anywhere. from git\u0026rsquo;s perspective, it was a net zero diff.\u003c/p\u003e\n\u003cp\u003efrom my perspective, it was not zero at all. i watched a long stream of activity, expected to see resulting changes, and then found a clean tree. i spent significant time retracing the run to understand what happened, and even after reconciling local and remote state i still had low confidence that everything was truly back to a known good place.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhere i drew the line\n    \u003cdiv id=\"where-i-drew-the-line\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#where-i-drew-the-line\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethe lesson for me is less \u0026ldquo;never trust ai\u0026rdquo; and more \u0026ldquo;do not outsource something you could not do yourself\u0026rdquo;. if i cannot explain the system, i should not delegate high-autonomy changes in that system to an agent.\u003c/p\u003e\n\u003cp\u003ethat lane discipline applies to people too. if work sits in another colleague\u0026rsquo;s domain, i should route it to them, even if they use an agent themselves. the difference is not whether ai is involved. the difference is whether the person driving understands the domain deeply enough to verify and own the result.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ethe lane check i use now\n    \u003cdiv id=\"the-lane-check-i-use-now\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-lane-check-i-use-now\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ebefore i hand work to an agent, i run five checks:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003edo i understand the domain well enough to review every change with confidence\u003c/li\u003e\n\u003cli\u003eif the agent makes a wrong assumption, can i detect it quickly\u003c/li\u003e\n\u003cli\u003edo i have explicit stop conditions and verification steps\u003c/li\u003e\n\u003cli\u003ewill i review the actual diff and command output, not just the narrative in chat\u003c/li\u003e\n\u003cli\u003eif this crosses domain ownership, have i handed it to the right colleague\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eif i answer \u0026ldquo;no\u0026rdquo; to any of these, i narrow the scope or route the task to someone else.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003edoes this mean ai should only do trivial work?\n    \u003cdiv id=\"does-this-mean-ai-should-only-do-trivial-work\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#does-this-mean-ai-should-only-do-trivial-work\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eno. ai can do serious work, but the owner still needs to understand the system and sign off on the result. complexity is fine, unowned complexity is the problem.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat do you do when git says clean but confidence is low?\n    \u003cdiv id=\"what-do-you-do-when-git-says-clean-but-confidence-is-low\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-do-you-do-when-git-says-clean-but-confidence-is-low\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ei treat that as a process warning. i retrace the execution log, compare expected outcomes against actual artifacts, and document what happened before continuing. if i still cannot explain it clearly, i escalate to the domain owner instead of pushing forward on uncertainty.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Automation_bias\"  target=\"_blank\" rel=\"noreferrer\"\u003eautomation bias\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Out-of-the-loop_performance_problem\"  target=\"_blank\" rel=\"noreferrer\"\u003eout-of-the-loop performance problem\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260318-from-prototype-to-production-ai/\" \u003efrom prototype to production: my early adopter view of ai\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260319-practical-ai-workflow-jira-github-mcp/\" \u003ea practical ai workflow: jira, github, and mcp\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260314-ai-br-ai-n-fr-ai/\" \u003eai br-ai-n fr-ai\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/series/ai/\" \u003eai series\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-26T13:31:57Z","date_published":"2026-03-26T13:31:57Z","id":"https://philliant.com/posts/20260326-the-danger-of-trusting-the-ai-agent/","summary":"i share a real failure mode where an ai agent created and then deleted files while debugging, leaving a clean git tree but low confidence. the lesson for me is simple: ai should accelerate the work i own and understand, while domain-specific decisions stay with the people accountable for that domain.","tags":["ai","workflow","trust","ownership","debugging"],"title":"the danger of trusting the ai agent","url":"https://philliant.com/posts/20260326-the-danger-of-trusting-the-ai-agent/"},{"content_html":"\n\u003ch2 class=\"relative group\"\u003ethesis\n    \u003cdiv id=\"thesis\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#thesis\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003efor a long time, a commercial flight was one of the few places where the world could not reach you unless you paid for a seatback phone nobody used. you were offline by default, not by discipline. now many cabins offer wifi strong enough to treat the plane like a slow office in the sky. that is a small technical change and a large cultural one, because it turns disconnection from a fact into a choice, and sometimes into an expectation. i used to think we should protect those disconnected spaces on purpose. today i am less sure of my own opinion, and this piece is an honest inventory of why.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003econtext\n    \u003cdiv id=\"context\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#context\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethe shift did not happen all at once. first it was email that barely worked, then messaging, then enough bandwidth that \u0026ldquo;i am on a plane\u0026rdquo; stopped being a credible excuse for silence in some workplaces. the option to connect is not the same as the obligation to connect, but options have a way of becoming norms. if the team assumes you can answer, the cost of opting out is social and professional, not just the price of the wifi pass.\u003c/p\u003e\n\u003cp\u003ei notice that i feel different about this than i did five or ten years ago. i used to romanticize the cabin as a rare enforced pause, a moving room where the only honest move was a book, a nap, or staring at clouds. now i sometimes have a different perspective since my brain is already racing and the seat is uncomfortable and sleep is not going to happen.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eargument\n    \u003cdiv id=\"argument\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#argument\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003ethe case for keeping flights disconnected\n    \u003cdiv id=\"the-case-for-keeping-flights-disconnected\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-case-for-keeping-flights-disconnected\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethere is real relief in a few hours where slack cannot ping you and the news cannot refresh on reflex. the stream of messages and media is designed to feel urgent. a metal tube at thirty thousand feet used to interrupt that design for everyone equally. when you land, nothing has changed except you, and that can be restorative even when it is boring.\u003c/p\u003e\n\u003cp\u003ei still believe that boredom and idle time are inputs to thinking, not failures of entertainment. a flight without wifi can be a long, low-stakes walk for your attention, and that has value. it is the same thread i explored in \u003ca href=\"/posts/20260320-brain-defrag-time-away-from-screens/\" \u003ebrain defrag: time away from screens (and from \u0026ldquo;one more\u0026rdquo; with ai)\u003c/a\u003e.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ethe case for wanting the connection\n    \u003cdiv id=\"the-case-for-wanting-the-connection\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-case-for-wanting-the-connection\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eif you cannot sleep on planes, hours in the air can feel like time you are borrowing from your life and not getting back. in that frame, wifi looks less like an intrusion and more like a way to reclaim the block for work, reading you actually chose, or staying in touch with people you care about. the \u0026ldquo;wasted time\u0026rdquo; feeling is personal, but it is not irrational.\u003c/p\u003e\n\u003cp\u003ecabin class changes how physical that tradeoff is. if you are fortunate enough to sit in first or business, the tray, the elbow room, and the seat pitch can make typing tolerable for a while. in economy, the same work is often inconvenient for you and unfair to the person beside you who did not sign up to be your armrest and your privacy screen. connectivity does not create that squeeze, but it can intensify it when everyone tries to turn a narrow row into an office.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003etension or counterpoint\n    \u003cdiv id=\"tension-or-counterpoint\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#tension-or-counterpoint\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethe strongest counterpoint to my old \u0026ldquo;protect the disconnected cabin\u0026rdquo; instinct is that disconnection was never equally available. people with caregiving responsibilities, unpredictable schedules, or thin margins already paid a tax when flights were black holes on the calendar. wifi can reduce that tax. my nostalgia for a universal offline bubble was partly a privilege story dressed up as a wellness argument.\u003c/p\u003e\n\u003cp\u003ethe strongest counterpoint to always-on flying is that the cabin is still a shared space, and not every kind of work belongs there without cost to neighbors and to your own nervous system. the technology says you can but your body and the person in the middle seat might wish you would not.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eclosing\n    \u003cdiv id=\"closing\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#closing\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei do not have a tidy answer about whether i like in-flight connectivity. some trips i am grateful for it. some trips i wish the excuse to be unreachable still existed without me having to defend it. what i know is that the choice is heavier than the toggle in the portal makes it look, and i will probably keep revisiting it every time the wheels leave the ground.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efurther reading\n    \u003cdiv id=\"further-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#further-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/In-flight_connectivity\"  target=\"_blank\" rel=\"noreferrer\"\u003ein-flight connectivity\u003c/a\u003e, overview of how internet reaches aircraft and how adoption spread\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Airline_seat\"  target=\"_blank\" rel=\"noreferrer\"\u003eairline seat\u003c/a\u003e, context on pitch, width, and why economy is a poor default office\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated on this site\n    \u003cdiv id=\"related-on-this-site\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-on-this-site\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/series/commentary/\" \u003ecommentary series\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260320-brain-defrag-time-away-from-screens/\" \u003ebrain defrag: time away from screens (and from \u0026ldquo;one more\u0026rdquo; with ai)\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-24T16:23:21Z","date_published":"2026-03-24T16:23:21Z","id":"https://philliant.com/posts/20260324-wifi-on-planes/","summary":"i used to want to protect disconnected travel time. now i am torn between relief from the message stream and the feeling that a long flight is wasted if i cannot sleep and i am not online. cabin class changes how real that tradeoff is, and i still do not have a clean verdict.","tags":["commentary","travel","attention","wifi","disconnect"],"title":"plane wifi: when the cabin forced disconnect","url":"https://philliant.com/posts/20260324-wifi-on-planes/"},{"content_html":"\u003cp\u003ethe dreaded left join to an effective satellite\u0026hellip;..\u003c/p\u003e\n\u003cp\u003ei wanted to write this note, if for no other reason, so the pattern is easier to find when someone searches the same problem. the situation is uncommon enough that public answers are rare, and the fix is small once you see it.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eif you need attributes from an \u003cstrong\u003eeffective satellite\u003c/strong\u003e for an \u003cstrong\u003eoptional\u003c/strong\u003e relationship, do not left join the link, hub, and effective satellite as separate tables in one flat \u003ccode\u003efrom\u003c/code\u003e clause next to your driving link. that shape often reintroduces ambiguity where you can match more than one effective row or change the result grain in ways that are hard to reason about. instead, build a \u003cstrong\u003ecte\u003c/strong\u003e (or subquery) that already resolves \u003cstrong\u003eone current effective row per link\u003c/strong\u003e (for example \u003ccode\u003eload_end_ts = '9999-12-31'\u003c/code\u003e or your project\u0026rsquo;s equivalent), then \u003ccode\u003eleft join\u003c/code\u003e that cte to your main link on the hub or link key you already carry.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eanyone modeling optional links in data vault 2.0 who still needs a stable \u003cstrong\u003eone row per fact\u003c/strong\u003e output\u003c/li\u003e\n\u003cli\u003ereaders who inherited sql where optional dimensions quietly duplicate keys\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhy this matters\n    \u003cdiv id=\"why-this-matters\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#why-this-matters\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003egrain is the contract downstream queries trust. when an optional path multiplies rows, dashboards and application reads disagree on what \u0026ldquo;one entity\u0026rdquo; means, and the bug shows up late because the sql \u0026ldquo;looks\u0026rdquo; like a normal join tree.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003estep-by-step\n    \u003cdiv id=\"step-by-step\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#step-by-step\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003e1) define the starting point\n    \u003cdiv id=\"1-define-the-starting-point\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#1-define-the-starting-point\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eyou have a driving \u003cstrong\u003elink\u003c/strong\u003e (for example link between a case and a cycle) with inner joins to its own \u003cstrong\u003ehub\u003c/strong\u003e, \u003cstrong\u003eeffective satellite\u003c/strong\u003e, and \u003cstrong\u003eattribute satellite\u003c/strong\u003e so the core row is current and unique. one foreign key on that link points at an \u003cstrong\u003eoptional\u003c/strong\u003e hub (for example an optional grouping). not every driving row has that key set.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003e2) apply the change\n    \u003cdiv id=\"2-apply-the-change\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#2-apply-the-change\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eput the optional side in a cte: start from the optional \u003cstrong\u003elink\u003c/strong\u003e, join the \u003cstrong\u003eeffective satellite\u003c/strong\u003e with an \u003cstrong\u003einner\u003c/strong\u003e predicate that keeps only the open interval row, then attach the \u003cstrong\u003ehub\u003c/strong\u003e if you need the business key. in the outer query, \u003cstrong\u003eleft join\u003c/strong\u003e the cte on the optional hub hash (or whatever stable key you store on the driving link).\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003e3) validate the result\n    \u003cdiv id=\"3-validate-the-result\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#3-validate-the-result\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ecount distinct keys on the driving natural or surrogate key before and after the change. the counts should match when the optional side is empty, and optional matches should add columns without adding rows.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ea minimal example\n    \u003cdiv id=\"a-minimal-example\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#a-minimal-example\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethis is anonymized and trimmed; names stand in for a real link, hub, and satellites. the following sql shows the shape i use.\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eWITH\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecte_optional_scope\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eAS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eSELECT\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003elink_scope\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003escope_h\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003ehub_scope\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003escope_bk\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eFROM\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elink_scope\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elink_scope\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eLEFT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eJOIN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehub_scope\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehub_scope\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eON\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elink_scope\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003escope_h\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehub_scope\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003escope_h\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eINNER\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eJOIN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eeff_sat_scope\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eeff_sat_scope\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eON\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elink_scope\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003el_scope_h\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eeff_sat_scope\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003el_scope_h\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e                                       \u003c/span\u003e\u003cspan class=\"k\"\u003eAND\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eeff_sat_scope\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eload_end_ts\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;9999-12-31\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eSELECT\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003ehub_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecase_bk\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eAS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecase_id\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003esat_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003estatus_code\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003ecte_optional_scope\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003escope_bk\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eAS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eoptional_scope_id\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eFROM\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elink_case\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elink_case\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eINNER\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eJOIN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehub_case\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehub_case\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eON\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elink_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecase_h\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehub_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecase_h\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eINNER\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eJOIN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eeff_sat_case\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eeff_sat_case\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eON\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elink_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003el_case_h\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eeff_sat_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003el_case_h\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e                                     \u003c/span\u003e\u003cspan class=\"k\"\u003eAND\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eeff_sat_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eload_end_ts\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;9999-12-31\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eINNER\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eJOIN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esat_case\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esat_case\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eON\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eeff_sat_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecase_h\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esat_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecase_h\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e                             \u003c/span\u003e\u003cspan class=\"k\"\u003eAND\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esat_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eload_end_ts\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;9999-12-31\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\u003c/span\u003e\u003cspan class=\"k\"\u003eLEFT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eJOIN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecte_optional_scope\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecte_optional_scope\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eON\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elink_case\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003escope_h\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecte_optional_scope\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003escope_h\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003ethe important part is not the column list, it is the \u003cstrong\u003eshape\u003c/strong\u003e: the effective satellite predicate lives \u003cstrong\u003einside\u003c/strong\u003e the cte, and the outer query only \u003cstrong\u003eleft joins\u003c/strong\u003e the already-resolved optional row set.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat is the most important caveat?\n    \u003cdiv id=\"what-is-the-most-important-caveat\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-is-the-most-important-caveat\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eyour project may use a different literal or rule for \u0026ldquo;current\u0026rdquo; effective rows. keep that predicate consistent with every other query that reads the same satellite family.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat should i do first?\n    \u003cdiv id=\"what-should-i-do-first\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-should-i-do-first\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ereproduce the duplicate key count on a small filter (one day, one tenant, one test id) before you rewrite the full model so you can prove the cte removed multiplication.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/series/data-vault-2.0/\" \u003edata vault 2.0 series\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260402-how-i-use-cursor-and-ai-agents-to-write-dbt-tests-and-documentation/\" \u003ehow i use cursor and ai agents to write dbt tests and documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260330-dbt-tests/\" \u003edbt tests, why they matter and where they fit in your data workflow\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-24T14:00:00Z","date_published":"2026-03-24T14:00:00Z","id":"https://philliant.com/posts/20260324-left-join-effective-satellite-cte/","summary":"when an entity link to another hub is optional, a naive left join that pulls in an effective satellite in the same from list can explode or blur grain. i isolate the current effective row in a cte and left join that instead.","tags":["data vault","sql","effective satellite","left join","grain"],"title":"left join an effective satellite without duplicating rows (use a cte)","url":"https://philliant.com/posts/20260324-left-join-effective-satellite-cte/"},{"content_html":"\n\u003ch2 class=\"relative group\"\u003ethesis\n    \u003cdiv id=\"thesis\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#thesis\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei am a better thinker when i am not always on. screens pull me into a steady drip of input, and ai tools make it easy to stay in a loop of \u0026ldquo;just one more task\u0026rdquo; because the next answer always feels within reach. the counterweight is deliberate time away. spending time outside, in the yard, on a run, anywhere my attention is not being fed the next pixel is not just relaxation, it is a required input to productivity. in those stretches away from the screen, my mind does something i have come to call \u003cdfn\u003ebrain defrag\u003c/dfn\u003e, where thoughts drift, connect, and settle the way old disk defragmenters used to shuffle blocks until the filesystem looked sane again. that idle-looking time is not wasted, and it is part of how i produce anything worth shipping.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003econtext\n    \u003cdiv id=\"context\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#context\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003efor years the default workday has been a screen with a glowing rectangle of obligations. adding ai on top did not invent overwork, but it did lower the friction. there is always another prompt, another refinement, another pass that could make the artifact slightly better. the tool is so willing that stopping feels like leaving money on the table.\u003c/p\u003e\n\u003cp\u003ei notice the cost in my body before i notice it in my calendar. my eyes stay tired, my shoulders stay tight, and my thinking stays \u003cstrong\u003enoisy\u003c/strong\u003e like too many tabs open at once. when i get outside, especially for something physical, the noise changes to wind, dirt, footsteps, breathing. the channel is wider and slower. my brain quits trying to finish every sentence in real time. that is when the defrag feeling shows up.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eargument\n    \u003cdiv id=\"argument\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#argument\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003escreens train you to produce on demand\n    \u003cdiv id=\"screens-train-you-to-produce-on-demand\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#screens-train-you-to-produce-on-demand\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ea screen rewards continuous output. replies, commits, messages, scrolling. even \u0026ldquo;rest\u0026rdquo; on a screen is usually just another feed. and the message is always the same, if you are not typing or tapping, you are falling behind.\u003c/p\u003e\n\u003cp\u003ei do not buy that for creative or analytical work. sustained quality needs gaps where nothing is \u0026ldquo;done\u0026rdquo; yet. if every hour is a performance hour, there is no hour left for the quiet work of connecting ideas, no time for half-formed thoughts to strengthen without someone watching, no experiementing with new ideas.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003eai tightens the \u0026ldquo;one more\u0026rdquo; trap\n    \u003cdiv id=\"ai-tightens-the-one-more-trap\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#ai-tightens-the-one-more-trap\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eai assistants are useful because they answer fast and never need a break. the dark side is that the session never has to end. you can always ask for one more variant, one more edge case, one more rewrite. it feels like collaboration, so stopping feels rude, like walking out on a colleague mid-sentence.\u003c/p\u003e\n\u003cp\u003ei have to treat that as my problem to solve, not the tool\u0026rsquo;s. the ai is not going to tell me to stop. i have to close the laptop, mute everything, and accept that some problems are supposed to sit overnight, or at least until after a run.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ebrain defrag\n    \u003cdiv id=\"brain-defrag\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#brain-defrag\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ewhen i am raking, planting, hauling, or simply moving under open sky, my attention is not idle. it is \u003cstrong\u003eunscheduled\u003c/strong\u003e. ideas that were pinned under \u0026ldquo;urgent\u0026rdquo; can float. two half-formed notions from last week can bump into each other. a worry i suppressed because i was in flow can surface long enough to be named and filed.\u003c/p\u003e\n\u003cp\u003ethis feels like the old windows defrag visualization: scattered fragments slowly sliding into contiguous order. the cpu was not \u0026ldquo;doing nothing\u0026rdquo;, it was reorganizing so the machine could run faster afterward. i think mental work has the same requirement. you cannot compress insight into every minute of the day. some minutes have to be for rearrangement, not for output.\u003c/p\u003e\n\u003cp\u003ei am not claiming neuroscience labels here. i am naming a felt experience that i have encountered an uncountable number of times. if i grind on a hard problem, then step away long enough that my mind changes channel, i often return with a new angle. the solution was not missing because i lacked information, it was missing because my internal index was fragmented.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003erest is not the opposite of serious work\n    \u003cdiv id=\"rest-is-not-the-opposite-of-serious-work\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#rest-is-not-the-opposite-of-serious-work\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003egood work is not the sum of keystrokes. it depends on being rested enough to tell a good idea from a loud one. when i am under-slept and over-screened, i can still type plenty. what i lose is taste, patience, and the ability to notice that i am solving the wrong problem.\u003c/p\u003e\n\u003cp\u003erecovery is not a reward for finishing the sprint. it is a required input to the next sprint. the yard and the running shoes are part of the pipeline, not a luxury bolt-on.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003etension or counterpoint\n    \u003cdiv id=\"tension-or-counterpoint\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#tension-or-counterpoint\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003enot everyone has a yard, safe streets to run, or a schedule that allows a long unplug. \u0026ldquo;go outside\u0026rdquo; can sound tone-deaf when life is caregiving, long work shifts, or a second job. regardless of how you choose to do it, what i mean is that \u003cstrong\u003eyou still need unstructured attention sometimes\u003c/strong\u003e, even if the form is a walk around the block, a shower with no podcast, or ten minutes staring at a ceiling without a phone. the defrag metaphor is about protected mental slack, not about the specific activity or location.\u003c/p\u003e\n\u003cp\u003ethe other honest objection is guilt. stepping away can feel like slacking when deadlines press. i feel that too. but the counterpoint is that if i never defrag, i pay in mistakes, rework, and dull ideas. the spreadsheet likes continuous output, the brain does not.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eclosing\n    \u003cdiv id=\"closing\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#closing\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei am not trying to romanticize dirt under my fingernails or pretend every run is transcendent. sometimes it is just exercise. but the pattern holds true often enough that i trust it. struggle, leave, let the mind wander, come back. the best ideas frequently arrive in the gap. the same can be said about music, the spaces between the notes matter just as much as the notes you play.\u003c/p\u003e\n\u003cp\u003ethe \u003cdfn\u003ebrain defrag\u003c/dfn\u003e works often enough that i schedule for it the same way i schedule for sleep.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efurther reading\n    \u003cdiv id=\"further-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#further-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Incubation_%28psychology%29\"  target=\"_blank\" rel=\"noreferrer\"\u003eincubation (psychology)\u003c/a\u003e, overview of stepping away from a problem and returning with new insight\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Attention_restoration_theory\"  target=\"_blank\" rel=\"noreferrer\"\u003eattention restoration theory\u003c/a\u003e, research frame for how natural environments can recover directed attention\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated on this site\n    \u003cdiv id=\"related-on-this-site\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-on-this-site\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/series/commentary/\" \u003ecommentary series\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260320-deep-dive-ai-models-i-use/\" \u003edeep dive: the ai models i use\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260319-practical-ai-workflow-jira-github-mcp/\" \u003epractical ai workflow: jira, github, and mcp\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-20T21:30:00Z","date_published":"2026-03-20T21:30:00Z","id":"https://philliant.com/posts/20260320-brain-defrag-time-away-from-screens/","summary":"i argue that constant production and always-on tools work against clarity. yard work, runs, and boredom give my thoughts room to float, and that is when problems unlock after long struggle.","tags":["commentary","attention","rest","wellbeing","ai"],"title":"brain defrag: time away from screens (and from \"one more\" with ai)","url":"https://philliant.com/posts/20260320-brain-defrag-time-away-from-screens/"},{"content_html":"\u003cp\u003ei spend most of my working day using an ai assistant in cursor. the part that is easy to skip in public write-ups are the simpler details like which model name maps to which vendor, what each one is trying to be good at, and where i should not pretend it is interchangeable with the others.\u003c/p\u003e\n\u003cp\u003ethis post is that roster for me, written as of friday mar 20, 2026. i am not running benchmarks here. i am writing down how these models behave in my hands, with links so you can read the official specs if you want to explore further on your own. for why i treat multi-model routing as a production-era default, see \u003ca href=\"/posts/from-prototype-to-production-ai/\" \u003efrom prototype to production: my early adopter view of ai\u003c/a\u003e.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003esix models in my rotation right now: \u003cstrong\u003ecomposer 2\u003c/strong\u003e when i want cursor-native agentic work, \u003cstrong\u003egpt-5.3 codex xhigh\u003c/strong\u003e when i need serious implementation muscle, \u003cstrong\u003eclaude 4.6 opus max\u003c/strong\u003e when the problem is genuinely hard and i want anthropic thinking, \u003cstrong\u003egemini 3.1 pro\u003c/strong\u003e when the input is big or visual, \u003cstrong\u003egrok 4.20\u003c/strong\u003e when i am stuck and want a fresh perspective, and \u003cstrong\u003ekimi k2.5\u003c/strong\u003e when i want strong tool use from outside the usual three vendors.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eanyone already using cursor (or something similar) who wants to know what models are out there\u003c/li\u003e\n\u003cli\u003eengineers who do not want to watch an hour of launch videos to get a vendor map\u003c/li\u003e\n\u003cli\u003efuture me, six months from now, when half of these names have changed and i need to remember what i was actually using\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ecomparison table\n    \u003cdiv id=\"comparison-table\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#comparison-table\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethe table is the quick reference. the sections below are where i get honest about what each model is actually like to use.\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003emodel (as shown in my router)\u003c/th\u003e\n          \u003cth\u003emaker\u003c/th\u003e\n          \u003cth\u003especiality / intended use\u003c/th\u003e\n          \u003cth\u003epro / con\u003c/th\u003e\n          \u003cth\u003edocumentation\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003ecomposer-2\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003ecursor\u003c/td\u003e\n          \u003ctd\u003eagentic coding inside cursor: edits, terminal-shaped workflows, tool use\u003c/td\u003e\n          \u003ctd\u003epro: built for the editor; strong on long-horizon tasks with summarization training. con: not a portable api model in my mental model; i think of it as an environment capability, not a generic llm\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://cursor.com/docs/models/cursor-composer-2\"  target=\"_blank\" rel=\"noreferrer\"\u003ecomposer 2 model page\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003egpt-5.3-codex-xhigh\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eopenai\u003c/td\u003e\n          \u003ctd\u003eagentic coding via the codex line; the \u003ccode\u003exhigh\u003c/code\u003e suffix is how my router encodes a higher reasoning effort preset on top of the codex family\u003c/td\u003e\n          \u003ctd\u003epro: excellent when i want careful refactors and api-shaped thinking. con: slower and more expensive than \u0026ldquo;just answer fast\u0026rdquo; tiers; easy to overuse on trivia\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://developers.openai.com/api/docs/models/gpt-5-codex\"  target=\"_blank\" rel=\"noreferrer\"\u003egpt-5-codex model\u003c/a\u003e, \u003ca href=\"https://developers.openai.com/codex\"  target=\"_blank\" rel=\"noreferrer\"\u003ecodex product hub\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eclaude-4.6-opus-max\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eanthropic\u003c/td\u003e\n          \u003ctd\u003emaximum depth sonnet-family reasoning when latency is a fair price\u003c/td\u003e\n          \u003ctd\u003epro: best anthropic option in my rotation for subtle bugs, spec ambiguity, and multi-file coherence. con: the cost and latency are real; i save it for work that deserves the tax\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://docs.anthropic.com/en/docs/about-claude/models\"  target=\"_blank\" rel=\"noreferrer\"\u003eclaude models overview\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003egemini-3.1-pro\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003egoogle\u003c/td\u003e\n          \u003ctd\u003eflagship gemini tier for long context and strong multimodal reasoning in the gemini stack\u003c/td\u003e\n          \u003ctd\u003epro: great when i am dragging in screenshots, pdf-shaped context, or very wide file sets. con: vendor-specific quirks still matter; i verify critical logic instead of trusting vibe\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://ai.google.dev/gemini-api/docs/models\"  target=\"_blank\" rel=\"noreferrer\"\u003egemini models\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003egrok-4-20\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003exai\u003c/td\u003e\n          \u003ctd\u003egrok 4 family reasoning with the 4.20 snapshot naming xai uses in api surfaces\u003c/td\u003e\n          \u003ctd\u003epro: useful second opinion when i feel anchored to one vendor\u0026rsquo;s \u0026ldquo;house style\u0026rdquo;. con: i treat cutting-edge models as higher variance until i have personal calibration data\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://docs.x.ai/docs/introduction/\"  target=\"_blank\" rel=\"noreferrer\"\u003exai api introduction\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003ekimi-k2.5\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003emoonshot ai\u003c/td\u003e\n          \u003ctd\u003ekimi k2 line tuned for coding, math-style reasoning, and tool calling on moonshot\u0026rsquo;s platform\u003c/td\u003e\n          \u003ctd\u003epro: strong when i want mixture-of-experts-style efficiency stories and a different training prior than the usual us trio. con: operational details (regions, billing, rate limits) are another console to respect\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://platform.moonshot.ai/docs/guide/start-using-kimi-api\"  target=\"_blank\" rel=\"noreferrer\"\u003ekimi api quickstart\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003ch2 class=\"relative group\"\u003e\u003ccode\u003ecomposer-2\u003c/code\u003e (cursor)\n    \u003cdiv id=\"composer-2-cursor\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#composer-2-cursor\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ecomposer 2 is cursor\u0026rsquo;s house model for agentic work such as file edits, tool calls, and terminal workflows. it does not feel like chatting with an llm. it feels like the editor itself got smarter.\u003c/p\u003e\n\u003cp\u003ei use it when the task lives in the repo: multi-step refactors, searching across the workspace, long sessions where i do not want to re-explain context every ten minutes. i do not think of it as an api model i happen to access through cursor. it is more like a capability of the editor itself.\u003c/p\u003e\n\u003cp\u003ethe official docs say it is tuned for tool use and long horizons. that matches what i see.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003e\u003ccode\u003egpt-5.3-codex-xhigh\u003c/code\u003e (openai)\n    \u003cdiv id=\"gpt-53-codex-xhigh-openai\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#gpt-53-codex-xhigh-openai\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethis is my \u0026ldquo;i need the ai to really think about this\u0026rdquo; slot on the openai side. the public docs call the family gpt-5-codex; the \u003ccode\u003e5.3\u003c/code\u003e and \u003ccode\u003exhigh\u003c/code\u003e parts are how my router encodes the version and reasoning effort. your account might show a different string.\u003c/p\u003e\n\u003cp\u003ei use it when the work is code-heavy and i want the model to show its reasoning, not just spit out an answer. it shines when the change touches contracts, apis, types, migrations, or anything where a wrong assumption quietly spreads.\u003c/p\u003e\n\u003cp\u003ethe downside is obvious: it is slower and more expensive, and it tempts me into using a sledgehammer on a thumbtack.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003e\u003ccode\u003eclaude-4.6-opus-max\u003c/code\u003e (anthropic)\n    \u003cdiv id=\"claude-46-opus-max-anthropic\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#claude-46-opus-max-anthropic\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethis is my only anthropic route right now and i save it for the hard stuff: security-sensitive code, tricky concurrency, specs that contradict themselves, and problems where i want the model to slow down and really chew on it.\u003c/p\u003e\n\u003cp\u003ethe trade-off is cost and patience. opus is not \u0026ldquo;better\u0026rdquo; at everything. it is better at the things where i would otherwise redo the work three times trying to get it right with a faster model.\u003c/p\u003e\n\u003cp\u003ei check anthropic\u0026rsquo;s model pages periodically because vendors bump versions quietly and my router changes behavior without telling me.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003e\u003ccode\u003egemini-3.1-pro\u003c/code\u003e (google)\n    \u003cdiv id=\"gemini-31-pro-google\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#gemini-31-pro-google\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003egemini is where i go when the input is not just code. screenshots, long mixed documents, big file sets, and that is where the pro tier earns its keep for me.\u003c/p\u003e\n\u003cp\u003esame review standard applies though. if the answer involves auth, money, or data integrity, the model is writing drafts, not making decisions. i sign off. always.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003e\u003ccode\u003egrok-4-20\u003c/code\u003e (xai)\n    \u003cdiv id=\"grok-4-20-xai\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#grok-4-20-xai\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003egrok is my \u0026ldquo;break the pattern\u0026rdquo; model. when i have been staring at the same bug through two other model families and getting nowhere, throwing it at a third set of priors sometimes finds the thing i missed faster than another hour of printf debugging.\u003c/p\u003e\n\u003cp\u003ei keep my expectations honest though. this model does not compete with the above flagship models, but it sometimes i even find value in seeing what it gets wrong which prompts a better question for me to ask to one of the better models. it is kind of like using microsoft edge to download google chrome.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003e\u003ccode\u003ekimi-k2.5\u003c/code\u003e (moonshot ai)\n    \u003cdiv id=\"kimi-k25-moonshot-ai\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#kimi-k25-moonshot-ai\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ekimi k2.5 is my pick when i want strong coding and tool calling from outside the usual us vendor trio. moonshot makes it easy to try because their endpoints are openai-compatible, so i do not have to rewire everything to test it.\u003c/p\u003e\n\u003cp\u003ei only keep a model in rotation to make sure i do not \u003cstrong\u003ealways\u003c/strong\u003e only use the same two or three models. otherwise it just collects dust.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ehow i actually pick (it is not scientific)\n    \u003cdiv id=\"how-i-actually-pick-it-is-not-scientific\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#how-i-actually-pick-it-is-not-scientific\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003elots of files, lots of tool calls → composer 2\u003c/li\u003e\n\u003cli\u003ehard code problem, i want to see the reasoning → codex xhigh or opus max, depending on whether i want openai-flavored or anthropic-flavored thinking\u003c/li\u003e\n\u003cli\u003ebig context window or images involved → gemini 3.1 pro\u003c/li\u003e\n\u003cli\u003ei have been going in circles for an hour → grok or kimi for a fresh set of eyes\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003edo you run all six every day?\n    \u003cdiv id=\"do-you-run-all-six-every-day\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#do-you-run-all-six-every-day\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eno. most days it is 90% gpt-5-codex. the full roster is there for when i need it, and over time i have built up a mental map of which model tends to do well on which kind of task.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003eshould i copy this exact list?\n    \u003cdiv id=\"should-i-copy-this-exact-list\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#should-i-copy-this-exact-list\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eplease do not. if you are not living inside an agentic editor all day, half of this will not make sense for your workflow. honestly, one fast model and one deep model will cover most people. add a third only if you keep running into the same wall.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/docs/\"  target=\"_blank\" rel=\"noreferrer\"\u003ecursor documentation home\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://developers.openai.com/api/docs/overview\"  target=\"_blank\" rel=\"noreferrer\"\u003eopenai developer documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.anthropic.com/en/home\"  target=\"_blank\" rel=\"noreferrer\"\u003eanthropic claude documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://ai.google.dev/gemini-api/docs\"  target=\"_blank\" rel=\"noreferrer\"\u003egoogle ai for developers (gemini)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.x.ai/docs/introduction/\"  target=\"_blank\" rel=\"noreferrer\"\u003exai developer documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://platform.moonshot.ai/docs\"  target=\"_blank\" rel=\"noreferrer\"\u003emoonshot kimi api platform\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260318-from-prototype-to-production-ai/\" \u003efrom prototype to production: my early adopter view of ai\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260313-my-cursor-setup/\" \u003emy cursor setup\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260319-practical-ai-workflow-jira-github-mcp/\" \u003ea practical ai workflow: jira, github, and mcp\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/series/ai/\" \u003eai series\u003c/a\u003e, the rest of the arc in one place\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-20T17:45:00Z","date_published":"2026-03-20T17:45:00Z","id":"https://philliant.com/posts/20260320-deep-dive-ai-models-i-use/","summary":"i walk through composer-2, gpt-5.3-codex-xhigh, claude 4.6 opus, gemini 3.1 pro, grok-4-20, and kimi-k2.5 with a comparison table plus longer notes on how i actually use each one.","tags":["ai","cursor","models","workflow","llm"],"title":"deep dive: the ai models i use","url":"https://philliant.com/posts/20260320-deep-dive-ai-models-i-use/"},{"content_html":"\u003cp\u003ei spend a lot of time in cursor with an ai assistant beside me, using the workspace and mcp layout i described in \u003ca href=\"/posts/my-cursor-setup/\" \u003emy cursor setup\u003c/a\u003e. for a while i thought the path to better outputs was better prompts. it was not. the thing that actually moved the needle was connecting the assistant to the systems my team already uses as source of truth like jira for issue tracking and github for prs and code review.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei use \u003ca href=\"https://modelcontextprotocol.io\"  target=\"_blank\" rel=\"noreferrer\"\u003emodel context protocol\u003c/a\u003e (mcp) servers for jira and github inside my editor. i start from templates (that i created with ai assistance), have the ai draft a proper issue from my rough notes, and then reuse that same narrative in the pull request with cross-links. the documentation sounds like overhead, but it is actually what makes later ai sessions work better, and every future model reads from the same source of truth instead of guessing.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eengineers already living in jira and github who are tired of copy-pasting between tabs\u003c/li\u003e\n\u003cli\u003eanyone doing multi-step ai work where the second session has no idea what the first one decided\u003c/li\u003e\n\u003cli\u003eteams that care about reviewable intent, not just the final diff\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ethe loop in plain terms\n    \u003cdiv id=\"the-loop-in-plain-terms\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-loop-in-plain-terms\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003ei set up mcp integrations so the assistant can create and update issues and pull requests without me retyping metadata.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ei describe what i want in rough bullets:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003egoals\u003c/li\u003e\n\u003cli\u003erisks\u003c/li\u003e\n\u003cli\u003eopen questions\u003c/li\u003e\n\u003cli\u003elinks\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ethe ai maps that onto my issue template so the fields read like something a human reviewer would thank me for.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ei point the same assistant (or a fresh chat) at the issue as the source of truth while it implements. the issue holds scope, acceptance checks, and explicit out-of-scope notes.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ewhen the branch is ready, i have the ai open or update the pull request using a second template which will document everything including the summary, how to test, risk, and a link back to the issue.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003ethe whole idea is \u003cstrong\u003eone narrative in the places my team already looks\u003c/strong\u003e, instead of three slightly different versions of the story scattered across slack, a comment thread, and a scratch file on my desktop.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhy templates matter more with ai\n    \u003cdiv id=\"why-templates-matter-more-with-ai\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#why-templates-matter-more-with-ai\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei know templates look bureaucratic. but a template is really just a schema. the ai fills in structured sections way more reliably than it invents structure on its own from a blank page. my templates bake in what \u0026ldquo;done\u0026rdquo; means, what reviewers should check, and where the links go.\u003c/p\u003e\n\u003cp\u003eand another point on the schema that a template creates is that if it is used by everyone in the team, to reiterate a point from \u003ca href=\"/posts/starter-templates-for-ai-rules-skills-and-commands/\" \u003estarter templates for ai rules, skills, and commands\u003c/a\u003e, the common, constant format makes human reading and reviewing much easier, faster, and accurate.\u003c/p\u003e\n\u003cp\u003ewhen the ai drafts the issue first, this all leads to something i can actually read and edit in seconds, with a clear title, scoped description, and test notes, instead of staring at a blank text box trying to remember what i, or my teammates, meant.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003emcp as the glue\n    \u003cdiv id=\"mcp-as-the-glue\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#mcp-as-the-glue\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ewithout live tool access, the assistant is guessing for any information that you did not explicity provide. it does not know the ticket number, the labels, or whether a pull request already exists. with mcp, it can actually look those things up, apply the template, and keep identifiers straight.\u003c/p\u003e\n\u003cp\u003ethat sounds small, but it kills an entire category of mistakes like wrong links, stale titles, descriptions that drifted from what the code actually does. reviewers see consistent intent instead of hunting for mismatches, and the next ai session can re-fetch the real object in its current state instead of relying on whatever was in chat history.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ethe meta move: let the ai brief the next ai\n    \u003cdiv id=\"the-meta-move-let-the-ai-brief-the-next-ai\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-meta-move-let-the-ai-brief-the-next-ai\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ehere is the single habit that made the biggest difference. before i switch contexts (new chat, sub-agent, long implementation pass), i ask the current model to document everything that was done in the jira issue. i treat that block like a handoff document between shifts. then, subsequent iterations can read the issue to see what was done, were it was left, and know what it needs to do next to continue the task (because it was well-defined with done criteria at the start because of the template).\u003c/p\u003e\n\u003cp\u003ethe ai is surprisingly good at this. it takes a messy conversation and compresses it into a clean set of instructions that the next session can pick up and run with. no rediscovering the plan, no \u0026ldquo;where was i?\u0026rdquo;.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003etrade-offs i accept\n    \u003cdiv id=\"trade-offs-i-accept\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#trade-offs-i-accept\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003esetting up mcp and templates takes real time upfront, but it pays for itself after just a few real tasks\u003c/li\u003e\n\u003cli\u003ei still read every issue and pull request before it goes out. the ai writes the first draft, and i decide if it ships\u003c/li\u003e\n\u003cli\u003efor a two-line fix, i skip the full ceremony. that is fine. not everything needs a process\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003edoes this slow you down on tiny changes?\n    \u003cdiv id=\"does-this-slow-you-down-on-tiny-changes\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#does-this-slow-you-down-on-tiny-changes\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003esometimes, yes. for a trivial low-risk change i skip the heavy template. but if there is any chance someone (including future me) will need to understand what happened six months from now, i use the full loop.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat if the issue and the code drift apart?\n    \u003cdiv id=\"what-if-the-issue-and-the-code-drift-apart\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-if-the-issue-and-the-code-drift-apart\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ei treat that as a bug. if scope changes during implementation, i update the issue first, then the pull request. the ai can actually do that sync for me if i ask it to, for example \u0026ldquo;update the issue description to match what the code actually does now\u0026rdquo;.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://modelcontextprotocol.io\"  target=\"_blank\" rel=\"noreferrer\"\u003emodel context protocol\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/docs/mcp\"  target=\"_blank\" rel=\"noreferrer\"\u003emcp in cursor\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260318-from-prototype-to-production-ai/\" \u003efrom prototype to production: my early adopter view of ai\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260313-my-cursor-setup/\" \u003emy cursor setup\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-19T18:30:00Z","date_published":"2026-03-19T18:30:00Z","id":"https://philliant.com/posts/20260319-practical-ai-workflow-jira-github-mcp/","summary":"i connect my editor to jira and github through mcp, create well-structured issues from templates before coding, and reuse that text in pull requests so every agent in the chain has the same ground truth.","tags":["ai","cursor","mcp","jira","github","workflow","documentation"],"title":"a practical ai workflow: jira, github, and mcp","url":"https://philliant.com/posts/20260319-practical-ai-workflow-jira-github-mcp/"},{"content_html":"\u003cp\u003ei have been an early adopter of new technology for all of my career, and ai has been one of the fastest shifts i have seen.\u003c/p\u003e\n\u003cp\u003eat first, ai felt \u0026ldquo;cool / neat / useful on the side\u0026rdquo;. i used it for first drafts, rough ideas, and quick experiments. and to expand \u0026ldquo;on-the-side\u0026rdquo;, it was a stand-alone tool, separate from other applications. i had to copy/paste questions and answers back and forth between the ai and my workspace.\u003c/p\u003e\n\u003cp\u003enow, it is different.\u003c/p\u003e\n\u003cp\u003eai is no longer just a sidekick in my workflow. it is powerful enough to be production-usable when paired with the right guardrails, review loops, and system design. plus, these capabilities are integrated directly into all of the tools, applications, and websites i use daily.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eai is not a side tool anymore. the benchmarks are better, inference is cheaper, and companies are actually using it in production, not just piloting it. in my own work, i stopped treating it as one model for everything and started routing different models to different jobs. the concrete roster i use in practice is in \u003ca href=\"/posts/deep-dive-ai-models-i-use/\" \u003edeep dive: the ai models i use\u003c/a\u003e.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eleaders wondering whether ai is actually ready for real workloads (not just demos)\u003c/li\u003e\n\u003cli\u003eengineers figuring out which model to use for what\u003c/li\u003e\n\u003cli\u003eteams trying to keep quality high without the bill getting ridiculous\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ethe evidence: 1 year ago, 6 months ago, and now\n    \u003cdiv id=\"the-evidence-1-year-ago-6-months-ago-and-now\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-evidence-1-year-ago-6-months-ago-and-now\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eif someone asked me \u0026ldquo;why do you trust it more now?\u0026rdquo;, the honest answer is that i have been using this stuff daily for a while, and the outputs are just better than they were a year ago. that is anecdotal. but the benchmarks back it up:\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003ewhen\u003c/th\u003e\n          \u003cth\u003estudy\u003c/th\u003e\n          \u003cth\u003estat that stood out to me\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e~1 year ago (2025)\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://hai.stanford.edu/ai-index/2025-ai-index-report\"  target=\"_blank\" rel=\"noreferrer\"\u003estanford ai index 2025\u003c/a\u003e\u003c/td\u003e\n          \u003ctd\u003ebenchmark gains in one year were large: \u003cstrong\u003e+18.8\u003c/strong\u003e (MMMU), \u003cstrong\u003e+48.9\u003c/strong\u003e (GPQA), and \u003cstrong\u003e+67.3\u003c/strong\u003e (swe-bench) percentage points\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e~6 months ago (sep 2025)\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://arxiv.org/abs/2509.11106\"  target=\"_blank\" rel=\"noreferrer\"\u003efluid language model benchmarking (arxiv)\u003c/a\u003e\u003c/td\u003e\n          \u003ctd\u003eon MMLU, they report higher validity and lower variance with \u003cstrong\u003e50x fewer\u003c/strong\u003e evaluation items\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003emost recent i could find (feb 2026)\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://arxiv.org/abs/2602.15327\"  target=\"_blank\" rel=\"noreferrer\"\u003eprescriptive scaling reveals the evolution of language model capabilities (arxiv)\u003c/a\u003e\u003c/td\u003e\n          \u003ctd\u003eanalysis used \u003cstrong\u003e5,000\u003c/strong\u003e observational + \u003cstrong\u003e2,000\u003c/strong\u003e new model-performance points, and found math-reasoning frontiers are still advancing over time\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003ethe part that gets me is not just that models are getting better, it is that we are also getting better at measuring whether they are actually better. both things improving at the same time is what makes me trust the trend.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003emore companies have models now\n    \u003cdiv id=\"more-companies-have-models-now\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#more-companies-have-models-now\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethis is not just a tech story. the org charts moved too.\u003c/p\u003e\n\u003cp\u003ethe \u003ca href=\"https://hai.stanford.edu/ai-index/2025-ai-index-report/economy\"  target=\"_blank\" rel=\"noreferrer\"\u003estanford ai index 2025 economy chapter\u003c/a\u003e reports that:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eorganizational ai use rose from \u003cstrong\u003e55% (2023)\u003c/strong\u003e to \u003cstrong\u003e78% (2024)\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003egenai use in at least one business function rose from \u003cstrong\u003e33%\u003c/strong\u003e to \u003cstrong\u003e71%\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eand at the model-building layer, the same report notes that nearly \u003cstrong\u003e90%\u003c/strong\u003e of notable ai models in 2024 came from industry (up from \u003cstrong\u003e60%\u003c/strong\u003e in 2023). companies are not just buying models anymore, they are building them. that shift matters.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ehow models have evolved\n    \u003cdiv id=\"how-models-have-evolved\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#how-models-have-evolved\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethe story is not \u0026ldquo;bigger model = better model\u0026rdquo; anymore. it got more interesting than that:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://arxiv.org/abs/2503.01996\"  target=\"_blank\" rel=\"noreferrer\"\u003eONERULER (mar 2025)\u003c/a\u003e showed long-context multilingual performance can swing by up to \u003cstrong\u003e20%\u003c/strong\u003e depending on instruction language, and english was only \u003cstrong\u003e6th of 26\u003c/strong\u003e languages in their setup\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://arxiv.org/abs/2601.02872\"  target=\"_blank\" rel=\"noreferrer\"\u003elongbench pro (jan 2026)\u003c/a\u003e evaluated \u003cstrong\u003e46\u003c/strong\u003e long-context models over \u003cstrong\u003e1,500\u003c/strong\u003e real long-context samples and found long-context optimization can matter more than raw parameter scaling\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://arxiv.org/abs/2602.15327\"  target=\"_blank\" rel=\"noreferrer\"\u003eprescriptive scaling (feb 2026)\u003c/a\u003e suggests some capability boundaries are stabilizing, while math reasoning keeps moving forward\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ewhat i take from all of this: \u0026ldquo;what is the best model?\u0026rdquo; is the wrong question now. the right question is \u0026ldquo;best model for what?\u0026rdquo;.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ehow model usage has evolved (including slms)\n    \u003cdiv id=\"how-model-usage-has-evolved-including-slms\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#how-model-usage-has-evolved-including-slms\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethe way i use models has changed as much as the models themselves.\u003c/p\u003e\n\u003cp\u003ebefore, i used one large model for almost everything. now, i use a system:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003elarger models for hard reasoning, large requests, and high-stakes trade-offs\u003c/li\u003e\n\u003cli\u003esmaller/faster models for mechanical edits or asking basic questions\u003c/li\u003e\n\u003cli\u003ethis helps balance cost, latency, and quality\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ethis is exactly where small language models (slms) come in, and why i think they matter more than most people give them credit for.\u003c/p\u003e\n\u003cp\u003ethe \u003ca href=\"https://hai.stanford.edu/ai-index/2025-ai-index-report\"  target=\"_blank\" rel=\"noreferrer\"\u003estanford ai index 2025\u003c/a\u003e highlights that inference cost for gpt-3.5-level performance dropped by over \u003cstrong\u003e280x\u003c/strong\u003e between nov 2022 and oct 2024, driven partly by more efficient model options.\u003c/p\u003e\n\u003cp\u003eand the slm research ecosystem is catching up quickly:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://arxiv.org/abs/2508.15478\"  target=\"_blank\" rel=\"noreferrer\"\u003eslm-bench (2025)\u003c/a\u003e benchmarked \u003cstrong\u003e15\u003c/strong\u003e slms across \u003cstrong\u003e9\u003c/strong\u003e tasks, \u003cstrong\u003e23\u003c/strong\u003e datasets, and \u003cstrong\u003e11\u003c/strong\u003e metrics (accuracy, compute, and consumption)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://arxiv.org/abs/2601.07790\"  target=\"_blank\" rel=\"noreferrer\"\u003ethis 2026 slm/srlm benchmark\u003c/a\u003e reported a \u003cstrong\u003e4b\u003c/strong\u003e model reaching \u003cstrong\u003e95.64%\u003c/strong\u003e on a log-severity task with RAG, while a \u003cstrong\u003e0.6b\u003c/strong\u003e model still reached \u003cstrong\u003e88.12%\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003efor me, the shift is going from \u0026ldquo;one model for everything\u0026rdquo; to a \u0026ldquo;roster of models to pick the right player for the job\u0026rdquo;.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eai agents are now inside nearly every tool i use\n    \u003cdiv id=\"ai-agents-are-now-inside-nearly-every-tool-i-use\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#ai-agents-are-now-inside-nearly-every-tool-i-use\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ea year or two ago, \u0026ldquo;ai in my tool\u0026rdquo; meant autocomplete or a chat sidebar you forgot about after a week. that changed. in my day-to-day as a data engineer, ai now shows up in basically every tool i touch, and it actually does useful work.\u003c/p\u003e\n\u003cp\u003ewhat that looks like in practice:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003emy code editor reads the repo, proposes multi-file edits, runs checks, and explains what it changed. it is not just finishing my sentences anymore\u003c/li\u003e\n\u003cli\u003esource control and review tools help me draft pull requests, summarize diffs, and flag the risky parts before a reviewer has to\u003c/li\u003e\n\u003cli\u003eticketing and docs tools turn my rough brain dump into structured requirements and keep threads summarized so i do not have to re-read 47 messages\u003c/li\u003e\n\u003cli\u003edata tools (sql editors, dbt, warehouse observability) help with query drafts, lineage questions, test ideas, and figuring out why a pipeline broke at 3am\u003c/li\u003e\n\u003cli\u003emore and more of my operational workflows are bounded loops that the ai runs end-to-end while i review results\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ethe bigger picture is that tools used to wait for me to click a button. now agents work alongside me toward an outcome. this is what i call \u003cdfn\u003ehuman+\u003c/dfn\u003e.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eclosing thought\n    \u003cdiv id=\"closing-thought\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#closing-thought\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei am still an early adopter. that has not changed. what changed is why i keep using it. it is not because ai is shiny or new. it is because it actually helps with real work when you set it up right.\u003c/p\u003e\n\u003cp\u003ethe phase where i had to convince people \u0026ldquo;no really, this is useful\u0026rdquo; is mostly over. the current phase, figuring out how to engineer it into production systems that do not break, is harder, and honestly more fun.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat is the most important takeaway from the benchmark trend?\n    \u003cdiv id=\"what-is-the-most-important-takeaway-from-the-benchmark-trend\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-is-the-most-important-takeaway-from-the-benchmark-trend\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eno single benchmark number is the story. the story is that the trend points the same direction across different benchmarks and different time windows. that consistency is what makes me think this is real progress, not just one lucky test result.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat is the practical operating model today?\n    \u003cdiv id=\"what-is-the-practical-operating-model-today\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-is-the-practical-operating-model-today\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003euse more than one model. hard problems and ambiguous decisions go to the big model. repetitive transforms, classification, and high-volume calls go to something faster and cheaper. add guardrails to both.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://hai.stanford.edu/ai-index/2025-ai-index-report\"  target=\"_blank\" rel=\"noreferrer\"\u003estanford ai index 2025\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://arxiv.org/abs/2602.15327\"  target=\"_blank\" rel=\"noreferrer\"\u003eprescriptive scaling reveals the evolution of language model capabilities\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://arxiv.org/abs/2601.02872\"  target=\"_blank\" rel=\"noreferrer\"\u003elongbench pro\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260320-deep-dive-ai-models-i-use/\" \u003edeep dive: the ai models i use\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260314-ai-br-ai-n-fr-ai/\" \u003eai br-ai-n fr-ai\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260314-how-to-use-ai-to-create-ai-rules-skills-and-commands/\" \u003ehow to use ai to create ai rules, skills, and commands\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-18T14:09:57Z","date_published":"2026-03-18T14:09:57Z","id":"https://philliant.com/posts/20260318-from-prototype-to-production-ai/","summary":"i have watched ai move from a prototype side assistant to an operational core system. this post shares that journey with time-stamped benchmark evidence and a practical view on where model usage is headed next.","tags":["ai","adoption","benchmarks","llm","slm","strategy"],"title":"from prototype to production: my early adopter view of ai","url":"https://philliant.com/posts/20260318-from-prototype-to-production-ai/"},{"content_html":"\u003cp\u003ein \u003ca href=\"/posts/how-to-use-ai-to-create-ai-rules-skills-and-commands/\" \u003ehow to use ai to create ai rules, skills, and commands\u003c/a\u003e, i made the case for having ai draft any artifacts that would be primarily used by ai.\u003c/p\u003e\n\u003cp\u003ethis post is the practical follow-up with generic templates you can copy, then adapt to your own constraints.\u003c/p\u003e\n\u003cp\u003ei kept the examples generic on purpose so you can drop them into whatever stack you are working in.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003etighter templates produce more consistent ai outputs. every time i add scope boundaries, ordered steps, and a clear definition of \u0026ldquo;done\u0026rdquo;, the same prompt works better across runs. the difference is not subtle.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eteams writing reusable ai operating instructions\u003c/li\u003e\n\u003cli\u003epeople seeing inconsistent results from weak prompt artifacts\u003c/li\u003e\n\u003cli\u003ereviewers who want predictable outputs with clearer acceptance checks\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ehow to use this post\n    \u003cdiv id=\"how-to-use-this-post\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#how-to-use-this-post\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003efor each artifact type, i show:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ea weak draft that usually creates inconsistent ai behavior\u003c/li\u003e\n\u003cli\u003ean improved draft that adds scope, constraints, and done criteria\u003c/li\u003e\n\u003cli\u003ea short explanation of why the quality improved in the second iteration\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003etemplate 1: rule files\n    \u003cdiv id=\"template-1-rule-files\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#template-1-rule-files\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003eweak draft (rule file)\n    \u003cdiv id=\"weak-draft-rule-file\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#weak-draft-rule-file\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-md\" data-lang=\"md\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# coding standards\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e follow team conventions\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- run checks before finishing\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003eimproved draft (rule file)\n    \u003cdiv id=\"improved-draft-rule-file\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#improved-draft-rule-file\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-md\" data-lang=\"md\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e---\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003edescription: \u0026#34;core implementation standards\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ealwaysApply: true\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e---\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# intent\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ekeep changes safe, scoped, and verifiable\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## scope\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e in scope: files directly related to the requested task\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e out of scope: broad refactors, unrelated cleanup, dependency upgrades unless explicitly requested\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## required behavior\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e preserve existing naming and architecture patterns\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e avoid modifying unrelated files\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e run validation checks for substantive edits\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e if a check fails, report the exact failure and likely cause\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## output requirements\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e explain what changed and why\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e list validations executed and outcomes\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- call out remaining risks or assumptions\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat improved (rule file)\n    \u003cdiv id=\"what-improved-rule-file\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-improved-rule-file\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethe second draft draws a line around what the ai should and should not touch, makes it run checks instead of just hoping for the best, and gives reviewers a predictable format which makes (human) scanning faster, easier, and more accurate.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003etemplate 2: skill files\n    \u003cdiv id=\"template-2-skill-files\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#template-2-skill-files\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003eweak draft (skill file)\n    \u003cdiv id=\"weak-draft-skill-file\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#weak-draft-skill-file\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-md\" data-lang=\"md\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# implement feature skill\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e1.\u003c/span\u003e read the task\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e2.\u003c/span\u003e implement the feature\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e3. test and finish\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003eimproved draft (skill file)\n    \u003cdiv id=\"improved-draft-skill-file\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#improved-draft-skill-file\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-md\" data-lang=\"md\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# scoped feature implementation skill\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## when to use\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e use when a feature request has clear acceptance criteria\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e do not use for open-ended brainstorming\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## required inputs\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e objective\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e acceptance criteria\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e constraints (performance, security, compatibility)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## workflow\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e1.\u003c/span\u003e restate scope and assumptions\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e2.\u003c/span\u003e inspect relevant code paths\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e3.\u003c/span\u003e implement the smallest complete change\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e4.\u003c/span\u003e add or update focused tests for changed behavior\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e5.\u003c/span\u003e run validation checks\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e6.\u003c/span\u003e summarize outcomes, risks, and follow-ups\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## done criteria\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e every acceptance criterion is mapped to an implementation result\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e validations pass or known failures are documented\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- no unrelated files are changed\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat improved (skill file)\n    \u003cdiv id=\"what-improved-skill-file\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-improved-skill-file\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethe second draft tells the ai when to use this skill, what information it needs upfront, what order to work in, and how to know when it is finished. that last part, done criteria, is the one most people skip, and it is the one that matters most.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003etemplate 3: command files\n    \u003cdiv id=\"template-3-command-files\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#template-3-command-files\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003eweak draft (command file)\n    \u003cdiv id=\"weak-draft-command-file\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#weak-draft-command-file\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-md\" data-lang=\"md\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eimplement a feature.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003edo the work and test it.\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003eimproved draft (command file)\n    \u003cdiv id=\"improved-draft-command-file\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#improved-draft-command-file\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-md\" data-lang=\"md\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eimplement a scoped feature with verification.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003erequired inputs:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e objective\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e scope\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e constraints\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eworkflow:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e1.\u003c/span\u003e restate scope before editing\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e2.\u003c/span\u003e implement minimal complete change\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e3.\u003c/span\u003e add or update focused tests\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e4.\u003c/span\u003e run validation checks\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e5.\u003c/span\u003e return concise change summary and risks\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003erequired behavior:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e modify only files needed for this objective\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e avoid unrelated refactors unless requested\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e keep interfaces stable unless requirement says otherwise\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eresponse format:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e scope confirmation\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e files changed with rationale\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e validation results\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- open risks or follow-ups\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat improved (command file)\n    \u003cdiv id=\"what-improved-command-file\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-improved-command-file\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethe vague version is basically \u0026ldquo;go do stuff\u0026rdquo;. the second version tells the ai exactly what it needs, how to work, and what shape the answer should take. it reads like a contract.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003etemplate 4: \u003ccode\u003eAGENTS.md\u003c/code\u003e\n    \u003cdiv id=\"template-4-agentsmd\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#template-4-agentsmd\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003eAGENTS.md\u003c/code\u003e is your project\u0026rsquo;s constitution. it sits at the root of your workspace and gives the ai the broad context it needs before it reads any specific rules or skills.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003eweak draft (\u003ccode\u003eAGENTS.md\u003c/code\u003e)\n    \u003cdiv id=\"weak-draft-agentsmd\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#weak-draft-agentsmd\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-md\" data-lang=\"md\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# project info\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ethis is a react and node app. we use postgres. write clean code.\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003eimproved draft (\u003ccode\u003eAGENTS.md\u003c/code\u003e)\n    \u003cdiv id=\"improved-draft-agentsmd\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#improved-draft-agentsmd\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-md\" data-lang=\"md\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# project context\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ethis is the \u003cspan class=\"sb\"\u003e`my-repo`\u003c/span\u003e workspace. it is a repository containing our data warehouse, backend services, and frontend ui.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## architecture\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e frontend: next.js (react)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e backend: nestjs (node)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e data: dbt on snowflake\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## core principles\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e1.\u003c/span\u003e the backend is the source of truth for business logic\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e2.\u003c/span\u003e data models must mirror backend entity definitions\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e3.\u003c/span\u003e do not duplicate types across boundaries, and use the shared schema package\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## available skills\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e use \u003cspan class=\"sb\"\u003e`create-dbt-model`\u003c/span\u003e when adding new analytics tables\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- use \u003cspan class=\"sb\"\u003e`sync-service-entity`\u003c/span\u003e when a backend migration affects the data warehouse\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat improved (\u003ccode\u003eAGENTS.md\u003c/code\u003e)\n    \u003cdiv id=\"what-improved-agentsmd\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-improved-agentsmd\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethe second version gives the ai a map. instead of \u0026ldquo;write clean code\u0026rdquo; (which means nothing), it explains how the pieces of the codebase relate and tells the ai which skills to reach for when it hits common tasks. think of it as onboarding documentation, except the new hire is an llm.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ehow to test your new templates\n    \u003cdiv id=\"how-to-test-your-new-templates\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#how-to-test-your-new-templates\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003edo not just commit a new rule and hope for the best. test it (duh).\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003ethe happy path test:\u003c/strong\u003e ask the ai to perform a standard task using the new skill. does it follow the steps in order? does it output the correct format?\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ethe boundary test:\u003c/strong\u003e ask the ai to do something explicitly forbidden by the rule\u0026rsquo;s scope (e.g., \u0026ldquo;refactor the database connection while you add this button\u0026rdquo;). a good rule will cause the ai to refuse the out-of-scope work.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ethe failure test:\u003c/strong\u003e introduce a deliberate syntax error in a file, then ask the ai to run its validation step. does it catch the error and report it according to your failure reporting expectations?\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eif the ai fails any of these tests, your constraints are not tight enough. go back to the template and make the boundaries more explicit.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003eweak draft to improved draft checklist\n    \u003cdiv id=\"weak-draft-to-improved-draft-checklist\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#weak-draft-to-improved-draft-checklist\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ewhen you improve any ai-facing artifact, check these six upgrades:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003edefine intent in one line\u003c/li\u003e\n\u003cli\u003edefine scope boundaries explicitly\u003c/li\u003e\n\u003cli\u003erequire ordered execution steps\u003c/li\u003e\n\u003cli\u003edefine done criteria\u003c/li\u003e\n\u003cli\u003estandardize output format\u003c/li\u003e\n\u003cli\u003einclude failure reporting expectations\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003ch2 class=\"relative group\"\u003eclosing note\n    \u003cdiv id=\"closing-note\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#closing-note\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eif you only take one thing from this post, make it scope boundaries. in my experience, almost every time the ai does something weird, the root cause is not the model. it is that nobody told the model where the walls are, so it makes up its own answer because, as we have discussed before, ai \u003cstrong\u003eALWAYS\u003c/strong\u003e has an answer.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003eshould i start with a rule, skill, or command template?\n    \u003cdiv id=\"should-i-start-with-a-rule-skill-or-command-template\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#should-i-start-with-a-rule-skill-or-command-template\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ewhichever one you reach for most often. for most people that is rules, because a good rule starts paying off immediately on every single run.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ehow do i know a template is ready for production use?\n    \u003cdiv id=\"how-do-i-know-a-template-is-ready-for-production-use\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#how-do-i-know-a-template-is-ready-for-production-use\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003erun it on a real task three ways:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ethe normal path\u003c/li\u003e\n\u003cli\u003esomething out of scope\u003c/li\u003e\n\u003cli\u003esomething deliberately broken\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eif the ai handles all three the way you would want, keep it. if not, the boundaries need tightening.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/docs/context/rules\"  target=\"_blank\" rel=\"noreferrer\"\u003erules in cursor\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/help/customization/skills\"  target=\"_blank\" rel=\"noreferrer\"\u003eskills in cursor\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260314-how-to-use-ai-to-create-ai-rules-skills-and-commands/\" \u003ehow to use ai to create ai rules, skills, and commands\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260313-my-cursor-setup/\" \u003emy cursor setup\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-15T11:00:00Z","date_published":"2026-03-15T11:00:00Z","id":"https://philliant.com/posts/20260315-starter-templates-for-ai-rules-skills-and-commands/","summary":"this follow-up post gives practical, generic templates you can adapt for rules, skills, and commands, plus side-by-side examples that show why tighter structure improves ai execution quality.","tags":["ai","cursor","rules","skills","commands","templates","workflow"],"title":"starter templates for ai rules, skills, and commands","url":"https://philliant.com/posts/20260315-starter-templates-for-ai-rules-skills-and-commands/"},{"content_html":"\u003cp\u003efor each rule, skill, and/or command, remember that they are mainly read by ai. thus, ai should, at least, draft the first version. then you can dial in the details from there. but this will give you a good starting point, and most notably, it will be written in the format the ai understands the best. you can just focus on making sure the content is correct. for copy-paste templates and weak versus improved examples, see \u003ca href=\"/posts/starter-templates-for-ai-rules-skills-and-commands/\" \u003estarter templates for ai rules, skills, and commands\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003ethat does not mean handing over ownership. i still define the goals, the boundaries, and what \u0026ldquo;good\u0026rdquo; looks like. the ai just takes that guidance and turns it into structured instructions that other ai runs can actually follow without drifting.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003esince ai is the one reading and following a rule, skill, or command, let ai write the first draft. you still own the truth, the boundaries, and what counts as \u0026ldquo;done\u0026rdquo;. but the formatting and structure? ai is better at writing for ai than you are, and that is fine.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eteams building reusable ai instructions for repeated workflows\u003c/li\u003e\n\u003cli\u003epeople who want cleaner ai execution with fewer ambiguous outputs\u003c/li\u003e\n\u003cli\u003ereviewers who need predictable artifact quality and safer constraints\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003edefinitions: rules vs. skills vs. commands\n    \u003cdiv id=\"definitions-rules-vs-skills-vs-commands\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#definitions-rules-vs-skills-vs-commands\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ebefore you ask ai to draft anything, it helps to know which bucket it belongs in. here is how i think about the three types:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003erules (\u003ccode\u003e.mdc\u003c/code\u003e files):\u003c/strong\u003e passive, always-on guardrails. use these for things the ai should \u003cem\u003enever\u003c/em\u003e do, or formatting it should \u003cem\u003ealways\u003c/em\u003e use. (e.g., \u0026ldquo;always use lowercase for markdown headings\u0026rdquo;.)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eskills (\u003ccode\u003eSKILL.md\u003c/code\u003e files):\u003c/strong\u003e active, multi-step runbooks. use these for complex processes that require a specific order of operations. (e.g., \u0026ldquo;how to scaffold a new dbt model and its tests\u0026rdquo;.)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ecommands (\u003ccode\u003e.md\u003c/code\u003e files):\u003c/strong\u003e trigger-based shortcuts. use these for quick, repetitive actions you want to fire off with a slash command. (e.g., \u0026ldquo;/review-pr\u0026rdquo; to run a specific review prompt.)\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ethe core idea\n    \u003cdiv id=\"the-core-idea\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-core-idea\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ematch the writer to the reader.\u003c/p\u003e\n\u003cp\u003eif ai is the one following the instructions, ai should write the first draft. in my experience it will:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003epick a format that is natural for ai to parse (\u003ccode\u003e.md\u003c/code\u003e, \u003ccode\u003e.mdc\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003edraw sharper lines around what the task is and is not\u003c/li\u003e\n\u003cli\u003espell out acceptance criteria i would have left vague\u003c/li\u003e\n\u003cli\u003eproduce fewer \u0026ldquo;wait, what do i do next?\u0026rdquo; gaps\u003c/li\u003e\n\u003cli\u003estay more consistent when the same artifact runs multiple times (repeatable across human users)\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhy this works in practice\n    \u003cdiv id=\"why-this-works-in-practice\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#why-this-works-in-practice\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003ethe format fits the reader\u003c/strong\u003e, ai writes instructions in a shape that other ai runs parse well, which is not surprising but it matters more than people expect\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eiteration is faster\u003c/strong\u003e, you can go from rough idea to usable draft in minutes instead of agonizing over wording from a blank page\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ethe scaffolding is more complete\u003c/strong\u003e, ai is annoyingly good at remembering to include constraints, edge cases, and verification steps that i would skip\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ereuse gets easier\u003c/strong\u003e, once a rule or skill format works, you can stamp out the same pattern for a different task or a different repo without starting over\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhere humans stay in charge\n    \u003cdiv id=\"where-humans-stay-in-charge\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#where-humans-stay-in-charge\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethe human still decides:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ewhat problem we are actually solving\u003c/li\u003e\n\u003cli\u003ewhat is in scope and what is not\u003c/li\u003e\n\u003cli\u003ewhat \u0026ldquo;good\u0026rdquo; looks like\u003c/li\u003e\n\u003cli\u003ewhich risks are not acceptable\u003c/li\u003e\n\u003cli\u003ewhether the final version ships\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ethe ai writes. i approve. this boundary is non-negotiable for me.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003estarter workflow you can use\n    \u003cdiv id=\"starter-workflow-you-can-use\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#starter-workflow-you-can-use\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003ewrite a short human brief: objective, scope, constraints, and examples\u003c/li\u003e\n\u003cli\u003eask ai to draft the rule/skill/command in a strict template\u003c/li\u003e\n\u003cli\u003ereview for accuracy, ambiguity, missing constraints, and unsafe assumptions\u003c/li\u003e\n\u003cli\u003efeed corrections back and ask for a tighter second draft\u003c/li\u003e\n\u003cli\u003etest it on one real task\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eONLY\u003c/strong\u003e keep the artifact if the final state adds direct, consistent value\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBE CAREFUL\u003c/strong\u003e to not create too many rules just for ceremony\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003ch3 class=\"relative group\"\u003eexample of the human brief\n    \u003cdiv id=\"example-of-the-human-brief\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#example-of-the-human-brief\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ethis does not need to be polished. i treat it as a brain dump about what you want.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003ehuman brief:\u003c/strong\u003e \u0026ldquo;i need a skill for adding a new api endpoint. it needs to update the openapi spec first, then create the controller, then write a failing test. do not let it touch the database layer\u0026rdquo;.\u003c/p\u003e\n\u003cp\u003ethe ai will take this messy sentence and turn it into a structured markdown file with clear trigger conditions, step-by-step instructions, and explicit out-of-scope boundaries.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003emaintenance and decay\n    \u003cdiv id=\"maintenance-and-decay\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#maintenance-and-decay\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eai instructions rot over time. as your project evolves, the rules that worked in march will start causing friction in august.\u003c/p\u003e\n\u003cp\u003ehow to spot decay:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ethe ai starts apologizing and saying \u0026ldquo;i will follow the rule next time\u0026rdquo; (but it did not this time)\u003c/li\u003e\n\u003cli\u003eyou find yourself manually overriding the ai\u0026rsquo;s output on a specific task\u003c/li\u003e\n\u003cli\u003ethe rule references files or folders that have been renamed\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ewhen this happens, do not just tweak the rule manually. feed the broken rule back to the ai, explain \u003cem\u003ewhy\u003c/em\u003e it is failing, and ask it to generate an updated draft. i regularly add a note at the end of my prompts that says something like \u0026ldquo;please update any relevant documentation\u0026rdquo;.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ecommon failure mode\n    \u003cdiv id=\"common-failure-mode\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#common-failure-mode\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethe biggest way this goes wrong is when ai starts \u003cem\u003emaking up\u003c/em\u003e policy instead of encoding \u003cem\u003eyour policy\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003ehere is the thing about ai, it always has an answer. always. so if your intent is vague, the ai will not stop and ask, and it will just guess. and confident guesses that are wrong are worse than no answer at all.\u003c/p\u003e\n\u003cp\u003emy rule is to get the truth right first. let ai worry about the formatting second.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003enext post\n    \u003cdiv id=\"next-post\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#next-post\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ehere is a follow-up with concrete starter templates plus weak-draft \u0026gt; improved-draft examples:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260315-starter-templates-for-ai-rules-skills-and-commands/\" \u003estarter templates for ai rules, skills, and commands\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat should i optimize first: format or policy?\n    \u003cdiv id=\"what-should-i-optimize-first-format-or-policy\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-should-i-optimize-first-format-or-policy\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003epolicy, every time. if the policy is vague, a beautifully formatted rule just makes the wrong behavior repeat faster and with more confidence.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhen should i not use this method?\n    \u003cdiv id=\"when-should-i-not-use-this-method\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#when-should-i-not-use-this-method\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ewhen you are still figuring out what you even want. if requirements are fuzzy, start with human conversation. do not convert anything into a structured artifact until you actually know where the walls are.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/docs/context/rules\"  target=\"_blank\" rel=\"noreferrer\"\u003erules in cursor\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/help/customization/skills\"  target=\"_blank\" rel=\"noreferrer\"\u003eskills in cursor\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260315-starter-templates-for-ai-rules-skills-and-commands/\" \u003estarter templates for ai rules, skills, and commands\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260313-my-cursor-setup/\" \u003emy cursor setup\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-14T18:15:00Z","date_published":"2026-03-14T18:15:00Z","id":"https://philliant.com/posts/20260314-how-to-use-ai-to-create-ai-rules-skills-and-commands/","summary":"this kickoff post explains why ai-authored rule, skill, and command scaffolds are often clearer for ai execution, and how to keep humans in control with constraints, reviews, and acceptance checks.","tags":["ai","cursor","rules","skills","commands","workflow"],"title":"how to use ai to create ai rules, skills, and commands","url":"https://philliant.com/posts/20260314-how-to-use-ai-to-create-ai-rules-skills-and-commands/"},{"content_html":"\u003cp\u003eyes, the title is a philliant joke, but the problem is real: when everything is ai-assisted, everything multiplies exponentially, so your brain starts feeling cooked.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ewhen i just allow the ai to run wild, especially letting it run on an ambiguous prompt, the likelihood of brain fry increases. i get that familiar brain fog feeling from when i am overworked, under-rested, and thinking deeply without breaks. think of it like running, eventually you have to take breaks to recharge or else you risk fatiguing to the point of mistakes and failure.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eanyone juggling multiple ai-assisted tasks at the same time and feeling it\u003c/li\u003e\n\u003cli\u003eteams where activity is high but confidence in what shipped is low\u003c/li\u003e\n\u003cli\u003ebuilders who want to stay fast without feeling mentally cooked by noon\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhat i mean by \u0026ldquo;brain fry\u0026rdquo;\n    \u003cdiv id=\"what-i-mean-by-brain-fry\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-i-mean-by-brain-fry\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ein this post, \u0026ldquo;ai brain fry\u0026rdquo; means:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ethe burnt-out brain feeling you get from thinking too hard about too many things at once (like muscle exhaustion but for your brain)\u003c/li\u003e\n\u003cli\u003ethis feeling is largely driven by:\n\u003cul\u003e\n\u003cli\u003etoo many parallel prompts without a clear decision path\u003c/li\u003e\n\u003cli\u003econstant context switching across tools, tabs, and models\u003c/li\u003e\n\u003cli\u003eshallow progress loops that feel busy but not meaningful\u003c/li\u003e\n\u003cli\u003elow confidence in final output quality despite high activity\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ethe result is spending more energy and resources on thinking than is humanly possible because you are trying to keep up with a machine. i like to call this the \u003cdfn\u003ejohn henry effect\u003c/dfn\u003e.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003esymptoms of ai brain fry\n    \u003cdiv id=\"symptoms-of-ai-brain-fry\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#symptoms-of-ai-brain-fry\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ehow do you know you have crossed the line from \u0026ldquo;highly productive\u0026rdquo; to \u0026ldquo;fried\u0026rdquo;? look for these symptoms:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eyou have 15 different chat threads open and cannot remember which one has the working solution\u003c/li\u003e\n\u003cli\u003eyou find yourself writing prompts that are just \u0026ldquo;fix it\u0026rdquo; over and over without reading the errors\u003c/li\u003e\n\u003cli\u003eyou forget what the original jira ticket was even asking for because you got lost in a refactoring rabbit hole (the \u003cdfn\u003eleaky faucet effect\u003c/dfn\u003e)\u003c/li\u003e\n\u003cli\u003eyou feel the \u0026ldquo;brain fog\u0026rdquo; that comes with mental fatigue\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eif you hit two or more of these, you need to step away from the keyboard.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhat i want to explore (and answer here)\n    \u003cdiv id=\"what-i-want-to-explore-and-answer-here\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-i-want-to-explore-and-answer-here\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ewhat is the right split between human judgment and ai execution?\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ethe human owns the problem. framing, constraints, trade-offs, and final sign-off are yours. ai owns first drafts, option generation, repetitive transforms, and test scaffolding.\u003c/p\u003e\n\u003cp\u003emy shortcut for deciding:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eif the decision is high-impact and hard to undo, i own it\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eif the task is mechanical and easy to roll back, ai performs it\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ehow do i keep speed without experiencing fatigue and burn-out?\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003espeed that burns you out is not speed. i use short cycles, define the outcome, run the ai, review what it produced, then pause before jumping into the next thing. the stopping conditions matter, and i decide when to stop before i start, because once i am in the flow it is way too easy to keep going. when i want that discipline backed by a single narrative in jira and github, i use the loop in \u003ca href=\"/posts/practical-ai-workflow-jira-github-mcp/\" \u003ea practical ai workflow: jira, github, and mcp\u003c/a\u003e.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ewhich workflows reduce cognitive load instead of adding hidden overhead?\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eboring workflows. seriously. one thread per objective, one source of truth for requirements, one review checklist before merge. it sounds dull, but it kills the hidden tax of constantly reopening context and trying to remember what you were doing ten minutes ago.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ewhat team habits prevent ai-assisted chaos?\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eshared prompt patterns, short decision logs, and agreeing on what \u0026ldquo;done\u0026rdquo; actually means. if ai creates a second coordination problem on top of the one you already had, you are doing it wrong.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003emy working thesis\n    \u003cdiv id=\"my-working-thesis\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#my-working-thesis\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ebrain fry is not an \u0026ldquo;ai is bad\u0026rdquo; problem. it is a \u0026ldquo;how do i work with something that never gets tired when i absolutely do?\u0026rdquo; problem.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eset your own personal boundaries with the ai. here are some things to avoid:\n\u003cul\u003e\n\u003cli\u003ethe \u0026ldquo;just one more task\u0026rdquo; trap (i unpack that loop in \u003ca href=\"/posts/brain-defrag-time-away-from-screens/\" \u003ebrain defrag: time away from screens (and from \u0026ldquo;one more\u0026rdquo; with ai)\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003egoing down the rabbit-hole and \u0026ldquo;fixing\u0026rdquo; things that are tangent to the task, but actually out-of-scope\u003c/li\u003e\n\u003cli\u003etrying to keep up with ai as it works\u003c/li\u003e\n\u003cli\u003ehaving ai perform more work than you are able to review\u003c/li\u003e\n\u003cli\u003ehaving ai perform work that is outside your area of expertise (i.e. you are not able to understand or verify the changes)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ei try my best to use the \u003cdfn\u003eron popeil method\u003c/dfn\u003e and \u003cdfn\u003eset it and forget it\u003c/dfn\u003e. just let the ai run and then come back and review the results/output when it is complete.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003emaking \u003cdfn\u003eset it and forget it\u003c/dfn\u003e work\n    \u003cdiv id=\"making-set-it-and-forget-it-work\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#making-set-it-and-forget-it-work\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eto actually walk away, you have to write prompts that include their own verification loops.\u003c/p\u003e\n\u003cp\u003einstead of: \u0026ldquo;write the data model\u0026rdquo;.\u003c/p\u003e\n\u003cp\u003euse: \u0026ldquo;write the data model. then write the dbt tests for it. then run \u003ccode\u003edbt test\u003c/code\u003e. if it fails, read the error and try to fix it up to 3 times. stop when it passes or after 3 attempts\u0026rdquo;.\u003c/p\u003e\n\u003cp\u003enow you can actually walk away. the ai has permission to struggle, retry, and stop on its own. you come back to results instead of error messages.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003ehow many active ai threads are too many?\n    \u003cdiv id=\"how-many-active-ai-threads-are-too-many\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#how-many-active-ai-threads-are-too-many\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003ei do not have a magic number. but here is my test: if i cannot explain from memory what each open thread is doing and where it left off, i have too many. time to close some and get back to one thread per objective.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003eshould i slow down ai usage to reduce fatigue?\n    \u003cdiv id=\"should-i-slow-down-ai-usage-to-reduce-fatigue\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#should-i-slow-down-ai-usage-to-reduce-fatigue\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003enot really. slowing down the ai is not the fix. redesigning the workflow is. keep the ai running fast, but reduce how often you have to context-switch to check on it. bounded loops and batch review usually get you there.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Task_switching_%28psychology%29\"  target=\"_blank\" rel=\"noreferrer\"\u003etask switching (psychology)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Cognitive_load\"  target=\"_blank\" rel=\"noreferrer\"\u003ecognitive load\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260320-brain-defrag-time-away-from-screens/\" \u003ebrain defrag: time away from screens (and from \u0026ldquo;one more\u0026rdquo; with ai)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260319-practical-ai-workflow-jira-github-mcp/\" \u003ea practical ai workflow: jira, github, and mcp\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260314-how-to-use-ai-to-create-ai-rules-skills-and-commands/\" \u003ehow to use ai to create ai rules, skills, and commands\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260318-from-prototype-to-production-ai/\" \u003efrom prototype to production: my early adopter view of ai\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-14T17:30:00Z","date_published":"2026-03-14T17:30:00Z","id":"https://philliant.com/posts/20260314-ai-br-ai-n-fr-ai/","summary":"this post frames ai brain fry as a workflow design problem and gives a practical framework to reduce cognitive overload while keeping ai leverage high.","tags":["ai","workflow","focus","thinking"],"title":"ai br-ai-n fr-ai","url":"https://philliant.com/posts/20260314-ai-br-ai-n-fr-ai/"},{"content_html":"\u003cp\u003ebelow is my cursor setup as of friday mar 13, 2026, but rewritten as a tutorial you can actually use.\u003c/p\u003e\n\u003cp\u003ei am not claiming this is the \u0026ldquo;best\u0026rdquo; setup. i am claiming this setup works for my day-to-day work, and that you can borrow the pieces that work for you.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003equick answer\n    \u003cdiv id=\"quick-answer\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#quick-answer\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethree things make this setup work for me: one workspace with all my repos in it, rules and skills that tell the ai how my projects actually work, and a habit of verifying outputs before i trust them.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewho this is for\n    \u003cdiv id=\"who-this-is-for\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#who-this-is-for\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003epeople using cursor for technical work across multiple repositories\u003c/li\u003e\n\u003cli\u003eteams that want higher ai throughput without losing review quality\u003c/li\u003e\n\u003cli\u003ebuilders who want a practical setup they can replicate quickly\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhy this matters\n    \u003cdiv id=\"why-this-matters\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#why-this-matters\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003emy goals for this post:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eexplain what i use, why i use it, and what each part does\u003c/li\u003e\n\u003cli\u003egive you enough links and steps to replicate the setup quickly\u003c/li\u003e\n\u003cli\u003ekeep it opinionated (because opinions are useful), but still practical\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eif you want references while reading:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/docs/\"  target=\"_blank\" rel=\"noreferrer\"\u003ecursor docs home\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://modelcontextprotocol.io/introduction\"  target=\"_blank\" rel=\"noreferrer\"\u003emodel context protocol intro\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/docs/introduction\"  target=\"_blank\" rel=\"noreferrer\"\u003ewhat is dbt\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003emachine\n    \u003cdiv id=\"machine\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#machine\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003efirst, i will admit that i am in a very good hardware situation for data + ai workflows. that helps.\u003c/p\u003e\n\u003cp\u003emy current machine:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003edevice: \u003ccode\u003emacbook pro 16\u0026quot; (m2 max, 64gb ram)\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eos: \u003ccode\u003etahoe 26.3.1\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003eworkspace layout\n    \u003cdiv id=\"workspace-layout\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#workspace-layout\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003emy setup is multi-repo on purpose. i work as part of a larger team with separated repos for data, backend, and ui. there are a few more infrastructure related repos, but for the most part, our work is in the three aforementioned repos, with my work being exclusive to the data repo. all of this combines into one web application.\u003c/p\u003e\n\u003cp\u003eif your work spans multiple repos, put all of them in one cursor workspace (even if you do not commit in all of them). the extra context makes agent output much more useful.\u003c/p\u003e\n\u003cp\u003ewhy:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eagents can reason across boundaries (for example, backend contract changes that impact frontend and data models)\u003c/li\u003e\n\u003cli\u003eyou reduce manual cross-team \u0026ldquo;did you change x?\u0026rdquo; pings\u003c/li\u003e\n\u003cli\u003eindexing across repos improves semantic search quality\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ehow to set this up:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003ecreate/open your primary repo in cursor\u003c/li\u003e\n\u003cli\u003eadd other related repos via \u003ccode\u003efile -\u0026gt; add folder to workspace...\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eorder the repos from top to bottom in the order of which repo you use most at the top and least at the bottom (this is because semantic search scans your workspace file tree from top to bottom, so having your most used repo at the top means the search returns results from that repo first)\u003c/li\u003e\n\u003cli\u003esave the workspace file so you can reopen the exact same context each day\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003ereferences:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://code.visualstudio.com/docs/editor/workspaces#_multiroot-workspaces\"  target=\"_blank\" rel=\"noreferrer\"\u003emulti-root workspaces (vs code docs)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/docs/context/codebase-indexing\"  target=\"_blank\" rel=\"noreferrer\"\u003ecursor semantic + agentic search\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ecursor settings i rely on (what each one does)\n    \u003cdiv id=\"cursor-settings-i-rely-on-what-each-one-does\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#cursor-settings-i-rely-on-what-each-one-does\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethese are not exotic settings. they are just my defaults.\u003c/p\u003e\n\u003cp\u003estarter \u003ccode\u003esettings.json\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;workbench.colorTheme\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Cursor Dark\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;editor.fontFamily\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;JetBrains Mono, Menlo, Monaco, \u0026#39;Courier New\u0026#39;, monospace\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;editor.fontSize\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mi\"\u003e14\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;editor.fontLigatures\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;editor.formatOnSave\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;files.autoSave\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;onFocusChange\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;editor.inlineSuggest.enabled\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;editor.minimap.enabled\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;editor.rulers\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e100\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;terminal.integrated.defaultProfile.osx\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;zsh\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp\u003ewhat each setting does and why i keep it:\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003esetting\u003c/th\u003e\n          \u003cth\u003ewhat it does\u003c/th\u003e\n          \u003cth\u003ewhy i use it\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eworkbench.colorTheme\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003econtrols editor color theme\u003c/td\u003e\n          \u003ctd\u003ei use \u003ccode\u003ecursor dark\u003c/code\u003e because contrast is good without being harsh on long sessions\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eeditor.fontFamily\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003epicks the code font stack\u003c/td\u003e\n          \u003ctd\u003ei keep a clean mono font stack so rendering is predictable on any machine\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eeditor.fontSize\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003econtrols code text size\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003e14\u003c/code\u003e is my readability/screen-density balance\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eeditor.fontLigatures\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eenables ligatures in supported fonts\u003c/td\u003e\n          \u003ctd\u003ehelps quick symbol parsing, especially in sql and typescript\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eeditor.formatOnSave\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eauto-formats when saving\u003c/td\u003e\n          \u003ctd\u003eeliminates style drift and manual formatting overhead\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003efiles.autoSave\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eauto-saves files by trigger\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003eonFocusChange\u003c/code\u003e is safer than after-delay for active edits\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eeditor.inlineSuggest.enabled\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eenables inline ai suggestions\u003c/td\u003e\n          \u003ctd\u003ekeeps quick local iteration fast\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eeditor.minimap.enabled\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eshows/hides code minimap\u003c/td\u003e\n          \u003ctd\u003ei disable it to reduce visual noise\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eeditor.rulers\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003evertical line markers\u003c/td\u003e\n          \u003ctd\u003ekeeps me honest on line length\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eterminal.integrated.defaultProfile.osx\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003echooses terminal shell profile\u003c/td\u003e\n          \u003ctd\u003eensures my shell scripts and aliases behave as expected\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003ereferences:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/help/customization/themes\"  target=\"_blank\" rel=\"noreferrer\"\u003ethemes and appearance\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/help/customization/keyboard-shortcuts\"  target=\"_blank\" rel=\"noreferrer\"\u003ekeyboard shortcuts\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ekeybindings i use constantly\n    \u003cdiv id=\"keybindings-i-use-constantly\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#keybindings-i-use-constantly\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethese are the shortcuts i use hundreds of times a day:\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eaction\u003c/th\u003e\n          \u003cth\u003emac\u003c/th\u003e\n          \u003cth\u003ewhy this matters\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003etoggle ai sidepanel\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ecmd+i\u003c/code\u003e or \u003ccode\u003ecmd+l\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003efastest path to agent context\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003ecommand palette\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ecmd+shift+p\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eentry point for almost every cursor power feature\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003ereference:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/help/customization/keyboard-shortcuts\"  target=\"_blank\" rel=\"noreferrer\"\u003ecursor keyboard shortcuts\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003emodel selection strategy (my opinionated default)\n    \u003cdiv id=\"model-selection-strategy-my-opinionated-default\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#model-selection-strategy-my-opinionated-default\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003emy model strategy is simple:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003euse the biggest, baddest model i can afford for all tasks\u003c/li\u003e\n\u003cli\u003eagain, i recognize my privilege here that i have effectively unlimited access to all of the most powerful models\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eyour model strategy should probably be something a little more like:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003euse \u003ccode\u003eauto\u003c/code\u003e / \u003ccode\u003ecomposer\u003c/code\u003e for most tasks\u003c/li\u003e\n\u003cli\u003eswitch to a stronger model for architecture or debugging-heavy work\u003c/li\u003e\n\u003cli\u003eswitch to a faster/cheaper model for repetitive edits, formatting, or broad scans\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ethis keeps quality high without letting cost run wild.\u003c/p\u003e\n\u003cp\u003ereference:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/docs/models-and-pricing\"  target=\"_blank\" rel=\"noreferrer\"\u003emodels and pricing\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003eproject-level ai behavior: rules, agents.md, and skills\n    \u003cdiv id=\"project-level-ai-behavior-rules-agentsmd-and-skills\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#project-level-ai-behavior-rules-agentsmd-and-skills\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethis is the part that made the biggest difference for me. everything above is editor configuration. everything below is what turns the ai from \u0026ldquo;generic assistant\u0026rdquo; into something that actually knows your project.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003erules\n    \u003cdiv id=\"rules\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#rules\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003erules are persistent instructions that live in your project. i use them to encode the stuff i got tired of repeating, such as team conventions, naming patterns, and \u0026ldquo;do not do this\u0026rdquo; guardrails.\u003c/p\u003e\n\u003cp\u003ereference:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/docs/context/rules\"  target=\"_blank\" rel=\"noreferrer\"\u003erules\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eexample rule (\u003ccode\u003e.cursor/rules/project-standards.mdc\u003c/code\u003e):\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-md\" data-lang=\"md\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e---\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003edescription: \u0026#34;project coding and validation standards\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ealwaysApply: true\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e---\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e keep edits scoped to the requested task\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e follow existing naming and folder patterns\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- run project validation checks for substantive changes\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003e\u003ccode\u003eagents.md\u003c/code\u003e\n    \u003cdiv id=\"agentsmd\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#agentsmd\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003e\u003ccode\u003eAGENTS.md\u003c/code\u003e is a markdown file at the root of your repo. i use it for plain-language context that the agent should always have, including project architecture, how repos relate, and what skills exist.\u003c/p\u003e\n\u003cp\u003ereferences:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/docs/context/rules\"  target=\"_blank\" rel=\"noreferrer\"\u003erules and agents.md overview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch3 class=\"relative group\"\u003eskills\n    \u003cdiv id=\"skills\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#skills\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eskills are step-by-step runbooks for tasks you do over and over. i have one for creating a new data model that handles the sql, the docs, the tests, and the validation summary all in one pass.\u003c/p\u003e\n\u003cp\u003ereference:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/help/customization/skills\"  target=\"_blank\" rel=\"noreferrer\"\u003eskills\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eexample skill (\u003ccode\u003e.cursor/skills/release-checklist/SKILL.md\u003c/code\u003e):\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-md\" data-lang=\"md\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# release checklist\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e1.\u003c/span\u003e run lint, format, and tests\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e2.\u003c/span\u003e list any failing checks with exact remediation\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e3.\u003c/span\u003e summarize risk areas and edge cases\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e4. provide release notes in markdown\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch2 class=\"relative group\"\u003econtext hygiene: ignore what should not be indexed\n    \u003cdiv id=\"context-hygiene-ignore-what-should-not-be-indexed\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#context-hygiene-ignore-what-should-not-be-indexed\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ecursor respects \u003ccode\u003e.gitignore\u003c/code\u003e, and you can add \u003ccode\u003e.cursorignore\u003c/code\u003e for extra exclusions.\u003c/p\u003e\n\u003cp\u003ethis matters for two reasons:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003esignal quality (so the ai is not reading garbage)\u003c/li\u003e\n\u003cli\u003esafety (so it does not index your secrets, generated files, or vendor blobs)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003ereference:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/help/customization/ignore-files\"  target=\"_blank\" rel=\"noreferrer\"\u003eignore files\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003estarter \u003ccode\u003e.cursorignore\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight-wrapper\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003enode_modules/\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003edist/\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ebuild/\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ecoverage/\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e*.min.js\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e.env*\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\n\u003ch3 class=\"relative group\"\u003ethe art of the \u003ccode\u003e@\u003c/code\u003e mention\n    \u003cdiv id=\"the-art-of-the--mention\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#the-art-of-the--mention\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eeven with a clean index, you do not want the ai guessing which files matter. i rely heavily on explicit \u003ccode\u003e@\u003c/code\u003e mentions in my prompts.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e@Files\u003c/code\u003e to pull in specific files\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@Folders\u003c/code\u003e to give the ai a boundary to look within\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@Web\u003c/code\u003e when i need it to read a specific documentation page that is not in my workspace\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003emy rule of thumb is that if i already know where the answer lives, i point the ai directly to it. do not make the ai go on a scavenger hunt.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ewhen the ai gets stuck (troubleshooting)\n    \u003cdiv id=\"when-the-ai-gets-stuck-troubleshooting\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#when-the-ai-gets-stuck-troubleshooting\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eno setup prevents every failure. when the ai starts hallucinating or going in circles, here is what i actually do:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003estop arguing with it.\u003c/strong\u003e if it fails twice on the same thing, going back and forth just fills the context window with noise. i learned this the hard way\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003estart a new chat.\u003c/strong\u003e drop the baggage. open a fresh session with only the specific files you need attached\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eswitch models.\u003c/strong\u003e sometimes the model is just stuck in a rut. swapping to a different one breaks the pattern more often than you would expect\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003ch2 class=\"relative group\"\u003emcp servers in my setup (what each one actually gives you)\n    \u003cdiv id=\"mcp-servers-in-my-setup-what-each-one-actually-gives-you\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#mcp-servers-in-my-setup-what-each-one-actually-gives-you\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003emcp is what allows cursor agents to talk to my other tools. for how i turn jira and github into the documentation-first loop with those integrations, see \u003ca href=\"/posts/practical-ai-workflow-jira-github-mcp/\" \u003ea practical ai workflow: jira, github, and mcp\u003c/a\u003e. here are the servers i use and what they actually do for me:\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003emcp server\u003c/th\u003e\n          \u003cth\u003ewhat it enables\u003c/th\u003e\n          \u003cth\u003ewhen i use it\u003c/th\u003e\n          \u003cth\u003edocs\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003egithub\u003c/td\u003e\n          \u003ctd\u003erepo/issue/pr context and actions\u003c/td\u003e\n          \u003ctd\u003ecode review, pr drafting, issue triage, release hygiene\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://docs.github.com/en/copilot/how-tos/provide-context/use-mcp/use-the-github-mcp-server\"  target=\"_blank\" rel=\"noreferrer\"\u003egithub mcp server\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eatlassian\u003c/td\u003e\n          \u003ctd\u003ejira + confluence context and updates\u003c/td\u003e\n          \u003ctd\u003econverting specs to tickets, reading decisions, status updates\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://support.atlassian.com/atlassian-rovo-mcp-server/docs/getting-started-with-the-atlassian-remote-mcp-server/\"  target=\"_blank\" rel=\"noreferrer\"\u003eatlassian rovo mcp\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003edbt labs\u003c/td\u003e\n          \u003ctd\u003edbt metadata, lineage, semantic layer, dbt actions\u003c/td\u003e\n          \u003ctd\u003emodel design, lineage checks, docs generation, build/test help\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://docs.getdbt.com/docs/dbt-ai/about-mcp\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt mcp\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003esnowflake\u003c/td\u003e\n          \u003ctd\u003egoverned data access and mcp-native tools\u003c/td\u003e\n          \u003ctd\u003equery validation, analytics checks, warehouse-backed exploration\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp\"  target=\"_blank\" rel=\"noreferrer\"\u003esnowflake mcp\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003efigma\u003c/td\u003e\n          \u003ctd\u003edesign-system + frame context for implementation\u003c/td\u003e\n          \u003ctd\u003etranslating designs to components with less guesswork\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://developers.figma.com/docs/figma-mcp-server/\"  target=\"_blank\" rel=\"noreferrer\"\u003efigma mcp server\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eslack\u003c/td\u003e\n          \u003ctd\u003esearch/read/post capabilities in slack context\u003c/td\u003e\n          \u003ctd\u003efinding decisions, summarizing threads, drafting updates\u003c/td\u003e\n          \u003ctd\u003e\u003ca href=\"https://docs.slack.dev/ai/slack-mcp-server\"  target=\"_blank\" rel=\"noreferrer\"\u003eslack mcp server\u003c/a\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003ea word on security:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eany mcp tool that can write or change things is real power, not a toy\u003c/li\u003e\n\u003cli\u003euse least privilege, prefer oauth over api keys sitting in plaintext, and make sure destructive actions require you to say \u0026ldquo;yes\u0026rdquo; before they fire\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003edbt references i actually use\n    \u003cdiv id=\"dbt-references-i-actually-use\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#dbt-references-i-actually-use\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eif your setup includes dbt, these are the docs i recommend bookmarking:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/docs/get-started-dbt\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt quickstarts\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/docs/build/documentation\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt project documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.getdbt.com/reference/commands/cmd-docs\"  target=\"_blank\" rel=\"noreferrer\"\u003edbt docs command reference\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003etheme choice\n    \u003cdiv id=\"theme-choice\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#theme-choice\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ei prefer dark everything, so my theme in cursor is \u003ccode\u003ecursor dark\u003c/code\u003e, of course\u003c/p\u003e\n\u003cp\u003ereferences:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/help/customization/themes\"  target=\"_blank\" rel=\"noreferrer\"\u003ecursor themes and appearance\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003ereplicate this setup in 45 minutes\n    \u003cdiv id=\"replicate-this-setup-in-45-minutes\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#replicate-this-setup-in-45-minutes\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003eif you want the practical version, do this in order:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003einstall/update cursor from \u003ca href=\"https://cursor.com/downloads\"  target=\"_blank\" rel=\"noreferrer\"\u003ecursor downloads\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003ecreate one workspace and add all related repos\u003c/li\u003e\n\u003cli\u003epaste the starter \u003ccode\u003esettings.json\u003c/code\u003e and tweak font/theme\u003c/li\u003e\n\u003cli\u003eset your core shortcuts (\u003ccode\u003ecmd+i\u003c/code\u003e, \u003ccode\u003ecmd+l\u003c/code\u003e, \u003ccode\u003ecmd+shift+p\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003eadd one always-on project rule for coding standards\u003c/li\u003e\n\u003cli\u003eadd one skill for your most repeated workflow\u003c/li\u003e\n\u003cli\u003eadd a \u003ccode\u003e.cursorignore\u003c/code\u003e file\u003c/li\u003e\n\u003cli\u003econnect mcp servers one by one (github first is usually easiest)\u003c/li\u003e\n\u003cli\u003everify each integration with one safe test prompt\u003c/li\u003e\n\u003cli\u003edocument your final setup so your team can copy it\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003ch2 class=\"relative group\"\u003everification prompts you can copy\n    \u003cdiv id=\"verification-prompts-you-can-copy\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#verification-prompts-you-can-copy\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ethese are good smoke tests after setup:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u0026ldquo;scan this workspace and summarize architecture in 10 bullets\u0026rdquo;\u003c/li\u003e\n\u003cli\u003e\u0026ldquo;list project conventions i should follow before i edit code\u0026rdquo;\u003c/li\u003e\n\u003cli\u003e\u0026ldquo;for this dbt project, explain lineage for model x and suggest tests\u0026rdquo;\u003c/li\u003e\n\u003cli\u003e\u0026ldquo;summarize open engineering tickets related to this feature\u0026rdquo;\u003c/li\u003e\n\u003cli\u003e\u0026ldquo;draft a release update message from recent merged prs\u0026rdquo;\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003eresults\n    \u003cdiv id=\"results\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#results\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003ewhat this actually gives me day to day:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ei start tasks faster because the ai already knows my project\u003c/li\u003e\n\u003cli\u003ei almost never retype the same instruction twice\u003c/li\u003e\n\u003cli\u003ethe ai can reason across repos, which catches things i would miss\u003c/li\u003e\n\u003cli\u003ehandoffs are cleaner and i have far fewer \u0026ldquo;oh no, i forgot about that dependency\u0026rdquo; moments\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003eclosing\n    \u003cdiv id=\"closing\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#closing\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cp\u003edo not copy my setup 1:1. that is not the point.\u003c/p\u003e\n\u003cp\u003ethe point is to try things, keep what removes friction, and ruthlessly delete what adds ceremony. the best setup is not the fanciest one. it is the one where the loop between \u0026ldquo;i want this\u0026rdquo; and \u0026ldquo;it is done and verified\u0026rdquo; stays as short as possible.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003efaq\n    \u003cdiv id=\"faq\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#faq\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat should i set up first if i only have 20 minutes?\n    \u003cdiv id=\"what-should-i-set-up-first-if-i-only-have-20-minutes\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-should-i-set-up-first-if-i-only-have-20-minutes\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003eone workspace with your most-used repos and your core shortcuts. then write one always-on rule so the ai knows your project constraints from the first prompt. everything else can wait.\u003c/p\u003e\n\n\u003ch3 class=\"relative group\"\u003ewhat is the most common failure mode with this setup?\n    \u003cdiv id=\"what-is-the-most-common-failure-mode-with-this-setup\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#what-is-the-most-common-failure-mode-with-this-setup\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h3\u003e\n\u003cp\u003econtext drift. if you do not tell the ai which files or folders matter, it burns tokens wandering around your codebase instead of solving the thing you actually asked about. explicit \u003ccode\u003e@\u003c/code\u003e mentions fix this almost instantly.\u003c/p\u003e\n\n\u003ch2 class=\"relative group\"\u003ereferences\n    \u003cdiv id=\"references\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#references\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://cursor.com/docs/\"  target=\"_blank\" rel=\"noreferrer\"\u003ecursor docs home\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://modelcontextprotocol.io/introduction\"  target=\"_blank\" rel=\"noreferrer\"\u003emodel context protocol intro\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2 class=\"relative group\"\u003erelated reading\n    \u003cdiv id=\"related-reading\" class=\"anchor\"\u003e\u003c/div\u003e\n    \n    \u003cspan\n        class=\"absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none\"\u003e\n        \u003ca class=\"text-primary-300 dark:text-neutral-700 !no-underline\" href=\"#related-reading\" aria-label=\"Anchor\"\u003e#\u003c/a\u003e\n    \u003c/span\u003e\n    \n\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260319-practical-ai-workflow-jira-github-mcp/\" \u003ea practical ai workflow: jira, github, and mcp\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260314-how-to-use-ai-to-create-ai-rules-skills-and-commands/\" \u003ehow to use ai to create ai rules, skills, and commands\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260315-starter-templates-for-ai-rules-skills-and-commands/\" \u003estarter templates for ai rules, skills, and commands\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"/posts/20260320-deep-dive-ai-models-i-use/\" \u003edeep dive: the ai models i use\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-03-13T17:30:00Z","date_published":"2026-03-13T17:30:00Z","id":"https://philliant.com/posts/20260313-my-cursor-setup/","summary":"this is my real cursor setup as of march 13, 2026, rewritten as a practical tutorial with settings explanations, mcp server breakdowns, and a replication checklist.","tags":["cursor","workflow","ai","writing","productivity"],"title":"my cursor setup","url":"https://philliant.com/posts/20260313-my-cursor-setup/"}],"language":"en","title":"philliant","version":"https://jsonfeed.org/version/1.1"}