GitHub vs GitLab

GitHub vs GitLab — Which One Should You Use?

Version control platforms are essential for modern development. Two of the most popular choices are GitHub and GitLab. Both are built around Git, but they focus on slightly different goals and workflows.

This article explains the differences in a simple, practical way with advantages and disadvantages of each.

What is GitHub?

  • GitHub is the world’s most popular code hosting platform, owned by Microsoft.
  • It is widely used for open-source projects, personal portfolios, and team collaboration.
  • GitHub focuses on simplicity, community, and developer networking.

What is GitLab?

  • GitLab is a complete DevOps platform that provides source code hosting along with built-in CI/CD, security tools, and deployment features.
  • GitLab focuses on the entire software development lifecycle.

| Feature | GitHub | GitLab |
| ------------ | --------------------------------- | -------------------------- |
| Main Focus | Code hosting & collaboration | Full DevOps lifecycle |
| Popularity | Very high | Moderate |
| Best for | Students, open-source, portfolios | Teams, DevOps, enterprises |
| CI/CD | Good (GitHub Actions) | Excellent (built-in) |
| Self-hosting | Limited | Strong support |

GitHub Advantages

1.Massive Community

  • GitHub hosts millions of repositories and is the default platform for open-source projects.
  • Most developers, recruiters, and companies actively use GitHub.

This makes it ideal for:

  • Showcasing projects
  • Networking
  • Contributing to open source
  • Job hunting

2.Beginner-Friendly Interface

GitHub has a clean and simple UI that is easy to understand for new developers.

Learning curve is minimal compared to GitLab.

3.Strong Portfolio Value

  • Recruiters often ask for GitHub profiles.
  • A strong GitHub profile can directly improve job opportunities.

4.Powerful Integrations

GitHub integrates easily with many tools:

  • VS Code
  • Slack
  • Docker
  • Cloud platforms

5.GitHub Actions (CI/CD)

GitHub provides built-in automation for:

  • Testing
  • Building
  • Deploying applications

It is sufficient for most projects.

GitHub Disadvantages

1. Limited Built-in DevOps Tools

Advanced DevOps features often require external tools or integrations.

2. Advanced Features Can Be Expensive

Enterprise features and higher CI/CD usage can become costly.

3. Less Built-in Project Management

Compared to GitLab, GitHub has fewer built-in planning tools.

GitLab Advantages

1.Complete DevOps Platform

GitLab provides an all-in-one solution:

  • Source control
  • CI/CD pipelines
  • Issue tracking
  • Security scanning
  • Deployment tools

No need for many third-party integrations.

2.Powerful Built-in CI/CD

GitLab pipelines are available out of the box and are more advanced than GitHub’s default setup.

3.Self-Hosting Option

Organizations can host GitLab on their own servers for:

  • Privacy
  • Security
  • Compliance

This is a major advantage for enterprises.

4.Better Project Management Tools

GitLab includes:

  • Issue boards
  • Roadmaps
  • Milestones
  • Time tracking

This makes it suitable for large teams.

GitLab Disadvantages

1.Smaller Community

GitLab has fewer public repositories and less open-source visibility than GitHub.

2.More Complex Interface

The platform has many features, which can feel overwhelming for beginners.

3.Less Recognition for Portfolios

Recruiters usually expect GitHub links rather than GitLab profiles.

Collaboration: A Common Myth

Both GitHub and GitLab allow:

  • Unlimited repositories
  • Unlimited collaborators
  • Large team workflows

There is no restriction like “only 2–3 people per project.”
Teams with dozens or even hundreds of developers use both platforms.

When to Choose GitHub

Choose GitHub if you are:

  • A student or beginner
  • Building a portfolio
  • Contributing to open-source projects
  • Preparing for job interviews

GitHub is the best starting point for most developers.

When to Choose GitLab

Choose GitLab if you are:

  • Working in a company environment
  • Managing large development teams
  • Using CI/CD heavily
  • Practicing DevOps workflows

GitLab is ideal for full project lifecycle management.

Final Verdict

Both platforms are excellent and built on the same Git foundation.

GitHub is best for learning, sharing, and career growth.
GitLab is best for DevOps, automation, and enterprise workflows.

Many developers end up using both during their careers.

The 55.8 Percent Productivity Number From Doshi And Vaishnav Is Narrower Than People Think

When Doshi and Vaishnav published their controlled experiment on AI code completion in Science (2023), the headline that propagated everywhere was “55.8% faster.” Repeat it enough and it becomes received wisdom.

The actual paper measured time-to-completion on a single well-defined HTTP server task. A problem with a known shape, a stable target, and a scoring function that rewarded a specific solution path. The 55.8% lift was real for that task. It is also the narrowest possible reading of what “AI productivity” means in software work.

A more careful follow-up at HICSS-59 (Stray et al., 2026) looked at sustained workflow integration over weeks instead of a single benchmarked task. Numbers compressed. Across mixed work (greenfield, debugging, refactoring, code review) aggregate time savings landed closer to 10-20%, with high variance across task class. Debugging and code review barely moved. Greenfield CRUD work moved the most.

That gap between single-task lab benchmark and integrated weekly workflow is where most engineering org AI productivity decisions are silently going wrong.

The mechanism gap

A code-completion model is doing one thing: predicting the next plausible token sequence given local context. Fantastic when the context is a half-finished function with a clear signature and the loss function would reward the standard completion. Much weaker when the work involves:

  • Tracing a bug through three repos and a queue
  • Deciding which refactor is worth doing
  • Reading existing code to understand intent before touching it
  • Negotiating a schema change with another team
  • Writing the test that catches the actual failure mode

None of those are next-token problems.

Where the gains actually compound

Builders shipping production AI workflows in 2025-26 are seeing real durable lift, but not by turning on Copilot and waiting. The compounding wins look like:

  1. Stack reduction. Skip a build step entirely. Replace a 4-step ETL with a single LLM-and-validator pass for cases where the validator can be trusted.

  2. Context elimination. Cut the time it takes to load a problem into working memory. Quick orientation queries on a strange codebase, API surface lookup, error message triage.

  3. Boilerplate elimination at the boundary. Form validators, type-mapping, mock data, fixture generation.

  4. Spec to first-draft compression. Get a structurally-correct first cut, then spend the saved time on the parts that need taste.

What this means for tooling decisions

Stop comparing AI tooling claims on single-task benchmarks. Ask vendors for sustained-workflow time-distribution data over weeks of real engineering work.

Measure your own lift the same way. Pick three task classes, instrument time-to-merge over a 4-week window, compare against baseline.

Hire for orchestration skill, not typing speed. The bottleneck moved.

Summary

The 55.8 percent number is not wrong, it is narrow. Sustained workflow integration data puts realistic aggregate productivity lift in the low double digits, concentrated in specific task classes.

Sources: Doshi and Vaishnav, Science 2023. Stray et al., HICSS-59 proceedings 2026.

Monorepo vs Multi-Repo: Why AI Agents Tip the Scale

The monorepo vs multi-repo debate ran for over a decade without a clear winner. That wasn’t because engineers couldn’t agree — it was because both models offered genuine advantages under different constraints. A 50-person startup with three services and a 10,000-person company with hundreds of microservices faced different problems. The right repository structure depended on team size, deployment cadence, ownership models, and tooling maturity.

That calculus has changed. AI coding agents, code generation, and agentic development workflows have shifted what matters in a repository model. The repository model that gives AI coding agents maximum context, atomic cross-cutting changes, and transactional execution now has a clear advantage.

That model is monorepo.

The old tradeoffs were real

Before AI coding agents became mainstream, the monorepo vs multi-repo decision optimized for human workflows: how engineers navigate code, how teams draw ownership lines, how CI/CD pipelines scale, and how releases ship.

Monorepo gave you atomic cross-service changes, a single dependency graph, unified CI/CD, and zero version skew between internal libraries. The cost was large clone sizes, slower CI without build caching, complex permission models, and the need for specialized tooling like Bazel, Pants, Nx, or Buck2 to keep builds fast.

Multi-repo gave you strong ownership boundaries, independent versioning, smaller checkouts, faster isolated builds, and a reduced blast radius when something broke. The cost was painful cross-repo changes, dependency drift between services, version coordination overhead, and friction around shared API contracts.

Both sets of tradeoffs were real. Google chose monorepo and invested heavily in custom tooling — Piper for source control, CitC for cloud workspaces, Blaze for builds — to make it work across billions of lines of code. Many companies chose multi-repo and built coordination processes around the seams.

Neither side was wrong. The inputs just hadn’t changed yet.

AI changed the optimization function

AI coding agents shifted three assumptions that the old tradeoff analysis depended on.

Context bandwidth is now the binding constraint. AI coding agents generate better code when they can see the full picture: type definitions, call sites, test cases, dependency relationships, and usage patterns across the entire codebase. A repository boundary is a context wall. Every wall degrades the quality of AI-generated output.

