DEV Community

shan han
shan han

Posted on

I haven't opened VS Code in 6 months — here’s what happened when AI took over my workflow

Author: Shan (HanShan) | Reflections after 20+ years of software engineering on transitioning from "typing code in an editor" to "driving development through AI dialogs."


The Icon I Rarely Click Anymore

Looking at my desktop dock, I can barely remember the last time I clicked on the VS Code icon. It stays there mostly out of habit and nostalgia.

VS Code Desktop Icon

Now, whenever I need to change something, my first instinct isn't opening a file—it's opening a chat prompt.

AI Chat Interface Workflow

This is what my workspace looks like every day. Over the past six months, I shipped three complete projects, fixed hundreds of bugs, and completely refactored a backend service suite. Not a single line of that code was typed out by hand in VS Code.

If someone had told me six months ago: "As a career programmer with over two decades of coding experience, you won't even bother opening your editor for half a year," I would have thought they were out of their mind.

Yet here we are: VS Code has virtually vanished from my daily workflow.

Empty Workspace / Shift to AI IDE

Even though VS Code has plenty of great AI plugins, I eventually said goodbye to it because native AI IDEs and agents handle context, agentic workflows, and tool execution significantly better.

Today, I want to unpack this half-year journey honestly: What actually happens to our development workflow when AI takes over writing code? And where does our core value as developers actually go?


Phase 1: The First 2 Weeks — Fingers on Autopilot, Mind Lagging Behind

The hardest part at the beginning was the cognitive dissonance.

When I first stopped using my traditional editor, my muscle memory kept betraying me.

I’d want to rename a variable, and my fingers would automatically press Cmd + P before I remembered there were no files to search. I’d want to inspect a utility function, switch over to an empty workspace, and freeze. Once, while adjusting CSS padding, I stared blankly at the screen for 10 minutes because "tweaking a pixel" had meant Open file → Search class → Edit value for twenty years—now I had to describe it in plain language.

I genuinely wondered if I was losing my edge.

Then it hit me: The discomfort wasn't from a lack of tools; it was from having my mental model ripped away.

Mental Model Shift Diagram

For decades, developers operated under a File-Centric View.

You carried a file tree in your head: which component lived in components, which API endpoint was in api, how state trickled down, where an enum was defined vs. consumed. When a bug popped up, you set breakpoints, sprinkled console.log statements, and climbed up the call stack.

Switching completely to Agentic workflows, MCP (Model Context Protocol), and terminal-native AI tools inverted this entire model into a Task & System View.

I no longer care which exact line a function lives on. I only provide three things: System Boundaries, Data Structure Definitions, and Expected Inputs/Outputs. The rest is the Agent's job—indexing the codebase, creating branches, editing files, running tests, and telling me: "Done. Ready to merge?"

It felt strange at first. Handing over the keyboard meant handing over the map—the mental map of my codebase.

File-Centric View Task & System View
Starting Point Create a new project file Write a detailed Specification
Mental Load Directory trees, file paths, naming conventions Module boundaries, data flow, failure modes
Debugging Breakpoints, logging, stepping through stack traces Describe the symptom → AI investigates logs & repos
Deliverable A snippet of code A verified change + Git diff
Developer Role Producer (Typist + Craftsman) Approver (Architect + Reviewer)
Amplified Skill Typing speed, path memory, debugging patience System definition, judgment, critical inquiry

After a month, I accepted a humbling truth:

70% of our time in the past wasn't spent "thinking about systems"—it was spent acting as human code converters.

Translating comments into syntax, design mocks into functions, or refactoring three legacy files into a new API—this boilerplate consumption dominated our daily lives. It gave us a sense of "productivity," but it wasn't where real engineering lived.


Phase 2: Six Months In — My New Development Stack

Once the adjustment period passed, three main pillars replaced my old editor-centric workflow:

Pillar 1: Writing Specifications Instead of Writing Code

Development no longer starts with touch index.ts; it starts with an extremely explicit specification document.

The clearer my definitions for module boundaries and data flow are, the sturdier the generated architecture becomes. Ambiguity in specs directly translates to exponential rework.

My pre-implementation spec template looks like this:

Goal

In one sentence: What problem does this module solve, and what is explicitly OUT of scope?

Boundaries

  • Input: Fields / Types / Caller
  • Output: Fields / Types / Return behavior on failure
  • Out of scope: Explicitly list 3 things this module does NOT handle.

Data Structures

Strictly defined via TypeScript interfaces/types. Types are contracts.

Failure Paths

List at least 3: Null inputs / Upstream timeouts / Invalid data formats, and expected behaviors for each.

Acceptance Criteria

Include runnable edge-case test suites.

When the specification is complete, generating the code becomes a deterministic execution rather than a creative gamble.