Cross-cutting change cost dropped toward zero. Renaming an interface, updating every call site, fixing the downstream tests, and adjusting the documentation used to be a multi-day coordination effort across repositories. An AI coding agent in a monorepo does this in a single pass. In a multi-repo setup, the same change still requires coordinated PRs, version bumps, release ordering, and compatibility windows.

Dependency reasoning became automated. Engineers used to maintain mental models of how services depended on each other. AI coding agents read the actual dependency graph. The bigger and more connected that graph is, the more accurately the agent reasons about change impact. Fragmenting the graph across repositories forces the agent to guess at boundaries it can’t see.

These three shifts don’t make multi-repo impossible. They make it more expensive relative to monorepo than it used to be.

Context is the new bottleneck

Consider a concrete scenario: you ask an AI coding agent to rename a field in a shared protobuf definition that five services consume. In a monorepo, the agent sees the .proto file, the generated bindings, and every service’s handler code. It renames the field, regenerates the bindings, and updates all five consumers in one pass. In a multi-repo setup, the agent can only see the proto definition repo. It renames the field there, but the five consuming services live in separate repositories. Each one breaks on its next build, and someone has to coordinate the updates manually.

This failure mode generalizes. When an AI coding agent working in service A needs to understand how service B consumes a shared library, it either has access to that code or it doesn’t. In a multi-repo world, it usually doesn’t. The agent falls back to stub assumptions, infers API behavior from incomplete type hints, or generates code that works in isolation but breaks at integration time.

Anyone who has used an AI coding agent across a multi-repo project has seen some version of this: the agent generates a change that compiles locally but violates a contract defined in another repository. The fix is the same every time — give the agent more context. Monorepo gives it all the context by default.

Cross-cutting changes went from expensive to cheap

AI coding agents are most effective at cross-cutting work: refactoring a shared interface and updating every consumer, migrating a dependency and fixing all downstream breakage, or propagating a type change across service boundaries.

In a monorepo, these are atomic operations. The agent modifies the source, updates every call site, adjusts the tests, and produces a single commit that either passes CI or doesn’t. No partial state. No version skew. No window where service A runs the new interface while service B still expects the old one.

In a multi-repo setup, the same change becomes a distributed transaction:

  1. Make the change in the library repo and publish a new version
  2. Open PRs in each consuming repo to update the dependency
  3. Ensure all consuming repos merge in the right order
  4. Handle the window where some services use the old version and others use the new one
  5. Coordinate rollback if any step fails

This is fragile enough when humans manage it. AI coding agents currently lack standardized tooling for orchestrating changes across multiple repositories as a single logical transaction. The agent either has one graph to work with or it doesn’t. Monorepo gives it the one graph.

AI erodes monorepo’s historical costs

The standard objections to monorepo were always about operational friction: the repo is too big to clone, the build is too slow, navigation is too hard, onboarding takes too long.

AI coding agents are wearing each of these down.

Historical objection Current state
“The codebase is too large to navigate” AI coding agents search and reason over million-line codebases — Cursor indexes the full workspace, Sourcegraph Cody builds semantic search across entire codebases
“Refactors across the repo are risky” AI coding agents execute refactors with full graph awareness and test validation
“The dependency graph is too complex” AI coding agents map dependency graphs automatically
“Build configuration is a burden” AI coding agents generate and maintain build files (tools like Gazelle already do rule generation for Bazel; AI extends this further)
“Onboarding new engineers takes weeks” AI coding agents explain repo structure, trace code paths, and answer architecture questions on demand

The infrastructure side has caught up too. Git sparse-checkout and Scalar (originally VFS for Git, developed by Microsoft for the Windows repo) limit your working set to only the files you need. Remote build execution through Bazel or similar systems means local machine specs matter less. Graph-aware CI systems like Nx and Turborepo only rebuild and retest what changed.

The operational costs that once justified multi-repo as “the simpler choice” are shrinking. The context costs of multi-repo are growing as AI coding agents become a larger part of the development workflow.

Toolchains assume a single workspace

Look at how the current generation of AI coding tools is built. IDE-integrated agents like Cursor and GitHub Copilot index the open workspace for context. CLI-based agents like Claude Code and Aider operate within a single repository directory. Code intelligence platforms like Sourcegraph Cody can bridge repositories, but doing so requires explicit multi-repo configuration that most teams skip.

The default for all of these tools is: open a repo, index it, reason over it as one unit. Multi-repo splits the graph across repository boundaries, and each tool either needs custom bridging (which most teams don’t build) or operates with a partial view of the system. The tools that gain traction tend to assume a single-workspace setup, because that’s where they produce the best results with the least configuration.

Agentic workflows need transactional boundaries

Agentic coding, where an AI coding agent executes a multi-step plan autonomously, follows a consistent loop: analyze the codebase, make a set of coordinated changes, update affected tests, validate CI, and commit.

That loop assumes a single transaction boundary. The agent needs write access to every file involved in the change, the ability to update dependents in the same commit, and a single CI run that validates the entire change set.

Monorepo provides this naturally. One repo, one commit boundary, one CI pipeline.

Multi-repo forces a distributed transaction: changes span multiple repositories, each with its own commit history, CI pipeline, and merge process. Distributed transactions are hard to get right even with purpose-built coordination infrastructure. AI coding agents don’t have that infrastructure today, and bolting it on adds complexity that monorepo avoids entirely.

The counterarguments, honestly

“Monorepos don’t scale.” They do, but they require investment. Google’s monorepo holds roughly two billion lines of code, used by more than 25,000 developers, managed by custom tooling built over a decade (Potvin & Levenberg, 2016). Not every company can replicate that. But for most organizations, sparse-checkout, Bazel or Nx, and remote execution handle the scaling problem. The scaling objection is about tooling investment, not an inherent architectural limit.

“Teams need isolation.” Isolation is legitimate, but repository boundaries are one enforcement mechanism, not the only one. CODEOWNERS files, path-based code ownership, protected directory policies, and build-graph enforcement all provide isolation within a monorepo. The question is whether the isolation benefit of separate repos outweighs the context cost. For most internal teams, it doesn’t.

“Independent releases are easier in multi-repo.” They are, for now. But AI-assisted release tooling is closing the gap: automated version propagation, dependency-update PRs, compatibility verification, and semantic release pipelines all reduce the coordination overhead of monorepo releases. This objection is valid but weakening.

When multi-repo still wins

Multi-repo remains the right choice in specific situations:

  • Legal or compliance separation: when regulations require distinct codebases for different business units or jurisdictions
  • Open-source boundary management: when public-facing OSS projects need their own contribution workflows and licensing
  • Vendor or third-party boundaries: when components are owned by external parties with their own release cycles
  • Security isolation mandates: when access controls must be enforced at the repository level for regulatory reasons
  • Fundamentally divergent tech stacks: when projects share no dependencies, no interfaces, and no team overlap

These are structural constraints, not optimization preferences. If you hit one, multi-repo is the pragmatic choice regardless of AI tooling.

What this means for your next project

If you’re starting a new platform or consolidating existing services, default to monorepo. The context advantages for AI-assisted development compound as the codebase grows. Every service, library, and schema in the same repo is another piece of context your AI coding agents can use to generate better code, catch more bugs, and execute larger refactors.

Co-locate services and their shared libraries. Centralize shared schemas, type definitions, and API contracts. Keep tests next to implementations. Adopt a graph-aware build system (Bazel, Nx, Turborepo) early. Enable repository-wide indexing for your AI coding tools.

The monorepo vs multi-repo debate was genuinely balanced when engineers were the only consumers of repository structure. AI coding agents are now a second consumer, and they optimize for different properties: full-codebase context, atomic multi-package changes, and a connected dependency graph.

The repository model that provides these is monorepo. The open question is how fast multi-repo orchestration tooling catches up — and whether it can close the context gap before monorepo becomes the default.

AI Psychosis in 2026 — What the New Evidence Actually Shows

A note before reading. This article discusses mental-health symptoms and psychiatric phenomena for general informational and educational purposes. It is not a diagnostic tool and is not a substitute for professional clinical care. If you are experiencing symptoms that concern you, or you are concerned about someone close to you, please reach out to a licensed mental-health professional. If you are in crisis, contact your local emergency services or a recognized crisis line in your country.

The first peer-reviewed case has been published, the Human Line Project has crossed twenty-two countries, and a January UCSF call for chat-log analysis has shifted what we can say with confidence.

In the past four months alone, the first peer-reviewed clinical case of new-onset AI-associated psychosis has been published in Innovations in Clinical Neuroscience. The British Journal of Psychiatry has run a Cambridge framework on harm reduction. Psychiatric News has published a February 2026 special report under the title The Hallucinating Machine. UCSF clinicians have publicly called for systematic analysis of patient chat logs as forensic input. Psychiatric Times has issued recommendations urging clinicians to ask about AI use at intake and to document it like substance use. New quantitative research, covered in Fortune in March, has measured how chatbots respond when users describe suicidal, manic, or delusional content, and found patterns of validation and reinforcement that should not exist in a system positioned for general consumer use.

The phrase has not been promoted to a recognized diagnosis. The clinical reality underneath it has, in measurable ways, become harder to dismiss.

I am a psychologist in training and a full-stack developer who builds AI systems for a living. What follows is an updated walk-through of what the 2026 evidence actually shows, who is at risk based on the current literature, the warning signs being flagged in clinical settings, and the concrete steps a user or someone close to them can take. The honest version of this conversation is more useful than either the alarmist or the dismissive version of it.

What is AI Psychosis?

AI psychosis is a descriptive label, not a recognized diagnosis. It does not appear in the DSM-5-TR or in the ICD-11 as of this writing. The label refers to a clinical pattern, increasingly documented in case reports and now in peer-reviewed journals, in which a user, sometimes with pre-existing psychiatric vulnerability, sometimes without, develops or consolidates psychotic symptoms in the context of extended chatbot use.

The pattern, as it has become more carefully described, looks like this: a user engages in an extended conversation with a large language model. The system, trained for satisfying responses, validates and elaborates the user’s framing rather than challenging it. Over time, the user’s beliefs about reality drift in directions that, in ordinary social contexts, would have been met with skepticism, redirection, or pushback. In some cases, the drift consolidates into fixed delusional content, most often mystical, conspiratorial, surveillance-related, or technology-singularity themes, and presents at a clinical encounter as an acute psychotic episode.

Three findings from the past few months have sharpened this description:

1. The Innovations in Clinical Neuroscience case study represents what is widely considered the first clinically described case of new-onset AI-associated psychosis published in a peer-reviewed journal. The case is significant not because it confirms the broad outline, clinicians had been describing this pattern informally for two years, but because the patient described in the report did not have an established prior personal history of psychotic-spectrum illness. The earlier informal consensus was that documented cases overwhelmingly involved identifiable pre-existing vulnerability. That framing has become, in light of the 2026 case literature and the Human Line Project data, harder to defend in its strongest form.

2. The British Journal of Psychiatry harm-reduction framework, published in early 2026, moves the conversation from recognition to mechanism and to intervention points. The framework names sycophancy, validation, parasocial dependence, and the absence of external-correction friction as the load-bearing structural variables, and articulates intervention possibilities at the platform, clinical, and policy levels.

3. New quantitative work, covered in Fortune in March 2026, has begun to measure, at scale, how chatbots respond to user statements consistent with suicidality, mania, and psychotic-spectrum content. The reported finding is that current consumer chatbots, in many such conversations, validate and elaborate rather than redirect to safety resources. This is the structural feature that the careful clinical commentary has been naming for two years. It is now being measured rather than asserted.

Is AI Psychosis Real?

The careful answer in April 2026 is: yes as a clinical pattern with measurable structural mechanisms, and no as a recognized standalone diagnosis.

What has changed since 2024:

  • A peer-reviewed case is now in the literature. Joseph Pierre’s earlier framing of familiar psychiatric trajectories altered by a novel input remains useful, and Allen Frances’s caution against premature labeling continues to apply to the diagnostic question. But the empirical floor has risen.

  • The Human Line Project, reported by The Guardian in March 2026 to have affiliates in twenty-two countries, found that more than 60% of those approaching the group reportedly had no prior personal history of mental illness. This figure is uncomfortable for the strongest version of the “only-the-vulnerable” framing. It does not establish that healthy users are at material risk in general, but it does establish that the population presenting in this way is broader and less narrowly bounded than the early literature predicted.

  • Quantitative research has begun to land. Studies covered in Fortune, Mad in America, Psychiatric News, and the British Journal of Psychiatry are starting to put numbers on what was previously only a structural argument.

  • Clinical practice has begun to adapt. The Psychiatric Times February 2026 recommendation that intake assessments now ask about AI chatbot use places AI use on a footing similar to substance use, social media, and other environmental inputs that affect mental health.

What has not changed: AI psychosis is not in the DSM-5-TR. It is not in the ICD-11. The careful clinical position remains that the underlying clinical pictures are still best described by existing categories, schizophrenia spectrum, brief psychotic disorder, delusional disorder, substance-induced psychosis, psychotic features in mood disorders, interacting with the new environmental input.

The answer is: real-as-pattern, real-as-mechanism, real-as-clinical-concern. Not real-as-new-disorder. The distinction continues to matter.

Can Chatbots Really Make People Psychotic?

Through 2024 and most of 2025, the careful answer was: the documented cases overwhelmingly involve users with pre-existing vulnerability; chatbots interact with vulnerability rather than creating it from nothing. That framing was a reasonable summary of the case literature available at the time.

That summary is now harder to defend in its strongest form, for two reasons:

The first is the peer-reviewed case mentioned above, in which the patient did not have an established prior personal history of psychotic-spectrum illness. A single case is not an epidemiological signal. It is, however, a published rebuttal to the strongest version of the prior consensus.

The second is the Human Line Project figure on prior history. If 60% of those approaching the support group had no documented prior mental-illness history, the case-by-case selection bias of clinical reporting, which tends to find pre-existing factors because it goes looking for them, may have been masking the real distribution.

The careful 2026 answer is therefore more conditional. The mechanism by which chatbots appear to act on the user, sycophantic validation, removal of external-correction friction, elaboration of speculative content, parasocial intensification, and displacement of human contact, is a structural mechanism that operates on cognition in general, not only on cognition that is already vulnerable. Most users will not develop psychotic content in response to it. Some users, including some without prior diagnosable vulnerability, appear to. The factors that distinguish the two populations are not yet well-characterized in the empirical literature.

The shift is not from “chatbots are safe” to “chatbots cause psychosis.” The shift is from “only previously vulnerable users are at risk” to “the population at risk is broader than the early literature suggested,” and the structural mechanism is now measurable.

Warning Signs

The signs that matter are largely the classical signs of emerging psychiatric vulnerability, observed in the context of heavy chatbot use. None of these in isolation indicates any psychiatric condition, they are flags worth attending to, particularly when several appear together.

  • Sleep disruption with heavy nocturnal chatbot use. Long sessions late at night recur across the case literature. Sleep deprivation is one of the most reliable triggers in the broader psychosis literature.

  • Increasing preoccupation with idiosyncratic ideas. A user spending large amounts of time on one specific theme, particularly mystical, conspiratorial, surveillance, or technology-singularity content, with the time spent increasing rather than diminishing.

  • Personification of the chatbot. Cases that escalated tended to involve users treating the model as an entity with its own perspective, intentions, or relationship. Personification accelerates emotional intensity and reduces natural skepticism.

  • Social withdrawal and parasocial isolation. Reduction in time with humans paired with an increase in time with the chatbot, particularly when the chatbot is replacing rather than supplementing human contact during distress.

  • Beliefs that the chatbot is communicating with you specifically, has special knowledge of you, or is conveying messages from elsewhere. The 2025–2026 case coverage documents users believing the chatbot was channeling deceased family members, revealing hidden cabals, conveying messages from spirits, or relaying information it could not plausibly have.

  • Intense emotional dependence on chatbot validation. Calm only in the chatbot’s presence; distressed when separated.

  • Acting on chatbot-generated content in significant ways. Major life decisions, financial decisions, medical changes (the documented 2025 bromism case began with ChatGPT advice to substitute sodium bromide for table salt), or interpersonal actions taken in response to chatbot suggestions without external check.

  • Decline in real-world functioning. Work, relationships, and self-care begin to deteriorate.

  • Immersive AI environments. A January 2026 Futurism report described an individual who, after extensive use of Meta smartglasses with embedded AI, ended up wandering the desert searching for aliens. Voice assistants, smartglasses, and continuous-conversation interfaces can amplify the same dynamics.

Several of these signs appearing together, particularly with rising intensity, warrant clinical contact.

Steps You Can Take

These are not vigilance instructions, vigilance does not scale. They are structural practices that reduce risk without requiring real-time self-monitoring.

Treat heavy chatbot use the way you would treat heavy use of anything else with elevated risk. If you have a personal or family history of psychotic-spectrum conditions, mood disorders with psychotic features, dissociative phenomena, or substance-induced psychosis, apply the same caution you would to any elevated-risk behavior.

Limit nocturnal sessions. A simple rule, no extended chatbot sessions after midnight, is structurally protective in a way that requires no willpower in the moment.

Maintain unmediated human contact. Schedule it if necessary. The friction of other minds is one of the foundational mechanisms by which unusual ideas fail to consolidate. If chatbot conversation is replacing rather than supplementing human contact, that is the pattern to interrupt.