Pillar 2: Context Attachment via MCP (Model Context Protocol)

Specifications define what I say; MCP defines what the AI can access.

Debugging used to mean sifting through logs, SSHing into servers, querying DBs, and comparing environment variables manually.

Using MCP, I connect the AI directly to my local database, API inspection tools, and Git repositories. The AI evolves from a "conversational chatbot reading pasted code" into an agent equipped with real tools.

MCP Tool Integration

A typical investigation now looks like this:

AI Debugging & Refactoring Workflow

Me: Describe the issue.

AI: Checks logs, inspects codebase, traces logic, checks commit history, edits code, compiles, and runs tests.

Me: Inspect the diff, verify test results, merge.

Going from "spend hours investigating" to "spend 30 seconds reviewing" comes down to whether you embrace this paradigm shift.

Pillar 3: Automated Verification — Tests Are the Main Character

Without unit tests as a safety net, AI-generated code is a ticking time bomb.

Over the past six months, I've seen AI "working" code fail in production: an API that passed basic checks corrupted user records under concurrent requests, and a "cleaner" refactored module accidentally stripped out fallback logic for empty arrays.

AI excels at generating quickly, not anticipating comprehensively.

My job shifted to designing edge-case test suites, then handing them to the AI to iterate on until every test turns green:

  1. Nulls & Zeroes: null, undefined, 0, empty arrays/objects.
  2. Boundaries: First page, last page, max length limits, long strings.
  3. Concurrency: Simultaneous mutations on identical records, duplicate submissions.
  4. Failure Branches: Upstream 500 errors, timeouts, malformed payloads.
  5. Formatting: Date boundaries (month-end, leap years, time zones), floating-point precision.
  6. State Integrity: Duplicate calls, external state mutations mid-execution.

Phase 3: The Reality Check — What Didn't Go Smoothly

Moving completely away from editors isn't a silver bullet. If you plan to adopt this workflow, watch out for these traps:

Pitfall 1: Hidden Architectural Rot

AI favors local optima. Architecture requires global constraints. Left unchecked, AI will reinvent wheels across files—three different HTTP wrappers, duplicate helper logic, or conflicting constants.

My fix: Put architectural rules in a project convention file (CLAUDE.md / RULES.md).

  • All HTTP calls MUST go through src/lib/api. No custom wrappers.
  • Logging MUST use MLog. System console.log is strictly prohibited.
  • New modules MUST declare dependencies before implementation.

Pitfall 2: Hallucinated Dependencies & Security Risks

AI will happily introduce deprecated or insecure packages that sound plausible, or call outdated APIs that pass compilation but fail at runtime.

My fix: Never let AI decide dependencies autonomously.

  1. AI must provide registry links and version numbers for any new package.
  2. Enforce CI dependency audits (vulnerabilities & deprecation checks).
  3. Personally review security-sensitive code (Auth, Crypto, File I/O) line by line.

Pitfall 3: Context Drift in Long Sessions

In short sessions, AI is obedient. In 2-hour multi-turn conversations, it starts drifting—forgetting constraints set in turn 3 or refactoring code to match its own preferences.

My fix: Keep sessions short and modular. One task per session. Re-state key constraints at the start of a prompt, and reset the context as soon as the agent strays.

Pitfall 4: Code Review Costs Skyrocket

When an AI modifies 1,000 lines in seconds, how much can you actually review?

If you can't review it, you are blindly accepting it. Review test coverage first, inspect deleted logic second, and review new lines last.


Final Thoughts

AI hasn't eliminated programmers, but it has made purely mechanical coding obsolete.

Your value as an architect, your understanding of underlying protocols, and your ability to anticipate system failures matter more than ever before.

How long has it been since you last opened your code editor? Feel free to share your current workflow in the comments!

Top comments (2)

Collapse
 
mythex profile image
Mythex •

"Inspect deleted logic second" deserves to be first, in my experience. Your empty-array example is the typical shape: an agent "cleans up" a branch it doesn't see a reason for, the tests still pass because nobody wrote a test for that branch, and the reason only shows up in production.

Two things that made deletions reviewable for us:

  1. Ask the agent to end every change with a short list of what it removed or changed in behaviour, one line each, with why. Additions are easy to spot in a diff; a missing if is not.
  2. When a removed branch turns out to have mattered, the fix includes a test for it and a one-line comment saying why it exists. The comment is what stops the next session from removing it again, because the agent reads it as a constraint instead of clutter.

Agree on short sessions too. One task per session is the single biggest quality jump I've seen.

Collapse
 
shanhan_dev profile image
shan han •

Thanks @mythex! Adding the inline comment as a hard constraint to prevent the agent from re-deleting logic in future sessions is brilliant. I’m definitely adopting that into my workflow!