Be careful with topics on which you have previously had unusual or intense ideas. Mystical, conspiratorial, surveillance-related, or technology-singularity themes are exactly the topics on which the chatbot’s sycophancy is most likely to drift you in a direction that does not serve you.

Notice when the chatbot starts to feel like a person to you. If you find yourself feeling that the chatbot understands you in a way no human does, that it has special knowledge of you, or that you are calmer in its presence than in your own life, step back.

Do not use a general-purpose chatbot as a therapist. Current general-purpose LLMs are not licensed mental-health providers. Illinois banned their use in licensed therapeutic roles in August 2025, and other jurisdictions have moved similarly through 2026.

Talk to your clinician about your AI use. Following the Psychiatric Times recommendation, mention it at intake the way you would mention sleep, alcohol, or social media. It is environmental input that affects how a clinician understands your situation.

What the Public Conversation Has Gotten Wrong

The alarmist version, that chatbots are causing a wave of new psychotic disorders in healthy users, is still not supported by the current evidence in its strongest form. There is no epidemiological study, as of April 2026, that establishes a population-level causal effect.

The dismissive version, “AI psychosis is moral panic, no different from earlier panics about novels, comic books, or video games”, has aged worse than the alarmist version. Earlier panics were largely about content. The mechanism here is structural, measurable, and now beginning to be quantified at scale. The analogy never quite worked. By 2026, it will not work at all.

Both extremes treat AI psychosis as a single thing that either exists or does not. The clinically useful framing remains more specific: the pattern is real, the mechanism is increasingly well-understood, the risk is bounded but broader than the strongest 2024 framing suggested, and the intervention points exist at the platform, clinical, and policy levels. None of this requires panic. None of it allows dismissal.

Frequently Asked Questions

What is AI psychosis?
A descriptive label, not a recognized clinical diagnosis. It refers to a pattern in which users develop or consolidate psychotic symptoms during extended chatbot use, often through the removal of external-correction friction by sycophantic conversational systems. The phrase first appeared in clinical commentary by Søren Dinesen Østergaard in 2023.

Is AI psychosis real?
The pattern is clinically real and now documented in peer-reviewed work. The label is not a recognized diagnosis. The careful clinical position is that the phenomenon represents a familiar psychiatric trajectory altered by a novel conversational input.

Can chatbots make people psychotic?
The 2026 evidence is more conditional than the 2024 evidence was. There is no epidemiological study establishing a population-level causal effect. There is now a peer-reviewed case in a patient without prior history, and broader peer-support data suggesting the affected population is less narrowly bounded than the early framing predicted.

What are the warning signs?
Sleep disruption with heavy nocturnal chatbot use; increasing preoccupation with idiosyncratic ideas; personification of the chatbot; social withdrawal; beliefs the chatbot is communicating specifically with you; intense emotional dependence on chatbot validation; significant life decisions taken on chatbot suggestion; decline in real-world functioning. None alone indicates psychosis, several together, with rising intensity, warrant clinical contact.

Who is at higher risk?
Highest risk: users with pre-existing or prodromal vulnerability, family history of psychotic-spectrum disorders, sleep deprivation, social isolation, substance use, adolescent and young-adult age. The 2026 evidence suggests the broader population may be less narrowly bounded than this list alone implies.

Can AI chatbots be used as therapists?
Current general-purpose LLMs are not licensed mental-health providers. Illinois banned their use in licensed therapeutic roles in August 2025. Therapeutic chatbot products with clinical oversight are an active area of research, but a general-purpose chatbot is not a substitute for a licensed clinician.

What should I do if I am worried about someone close to me?
The classical warning signs of psychiatric vulnerability remain the relevant signals. Reach out, reduce isolation, support unmediated human contact, and involve a licensed clinician early. Mention the chatbot context to the clinician, in line with the 2026 Psychiatric Times guidance.

Sources

Peer-Reviewed Literature

  • Østergaard, S. D. (2023). Will generative artificial intelligence chatbots generate delusions in individuals prone to psychosis? Schizophrenia Bulletin. Link
  • Innovations in Clinical Neuroscience (2026). “You’re Not Crazy”: A Case of New-onset AI-associated Psychosis. PubMed
  • British Journal of Psychiatry (2026). Chatbot psychosis: moving beyond recognition to mechanistic understanding and harm reduction. Cambridge Core
  • JMIR Mental Health (2025). Delusional Experiences Emerging From AI Chatbot Interactions. JMIR
  • Eichenberger et al. (2025). A Case of Bromism Influenced by Use of Artificial Intelligence. Annals of Internal Medicine: Clinical Cases. Link
  • Sakata, K., et al. (2026). Quantifying improvement of psychotic symptoms… clinical note analysis with large language models. PMC

News & Public Commentary

  • The Guardian (March 26, 2026). Marriage over, €100,000 down the drain: the AI users whose lives were wrecked by delusion.
  • UCSF News (January 20, 2026). Psychiatrists hope chat logs can reveal the secrets of AI psychosis.
  • Psychiatric News (February 2026). The Hallucinating Machine.
  • Mad in America (March 20, 2026). AI Chatbots in Mental Health: Promise, Dependence, and Growing Concerns.
  • Fortune (March 2026). New research: AI chatbots may worsen mental illness.
  • Futurism (January 15, 2026). A Venture Capitalist Is Going Through AI-Induced Psychosis.

Technical Reports & Regulations

  • RAND Corporation (2026). Manipulating Minds: Security Implications of AI-Induced Psychosis.
  • Sharma, M., et al. (2023). Towards understanding sycophancy in language models. Anthropic. arXiv
  • Illinois Wellness and Oversight for Psychological Resources Act (HB 1806). Enacted August 2025.
  • China Cyberspace Administration Regulation (December 2025). Draft/Final rules on “Human-like interactive AI services” and mental health safeguards.

Too many .xml files to manage? Here is a simple and lightweight cli that solves that!

XMLM – XML Analysis Tool

A simple terminal tool that reads one or more XML files and processes them using natural language. Summarize, analyze, and compare XML files with ease.

In a nerdy way to say:

XMLM is a Node.js-based CLI tool that integrates Ollama (with local model files) to provide smart analysis of XML files. It can generate summaries of individual files or compare multiple files to identify differences and similarities. Can used for big ammounts of files or information.

Here is the github repo: everm4iva/xmlm-cli

Implement SAML SSO Authentication in Laravel Filament with Socialite

Single Sign-On (SSO) is a common requirement in enterprise applications.

When working with Laravel Filament in internal business environments, clients often want to authenticate users directly through:

  • Active Directory
  • Microsoft Entra ID (Azure AD)
  • Okta
  • Keycloak
  • Google Workspace

Instead of managing passwords inside your application.

In this article, we’ll build a clean SAML SSO integration using:

  • Laravel Socialite
  • The Socialite SAML2 provider

The goal is not only to make authentication work, but also to build a maintainable foundation for enterprise environments.

At the end of this article, you’ll have:

  • SAML authentication working inside Filament
  • A metadata endpoint for your Identity Provider
  • A dedicated authentication flow
  • A clean architecture ready for role synchronization

In the premium follow-up article, we’ll implement:

  • Active Directory group mapping
  • Spatie Permission synchronization
  • Production-ready role handling
  • Enterprise access control strategies

Installing the SAML2 Provider

First, install Laravel Socialite and the SAML2 provider:

composer require laravel/socialite
composer require socialiteproviders/saml2

You can then configure your SAML provider inside config/services.php.

Configuring the SAML Provider

Here is a simple SAML configuration:

'saml2' => [
    'metadata' => env('SAML2_METADATA_URL', 'http://localhost:4000/api/saml/metadata'),
    'sp_acs' => 'auth/saml2/callback',
    'sp_default_binding_method' => LightSamlSamlConstants::BINDING_SAML2_HTTP_POST,
    'sp_name_id_format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
],

Depending on your security requirements, you may also need signed or encrypted assertions.

Understanding the Configuration

metadata

This is the Identity Provider metadata URL.

Depending on your environment, this could come from:

  • Microsoft Entra ID
  • Okta
  • Keycloak
  • A local SAML testing provider

The provider uses this metadata to retrieve:

  • certificates
  • SSO endpoints
  • bindings
  • entity identifiers

sp_acs

This is your Assertion Consumer Service (ACS) endpoint.

After authentication, the Identity Provider redirects the user back to this endpoint.

In our case:

/auth/saml2/callback

sp_default_binding_method

This defines how SAML responses are transmitted.

Using POST binding is generally the safest and most common option.

Creating the Controller

A dedicated controller keeps the authentication flow clean and isolated.

<?php

namespace AppHttpControllersAuth;

use AppServicesSAML2Service;
use FilamentNotificationsNotification;
use IlluminateHttpRedirectResponse;
use IlluminateHttpResponse;

class SAML2Controller extends Controller
{
    public function __construct(protected SAML2Service $saml2Service) {}

    public function metadata(): Response
    {
        return $this->saml2Service->metadata();
    }

    public function redirect(): RedirectResponse
    {
        return $this->saml2Service->redirect();
    }

    public function callback(): RedirectResponse
    {
        $user = $this->saml2Service->callback();

        if (! $user) {
            Notification::make()
                ->title(__('Unable to connect. Please contact an administrator.'))
                ->danger()
                ->send();
        }

        return redirect(filament()->getUrl());
    }
}

Why Use a Dedicated Service?

Many authentication tutorials place all the logic directly inside the controller.

This quickly becomes difficult to maintain when adding:

  • role synchronization
  • multiple providers
  • access policies
  • audit logging
  • tenant support

Moving the SAML logic into a dedicated service keeps the architecture maintainable.

Defining the Routes

Next, create the authentication web routes:

Route::prefix('auth/saml2')
    ->name('auth.saml2.')
    ->controller(AppHttpControllersAuthSAML2Controller::class)
    ->group(function () {
        Route::get('metadata', 'metadata')->name('metadata');
        Route::get('redirect', 'redirect')->name('login');
        Route::post('callback', 'callback')->name('callback');
    });

This gives us:

  • /auth/saml2/metadata : Service Provider metadata
  • /auth/saml2/redirect : Redirect to Identity Provider
  • /auth/saml2/callback : Handle SAML response

Building the SAML Service

Now let’s implement the service.

<?php

namespace AppServices;

use AppModelsUser;
use FilamentFacadesFilament;
use IlluminateHttpResponse;
use IlluminateSupportFacadesAuth;
use LaravelSocialiteFacadesSocialite;
use SocialiteProvidersSaml2Provider;
use SymfonyComponentHttpFoundationRedirectResponse;

class SAML2Service
{
    public function redirect(): RedirectResponse
    {
        return Socialite::driver('saml2')->redirect();
    }

    public function callback(): ?User
    {
        /** @var Provider $saml2Provider */
        $saml2Provider = Socialite::driver('saml2');

        /** @var SocialiteProvidersSaml2User $socialiteUser */
        $socialiteUser = $saml2Provider->stateless()->user();

        $user = User::query()->updateOrCreate(
            ['email' => strtolower($socialiteUser->getEmail())],
            ['name' => $socialiteUser->getName()]
        );

        if ($user->canAccessPanel(Filament::getCurrentOrDefaultPanel())) {
            Auth::login($user);

            return $user;
        }

        return null;
    }

    public function metadata(): Response
    {
        /** @var Provider $saml2Provider */
        $saml2Provider = Socialite::driver('saml2');

        return $saml2Provider->getServiceProviderMetadata();
    }
}

Understanding the Authentication Flow

Redirecting the User

return Socialite::driver('saml2')->redirect();

This sends the user to the Identity Provider login page.

Depending on the environment, users may already be authenticated through their corporate session.

Retrieving the Authenticated User

$socialiteUser = $saml2Provider->stateless()->user();

The provider validates the SAML response and extracts the user information.

At this stage, you usually receive:

  • email
  • first name
  • last name
  • groups
  • claims

The exact payload depends on your Identity Provider configuration.

Creating or Updating the User

User::query()->updateOrCreate(...)

This approach allows users to authenticate without pre-creating accounts manually.

It also keeps user information synchronized automatically.

Restricting Filament Access

$user->canAccessPanel(...)

This is an important step.

Authenticating a user does not necessarily mean they should access your Filament panel.

By checking panel access explicitly, you keep your authorization layer consistent with the rest of your application.

Generating Service Provider Metadata

One of the most useful features of the provider is automatic metadata generation.

return $saml2Provider->getServiceProviderMetadata();

This endpoint can be shared directly with your Identity Provider administrator.

It avoids:

  • manually crafting XML files
  • configuration mistakes
  • certificate inconsistencies

In many enterprise environments, this alone saves a significant amount of setup time.

Improving the Login Experience in Filament

You can now add a custom login button inside your Filament login page.

For example with a render hook:

FilamentView::registerRenderHook(
    PanelsRenderHook::AUTH_LOGIN_FORM_BEFORE,
    fn (): View => view('filament.components.saml-login-button')
);

In provider file (like AppServiceProvider.php boot function)

<x-filament::button
    href="{{ route('auth.saml2.login') }}"
    tag="a"
    color="primary"
    class="w-full"
    icon="heroicon-o-arrow-right-circle"
    aria-label="Connect with your SSO account"
>
    {{ __('Connect with your SSO account') }}
</x-filament::button>

In view file filament.components.saml-login-button.blade.php

This provides a much cleaner enterprise login experience.

Testing

For local development and testing, I personally use MockSAML:

This is also why the default metadata configuration points to port 4000:

'metadata' => env(
    'SAML2_METADATA_URL',
    'http://localhost:4000/api/saml/metadata'
),

Using a lightweight mock Identity Provider makes it much easier to test:

  • SAML authentication flows
  • user provisioning

Without requiring access to a real enterprise Active Directory during development.

What About Active Directory Groups?

At this point, authentication works.

However, most enterprise applications also need:

  • role synchronization with Active Directory group mapping
  • dynamic authorization

This is where things become significantly more interesting.

In the premium article, we’ll implement:

  • automatic role synchronization
  • group parsing from SAML claims
  • Active Directory CN extraction
  • role mapping strategies
  • production-ready access control

SAML authentication is often perceived as complex, but Laravel Socialite combined with the SAML2 provider makes the integration surprisingly clean.

By isolating the authentication flow into a dedicated service and integrating directly with Filament, you can build enterprise-ready authentication while keeping your application maintainable.

The next step is implementing proper authorization and Active Directory role synchronization.

To receive more articles like this one, subscribe to Filament Mastery!

AI wrote my bug. I shipped it anyway. Here’s what I learned.

Last month, I let AI “help” me refactor a small but performance-critical bit of frontend code. It confidently gave me a clean, modern solution. Types checked, tests were green, and the code looked nicer than what I’d written before. I merged it.

Two days later, a user reported that a key interaction was randomly failing. Turned out the bug was subtle, intermittent, and 100% introduced by that AI-generated snippet. The worst part: the code looked so reasonable that my brain just rubber-stamped it.

This is how AI is in my workflow now: incredibly useful, occasionally dangerous, and something I treat more like a junior teammate than a trusted source of truth.

Tools in my day-to-day workflow
Here’s what I actually use as a JavaScript/web dev working on real projects:

GitHub Copilot for inline suggestions, writing boilerplate React components, and quick refactors.

Claude for “bigger brain” tasks: explaining legacy code, generating first-draft docs, and exploring alternative designs.

Browser devtools + tests as the “reality check” layer when AI feels too confident.

AI’s job in my workflow is to speed up the “typing” and help me explore ideas, not to replace my thinking.

When AI really helped: reducing noisy event handlers
I had a React component that attached a scroll listener and did some heavy work on every event. It wasn’t catastrophic, but it caused jank on low-end devices. I asked Copilot to suggest a lightweight throttling solution.

AI-generated suggestion (good enough start)
js
// AI suggestion: basic throttle for scroll handler
function throttle(fn, delay) {
let lastCall = 0;

return function (…args) {
const now = Date.now();
if (now – lastCall >= delay) {
lastCall = now;
fn.apply(this, args);
}
};
}

function handleScroll() {
// expensive calculation
}

window.addEventListener(‘scroll’, throttle(handleScroll, 100));
This was actually pretty decent for my use case. It avoided calling handleScroll on every scroll event and eliminated most of the jank.

I still made adjustments:

Extracted the throttle into a shared utility.

Added proper typing and tests.

Verified behavior in the browser with real scrolling patterns.

Final version after review
ts
// utils/throttle.ts
export function throttle void>(
fn: T,
delay: number
) {
let lastCall = 0;
let timeoutId: number | null = null;

return function (this: unknown, …args: Parameters) {
const now = Date.now();
const remaining = delay – (now – lastCall);

if (remaining <= 0) {
  lastCall = now;
  if (timeoutId !== null) {
    window.clearTimeout(timeoutId);
    timeoutId = null;
  }
  fn.apply(this, args);
} else if (timeoutId === null) {
  timeoutId = window.setTimeout(() => {
    lastCall = Date.now();
    timeoutId = null;
    fn.apply(this, args);
  }, remaining);
}

};
}
AI got me 60–70% of the way. I added the rest: better handling of calls at the edges, reuse, and type safety.

This is AI at its best in my workflow: drafting something reasonable that I then refine.

When AI misled me: a subtle async bug
Now the painful story.

I had some code that needed to ensure a DOM element existed before measuring it. I asked Copilot for a small helper that “waits for an element to exist then resolves with it or times out.” Copilot produced something like this:

AI suggestion (looked correct, wasn’t)
js
function waitForElement(selector, timeout = 3000) {
return new Promise((resolve, reject) => {
const element = document.querySelector(selector);
if (element) {
resolve(element);
return;
}

const observer = new MutationObserver(() => {
  const el = document.querySelector(selector);
  if (el) {
    observer.disconnect();
    resolve(el);
  }
});

observer.observe(document.body, { childList: true, subtree: true });

setTimeout(() => {
  observer.disconnect();
  reject(new Error('Element not found'));
}, timeout);

});
}
At a glance, it looked fine: observe DOM mutations, resolve when the element appears, reject on timeout. I skimmed it, tests passed, and I shipped it.

The bug? Under certain conditions, the timeout fired after the element was found and resolved. In rare race conditions, the promise would resolve and then later be rejected, causing unpredictable error handling elsewhere.

Corrected version with proper cleanup
js
function waitForElement(selector, timeout = 3000) {
return new Promise((resolve, reject) => {
const existing = document.querySelector(selector);
if (existing) {
resolve(existing);
return;
}

let settled = false;
const observer = new MutationObserver(() => {
  const el = document.querySelector(selector);
  if (el && !settled) {
    settled = true;
    observer.disconnect();
    window.clearTimeout(timeoutId);
    resolve(el);
  }
});

observer.observe(document.body, { childList: true, subtree: true });

const timeoutId = window.setTimeout(() => {
  if (!settled) {
    settled = true;
    observer.disconnect();
    reject(new Error(`Element not found: ${selector}`));
  }
}, timeout);

});
}
Key differences:

Introduced a settled flag.

Cleared the timeout when resolving.

Guarded both paths so the promise only settles once.

This is exactly the kind of subtle bug AI is prone to: the logic is “plausible” and looks idiomatic, but it hasn’t been truly thought through.

My framework for trusting AI (or not)
Here’s how AI fits into my decision-making:

Use AI for:

Boilerplate and repetitive patterns.

Utility functions that I heavily review.

Alternative approaches I might not think of on my own.

Writing tests and docs drafts that I refine.

Be skeptical when:

The code touches async, concurrency, or subtle browser behavior.

It involves security, authentication, or data validation.

The code “just works” and I don’t fully understand why.

Non-negotiables before merging AI code:

Read it line by line and explain it in plain language.

Add tests that would have caught the bug if the code were wrong.

Run it in a realistic environment, not just unit tests.

The mindset shift: AI is a junior engineer with infinite stamina but no real understanding. If it writes something you don’t fully get, that’s your bug waiting to happen.

Your turn
AI is now part of most dev workflows, for better or worse. For me, it’s worth the risk—but only when paired with a strong review habit and healthy skepticism.

How are you using AI in your workflow right now, and what’s one time it either saved you hours or nearly burned you—what happened?

First Look at Google AI Studio + Gemini at I/O 2026

🚀 First Look at Google AI Studio + Gemini at I/O 2026

Google I/O 2026 wasn’t just about flashy demos — it was about making AI practical for developers. For me, the standout announcement was the evolution of Gemini into a full ecosystem, anchored by Google AI Studio.

🌟 Why It Matters

Until now, experimenting with large models often meant juggling APIs, SDKs, and cloud credits. With AI Studio, Google is positioning Gemini as the fastest way to start building — lowering the barrier for developers who want to prototype, test, and deploy AI-powered apps.

This shift feels less like “another model release” and more like a platform moment. Gemini isn’t just a model anymore; it’s the connective tissue across Google’s ecosystem — from Docs and Gmail to Firebase and Cloud.

🛠️ Hands-On Impressions

I spent time exploring AI Studio during I/O, and here’s what stood out:

  • Instant Playground: You can spin up a Gemini-powered app in minutes, no complex setup.
  • Tight Integration: Firebase and Cloud hooks are built-in, meaning you can go from prototype to production without duct tape.
  • Transparency: Google emphasized responsible AI, with clear usage dashboards and guardrails.

It reminded me of the early days of Firebase — simple, approachable, and developer-first.

🔍 My Take

The most underrated aspect of this release is accessibility for small teams. While enterprises will benefit from Gemini’s scale, indie developers now have a way to experiment without heavy infrastructure. This democratization could spark the next wave of AI-driven startups.

📚 Resources

💡 Community Question: What’s the first app or workflow you’d build with Gemini in AI Studio?

👉 Suggested tags: #GoogleIO2026 #Gemini #AIStudio #GoogleAI #Cloud #Firebase #AI #DeveloperTools

Software Engineer Resume Keywords 2026: How to Beat ATS and Impress Recruiters

If your software engineer resume is getting ignored, keyword misalignment is often the culprit. Not because you’re unqualified — but because your resume doesn’t speak the same language as the job description or the ATS parsing it.

Here’s the thing most candidates miss: resume keywords aren’t just a list of tools. They’re role signals. They tell a recruiter what kind of engineer you are, which systems you’ve worked on, and whether you can hit the ground running on their team.

This guide breaks down which software engineer resume keywords matter most in 2026, how to choose them strategically, and how to rewrite weak bullets into recruiter-ready proof.

Why Keywords Are Make-or-Break in 2026

Modern recruiting runs two filters before a human reads your resume: an ATS parser and a recruiter who skims for 10 seconds. Both are keyword-sensitive.

The ATS doesn’t know you’re a great engineer — it matches text. The recruiter scans for familiar patterns: role type, stack, scope, outcomes. If those signals aren’t visible in the top half of the page, your resume loses both races.

The fix isn’t to dump every technology you’ve ever touched. It’s to make four things obvious fast:

  • What kind of engineer you are (backend, frontend, full stack, platform)
  • What stack you actually use
  • What systems or products you’ve built
  • What measurable outcomes you’ve driven

The Right Keywords by Engineer Type

Not all SWE resumes are the same. Here’s what each specialty should prioritize:

Backend engineers should highlight: Python, Java, Node.js, REST APIs, microservices, PostgreSQL, Redis, AWS, scalability, observability.

Frontend engineers should feature: React, TypeScript, JavaScript, component libraries, accessibility, performance optimization, state management, design systems.

Full stack engineers need both worlds plus: end-to-end feature delivery, API integration, deployment pipelines, product collaboration.

New grads don’t need production scale — but they do need to show shipped work: full stack projects, internship scope, data structures, algorithms, debugging, testing.

The key insight: don’t try to be everything. Your top half should clearly signal the specific role you’re targeting.

How to Extract Keywords from a Job Description

Most candidates over-highlight tools and miss the hiring language buried in responsibilities. Here’s a better approach — pull from four buckets:

  1. Job title and seniority — the exact or near-exact title in the posting
  2. Technical stack — languages, frameworks, infra, databases
  3. Responsibilities and ownership — the verbs matter (“led”, “owned”, “partnered”)
  4. Business or system outcomes — what success looks like in the role

For example, if a posting repeatedly mentions “Backend Engineer,” “Python,” “AWS,” “microservices,” “REST APIs,” and “scalability” — those aren’t just keywords. They’re the shape of the story your resume needs to tell.

Real Before/After: Keyword Rewrite

Target role: Full Stack Engineer (React, TypeScript, Node.js, product stakeholders)

Before:

  • Built product features for internal users
  • Worked on backend services and frontend changes
  • Helped improve application performance

After:

  • Built React and TypeScript product workflows for internal operations users, improving task completion speed by 18%
  • Shipped Node.js API integrations and backend service updates for internal tooling used across support and product teams
  • Improved application performance by reducing duplicate data-fetching and simplifying client-side rendering paths

The difference? Stack is explicit. Scope is clear. Outcomes are measurable. And every bullet now sounds like language borrowed from the job description — because it is.

The 5 Keyword Mistakes That Kill SWE Resumes

1. Listing tools without showing where they were used. Keywords attached to nothing are empty signals.

2. Using a vague title. “Software Engineer” can mean anything. If you want backend roles, say backend. If you want full stack, make that visible at the top.

3. Mixing outdated and current keywords randomly. Old tools can stay on the resume — but the top half should reflect your current target direction.

4. Copying job descriptions word-for-word. It reads as artificial and creates weak interview follow-through. Use the language; don’t plagiarize it.

5. Forgetting that resume keywords must connect to interview stories. If your resume says microservices, caching, or observability — be ready to explain those choices in depth. Your resume creates expectations your interviews must fulfill.

How Many Keywords Is Enough?

More is not better. For most SWE resumes:

  • 1 clear target title near the top
  • 8–12 high-signal keywords drawn from the posting
  • 4–6 strong bullets that pair stack with outcome language

Anything beyond that tends to dilute rather than strengthen.

A Quick ATS Optimization Workflow

  1. Pull the 8–12 repeated terms from the job description
  2. Make your target role title visible near the top
  3. Rewrite your summary around your actual stack and scope
  4. Update the skills section so the most relevant tools appear first
  5. Rewrite your best 4–6 bullets with stack + impact language
  6. Compare the final draft against the posting one more time

If you’re submitting through systems like Workday, pay extra attention to formatting — tables, text boxes, and multi-column layouts can break parsing.

The Recruiter Questions Your Resume Needs to Answer

Every recruiter scanning a SWE resume is implicitly asking:

  • What kind of engineer is this, exactly?
  • Which stack do they actually use in production?
  • Have they built customer-facing systems or internal tools?
  • Do they have scale, performance, or reliability experience?
  • Are their bullets outcome-driven or generic?
  • Does the resume match the role they’re applying for?

The best software engineer resumes answer all of these in the first half of the page.

Putting It Together

Keyword optimization isn’t a trick — it’s a communication skill. Your job is to make the fit between your experience and the role immediately visible to both an algorithm and a human.

Start with the job description. Pull the language that repeats. Build your bullets around stack, scope, and outcomes. Make your role type unmistakable. Keep the skills section relevant and current.

Read the full article here

Been using ManyOffer to sharpen my own answers — if you want AI mock interviews with real LP feedback, they have a deal running through July worth checking out: Claim 1 free month here

Forge Review: 8B Local Model Hits 99% on Agentic Tasks

Originally published on andrew.ooo — visit the original for any updates, code snippets that aged out, or follow-up posts.

TL;DR

Forge is a Python reliability layer for self-hosted LLM tool-calling, built by Antoine Zambelli, AI Director at Texas Instruments. It hit the Hacker News front page on May 19, 2026 with 206 points and a tagline that did the heavy lifting on its own: “Guardrails take an 8B model from 53% to 99% on agentic tasks.”

The headline result, drawn from Forge’s own 26-scenario eval suite:

  • Bare 8B local model: ~53% on multi-step agentic workflows
  • Same 8B model + Forge guardrails: 99.3%
  • Claude Sonnet, no guardrails: 87.2%
  • Claude Sonnet + Forge: ~100%

That second-to-last line is the one that makes people sit up: a $0 local 8B model on a $600 GPU, wrapped in Forge, beats a frontier API used the normal way. The gap between bare-metal local inference and a cloud API closes to less than 1 percentage point when both sides run through Forge. The framework, the ablation study, and the methodology are written up in an IEEE-track paper (Zambelli 2026, DOI: 10.1145/3786335.3813193).

Key facts:

  • MIT licensed, pip-installable as forge-guardrails
  • Backends: Ollama, llama-server (llama.cpp), Llamafile, Anthropic
  • Top eval config: Ministral-3 8B Instruct Q8 on llama-server
  • Three usage modes: full WorkflowRunner, middleware-only, drop-in OpenAI-compatible proxy
  • Core trick: rescue parsing, retry nudges, step enforcement, tiered context compaction, plus a synthetic respond tool that keeps small models in tool-calling mode
  • 865 deterministic unit tests + 26-scenario eval harness
  • Status: active (Python 3.12+), authored solo, real paper backing it

If you have a 24 GB GPU sitting in a closet and you’ve been waiting for the moment when “self-hosted agents” stops meaning “self-hosted toys,” this is the moment.

Quick Reference

Field Value
Repo github.com/antoinezambelli/forge
Author Antoine Zambelli (AI Director, Texas Instruments)
License MIT
Language Python 3.12+
Install pip install forge-guardrails
HN debut May 19, 2026 — 206 points
Top eval result 99.3% (Ministral-3 8B Q8 + Forge)
Hardest tier score 76% (Ministral-3 8B Q8, advanced_reasoning subset)
Backends Ollama, llama-server, Llamafile, Anthropic
Paper DOI 10.1145/3786335.3813193

Why this matters

For most of 2025 and early 2026, the conventional wisdom on local agents was: nice for chat, useless for tool calling. Anyone who plugged a local 8B into a five-step workflow watched it confidently call get_weatherr with a typo, return text instead of a JSON tool call, forget which step it was on, and time out somewhere in the middle. Real agentic use stayed on frontier APIs.

Forge’s contribution is to show that the gap is not really a model problem — it’s a harness problem. The model knows how to call tools. It just needs:

  1. Permission to fail and try again (retry nudges)
  2. A parser that can salvage a malformed call instead of throwing
  3. A reminder of which step it’s on when it wanders
  4. A context manager that doesn’t quietly truncate the last tool result
  5. A way to emit text without leaving tool-calling mode

Stack those five things and the same weights that score 53% raw score 99%. That’s the entire argument, and Forge implements every piece of it as composable middleware so you can use the parts you need.

Install in three minutes

# core only
pip install forge-guardrails

# plus the Anthropic client
pip install "forge-guardrails[anthropic]"

You also need a backend. Forge is most opinionated about llama-server (its top-10 eval configs all run on it), but Ollama is the easiest on-ramp:

# Ollama path — easiest
ollama pull ministral-3:8b-instruct-2512-q4_K_M

# llama-server path — best performance
llama-server -m path/to/Ministral-3-8B-Instruct-2512-Q8_0.gguf 
  --jinja -ngl 999 --port 8080

The --jinja flag matters. It’s what enables native function calling in llama.cpp, and without it you fall back to prompt-injected tool calling, which is measurably worse on the harder eval tier.

A real workflow in 30 lines

This is the canonical Forge example, lightly trimmed from the README:

import asyncio
from pydantic import BaseModel, Field
from forge import (
    Workflow, ToolDef, ToolSpec,
    WorkflowRunner, OllamaClient,
    ContextManager, TieredCompact,
)

def get_weather(city: str) -> str:
    return f"72°F and sunny in {city}"

class GetWeatherParams(BaseModel):
    city: str = Field(description="City name")

workflow = Workflow(
    name="weather",
    description="Look up weather for a city.",
    tools={
        "get_weather": ToolDef(
            spec=ToolSpec(
                name="get_weather",
                description="Get current weather",
                parameters=GetWeatherParams,
            ),
            callable=get_weather,
        ),
    },
    required_steps=[],
    terminal_tool="get_weather",
    system_prompt_template="You are a helpful assistant. Use the available tools to answer the user.",
)

async def main():
    client = OllamaClient(
        model="ministral-3:8b-instruct-2512-q4_K_M",
        recommended_sampling=True,
    )
    ctx = ContextManager(
        strategy=TieredCompact(keep_recent=2),
        budget_tokens=8192,
    )
    runner = WorkflowRunner(client=client, context_manager=ctx)
    await runner.run(workflow, "What's the weather in Paris?")

asyncio.run(main())

What’s quietly happening behind that runner.run call:

  • ResponseValidator checks every model response against the tool schema, flags malformed JSON, and routes failures to the nudge system instead of bubbling them up.
  • StepEnforcer tracks required_steps (none in this example, but typical workflows have them) and refuses to terminate until they’re satisfied.
  • TieredCompact keeps the last 2 turns verbatim and compacts older turns when the context budget gets tight, so a runaway loop doesn’t quietly drop the original user request.
  • The retry nudge templates in forge/prompts/nudges.py produce small, surgical “you produced invalid output, here’s why, try again” messages instead of restarting the loop.
  • recommended_sampling=True auto-applies the sampling params the model card recommends, which Zambelli found made a measurable difference in tool-call accuracy on small models.

This pattern — defining a Workflow, picking a backend client, attaching a ContextManager, and handing both to WorkflowRunner — is the high-level entry point. If you’d rather keep your own orchestration loop, Forge also ships a middleware mode where you call its guardrails directly on responses you’ve already gotten back from a model.

The drop-in proxy mode (this is the killer feature)

This is the bit that will pull people in even if they have no interest in rewriting their stack:

# external mode — you run llama-server, Forge wraps it
python -m forge.proxy --backend-url http://localhost:8080 --port 8081

# managed mode — Forge starts llama-server for you
python -m forge.proxy --backend llamaserver 
  --gguf path/to/Ministral-3-8B-Instruct-2512-Q8_0.gguf --port 8081

Now point any OpenAI-compatible client — opencode, Continue, aider, your homegrown agent loop — at http://localhost:8081/v1 and you get the full Forge guardrail stack for free. The client thinks it’s talking to a smarter model.

Internally the proxy does one slightly diabolical thing: when a request contains tools, it injects a synthetic respond tool. The model is then expected to call respond(message="...") instead of emitting bare text. This keeps it in tool-calling mode at all times — which is where Forge’s guardrails apply — and the synthetic call is stripped from the outbound response so the client never sees it. ADR-013 in the repo has the full reasoning, but the short version: 8B models cannot be trusted to decide between “emit text” and “emit a tool call.” Force them to always pick a tool, and accuracy jumps.

The 26-scenario eval suite

Forge ships its own benchmark. Two tiers:

  • OG-18: 18 baseline scenarios covering single tool calls, multi-step workflows, parameter validation, and recovery from injected errors.
  • advanced_reasoning: 8 harder scenarios — chained dependencies, branching logic, ambiguous user prompts, partial information.

Run it yourself:

python -m tests.eval.eval_runner 
  --backend llamafile 
  --llamafile-mode prompt 
  --gguf "path/to/Ministral-3-8B-Instruct-2512-Q8_0.gguf" 
  --runs 10 --stream --verbose

# batch eval across configs
python -m tests.eval.batch_eval --config all --runs 50

# HTML dashboard
python -m tests.eval.report eval_results.jsonl

The published numbers:

Config OG-18 advanced_reasoning Combined
Ministral-3 8B Q8 (llama-server) + Forge ~93% 76% 86.5%
Ministral-3 8B Q8 (llama-server), bare — — ~53%
Claude Sonnet, bare — — 87.2%
Claude Sonnet + Forge — — ~100%

The “99.3% on agentic tasks” headline number comes from a narrower slice of the benchmark — strict tool-calling reliability, not the full combined score. Read the paper for the precise breakdown; Zambelli is straightforward about which number means what.

One of his most interesting eval findings, surfaced in the HN thread: the serving backend matters as much as the model. Mistral-Nemo 12B weights produce 7% accuracy on llama-server with native function calling and 83% on Llamafile in prompt-injected mode. Same weights. The difference is entirely in how the chat template hands the tool schema to the model.

Community reaction

The HN thread had real engineers in it. A few notes worth pulling out:

On the “small models with harnesses beat big models” thesis: “I’ve been saying for a while that given a proper harness, small local models can perform incredibly well. When you have a system that can try everything, it will eventually get it right as long as you can prevent it from getting it wrong in the meantime.” (HN user, 48200359)

Zambelli’s response: “Essentially, yes that’s right! There’s some subtlety in how to let it know it was wrong (returning things as tool errors because it trained on that), but that’s the gist of it — sort of a self-correcting architecture.”

The most useful piece of pushback, from a heavy local-LLM user: “Specifically for agentic workflows and local models, accuracy around function/tool calling hasn’t been a problem for me now for about 6 – 12 months, personally, since around QwenCoder3. The main issue is context management and the impact on timing… It looks like your work adds layers and wrappers like guard rails and retries. This would make my local model experience – specifically for agents – unusable because of the delays it would add.”

This is the right critique. Forge improves accuracy but adds round-trips. Zambelli responded by floating a new metric he’s going to start tracking: ETTWS — Estimated Time To Working Solution. A retry loop that succeeds on attempt three with three small models calls might still beat a single shot that gets 53% accuracy and then forces you to restart the whole workflow. But you need the data to defend that claim, and right now it’s not in the paper.

On the framing: “This is a thousand unusually smart monkeys who speak every major human language fluently and are proficient in every major programming language, but sometimes still make bizarre mistakes and need to be put back on track.” Forge is, in that framing, the trainer with the clicker.

Honest limitations

This is not a finished product. Things to know before you bet a workflow on it:

  1. No public latency benchmarks. All the published numbers are accuracy. The HN thread surfaced this and Zambelli acknowledged it. If you’re running an interactive agent, you need to time-box your retries and prove to yourself that the wall-clock-to-success is better than your current setup.

  2. Python only. No JS, Go, or Rust bindings. If your stack is Node-first, you’re either standing up a sidecar or waiting.

  3. Model coverage is uneven. The eval suite is heavily skewed toward the Ministral-3 family and Mistral-Nemo. Qwen, Llama 3.x, and Gemma configurations exist but are less battle-tested. The Model Guide in the repo is honest about which combos have been graded.

  4. The synthetic respond tool is a workaround, not a fix. Some users will be uncomfortable that the proxy injects an extra tool into every request. ADR-013 is worth reading before you adopt this in production.

  5. Multi-agent and slot-sharing support is brand new. SlotWorker (priority-queued access to a shared inference slot) is in the repo but isn’t yet a documented production pattern.

  6. Active solo project. It’s a one-maintainer project (Zambelli, plus an academic paper). If you adopt it, plan to read the code.

Forge vs. the alternatives

Project Focus Strength Weakness vs. Forge
Outlines / Instructor Structured output / JSON schema Mature, multi-language Doesn’t manage step enforcement or multi-step retry
LangGraph Agent orchestration Huge ecosystem No specific guardrails for self-hosted reliability; assumes the model gets it right
DSPy Prompt/program optimization Auto-tunes prompts Different layer — could compose with Forge
vLLM guided decoding Constrained generation at the token level Fastest Server-side only, ties you to vLLM
Forge Self-hosted tool-calling reliability + context mgmt Closes the local-vs-frontier gap Python-only, accuracy-first metrics

The cleanest mental model: Outlines/Instructor enforce schema, vLLM constrained decoding enforces tokens, LangGraph orchestrates flows, Forge enforces a workflow. They’re complementary, not competitive.

Who should adopt this today

  • Solo developers running local agents on a 24–48 GB GPU. You’ll feel the reliability jump on day one.
  • Teams building privacy-sensitive agentic products (legal, medical, on-prem) where a frontier API isn’t on the table and the current local stack is too flaky.
  • Research groups doing ablation studies on tool-calling reliability — Forge’s eval harness is already publication-quality.
  • Anyone running opencode, Continue, or aider against a local model and wishing it were less stupid. The proxy mode is a 30-second adoption.

Hold off if:

  • You need sub-second latency on every step and can’t tolerate retry overhead.
  • Your stack is Node-only and you can’t stomach a Python sidecar.
  • You’re already paying for frontier API access and your reliability problem is “Claude refused to call my tool once last week” — Forge is overkill for that.

FAQ

Q: Does Forge work with Qwen, Llama 3, or Gemma — or only Ministral?
A: It works with anything its backends support (Ollama, llama-server, Llamafile, Anthropic). The published eval numbers happen to be best on Ministral-3 8B Q8, but the framework is model-agnostic. The Model Guide in the repo is honest about which model + backend combos have been graded and which are “should work, untested.”

Q: How much slower is a Forge-wrapped run vs. a raw model call?
A: There are no public latency numbers yet, which is the main critique on HN. In practice, you’re trading wall-clock for completion rate: a single-shot 8B might return in 800ms and be wrong; a Forge-wrapped run might take 2–4 seconds and finish the workflow correctly. Zambelli is adding an ETTWS (Estimated Time To Working Solution) metric to the next paper rev specifically to address this.

Q: Do I have to use the WorkflowRunner, or can I just bolt the guardrails onto my existing loop?
A: You can absolutely just use the middleware. examples/foreign_loop.py in the repo shows how to call ResponseValidator, the nudge system, and the context manager directly. The full WorkflowRunner is convenient but optional.

Q: What’s the respond tool actually for?
A: 8B models trained on tool-calling datasets get confused when asked to choose between emitting plain text and emitting a tool call. Many will emit text when they should call a tool, or call a tool when they should just answer. The synthetic respond tool removes the choice: there’s always a tool to call, even for plain answers. The proxy strips it from the response on the way out so clients see normal text. ADR-013 in the repo has the full analysis and the eval data behind the decision.

Q: Is the IEEE paper open-access or paywalled?
A: The DOI (10.1145/3786335.3813193) may take a moment to resolve depending on publisher timing, but there’s a pre-publication preprint kept in the repo at docs/forge_ieee_preprint.pdf. Cite the DOI version, read the preprint.

Q: Does it support streaming?
A: Yes — StreamChunk and SSE streaming are first-class in the client and proxy layers. The proxy server can stream chunks to OpenAI-compatible clients while still applying guardrails on completion boundaries.

Q: Can I use it with Anthropic as a baseline / hybrid?
A: Yes. pip install "forge-guardrails[anthropic]" and use AnthropicClient as the backend. Useful for A/B tests against your local config or for hybrid workflows where part of the chain runs on Claude and part runs locally.

Bottom line

Forge is the most concrete answer yet to the question “is self-hosted agentic AI actually viable, or is it always going to be the toy alternative?” On the published evidence — and the IEEE paper behind it — the answer is: with the right harness, an 8B local model in a $600 GPU is functionally on par with a frontier API. That’s a tectonic shift for anyone who has been waiting for the moment when running real agents at home stops feeling masochistic.

The latency story is unfinished. The model coverage is uneven. It’s a solo project. None of that changes the headline result, which is one of the cleanest demonstrations of “framework matters more than weights” published this year.

If you have a GPU, install it tonight. Point your existing agent client at the proxy and see what happens. The setup cost is fifteen minutes; the upside is the local agent stack you’ve been waiting on.

Repo: github.com/antoinezambelli/forge
Paper: Zambelli 2026, DOI 10.1145/3786335.3813193
HN thread: news.ycombinator.com/item?id=48192383