Skip to content

AI Copilot in VS Code: Tips for Using Claude Sonnet 4 Effectively

by Roman Semko

I have a bit of a love-hate relationship with coding agents like Claude Sonnet 4. On one hand they really make life easier. They generate boilerplate, wire up standard patterns and generally take care of work that is not very interesting but has to be done anyway. On the other hand it's like always driving with GPS: slowly you lose your own sense of direction. If you rely on the AI too much, you get less sharp as a developer over time.

But there is another side. Used with some thought, an AI assistant clears away a lot of routine work and frees your attention for the parts that really need design and judgement. Going from assembly to C, and later from C++ to Python, already moved us up the abstraction ladder, so we could think more about what we build and less about every detail of how to express it. Prompting an AI is just one more step in this direction. You still talk to a machine, only more indirect and less deterministic.

In the end programmers use languages to shape logic, and prompting is one more language you can learn. The real questions are when it makes sense to use it, when you better write the code yourself, and how to phrase your requests so the output is actually useful.

After a few months with Claude Sonnet 4 as a kind of pair programmer in VS Code, I settled into some habits that work reasonably well for me.

1. Boilerplate yes, tricky core no

These models are very good at standard patterns and boilerplate, so this is where I let them do most of the work. A basic Node.js REST API skeleton, a simple React component, some standard config file. Problems that are well known and where the space of reasonable solutions is narrow.

With logic that is unusual, subtle or central for the design I am much more careful. If the task needs real understanding of the domain or some non-obvious reasoning, I mostly write this part myself. Models sound very confident even when they are slightly off, and that's exactly what you don't want in the core of your system.

So the AI helps with the routine layers of the code. The key ideas stay mine.

2. Let it write tests, and run them

A habit that helped a lot: ask the AI to generate tests for any code it just wrote, and then really run them right away.

It happens all the time that the AI returns code which looks fine on first look but has small mistakes or misses some edge cases. When you run unit tests immediately, you get a quick signal what is wrong. You feed that back into the next prompt and the model fixes its own output.

If you pay per request, there is an extra benefit. When "write the code" and "write and run the tests" happen in one interaction, you save round trips. Less waiting, less cost and in the end you have tested code and not only plausible-looking code.

3. Small files, simple solutions

Left alone, an AI overcomplicates things easily. If you keep asking for tweaks and additions in the same file, it slowly grows into a long, tangled thing nobody wants to read.

So I set some informal limits. I ask Claude to keep single files below roughly 300-350 lines and to avoid elaborate designs unless they are clearly needed. After the first version I often follow up with something like "please refactor this to be simpler and more concise" or "remove duplication and make the logic clearer".

Pushing DRY (don't repeat yourself) in the prompts helps to keep things from sprawling. Smaller, focused files are easier to understand for humans, and they seem to work better with the model's context too. From my experience very long files make the model lose track of details, or it gets slow because it tries to consider everything at once. Modest, well separated modules give faster and more reliable answers.

4. Documentation together with the code

Another useful habit is to ask the AI to document what it does. Inline comments, a short explanation block at the top of the file, or a small usage example in a docstring or a markdown section.

Good documentation helps you to understand the code later without figuring out everything again. And it helps with future prompts: when you come back the next day and want Claude to extend or change the code, the explanations give the model immediate context about intent and assumptions.

So comments and docstrings are kind of a bridge between your understanding and how the AI interprets the code. Human colleagues working on the same codebase will thank you as well.

5. Control what gets created

Claude, like many AI assistants, is sometimes a bit too eager to help. You ask it to explore an idea or debug something and suddenly there are extra files: scratch scripts, notebooks, temporary helpers, pieces of READMEs you never asked for.

Sometimes they are useful for a moment. But if you just leave them there, the project slowly fills up with half-finished stuff. To keep it tidy I say explicitly in my instructions that the AI should only create new files when I ask, and that temporary artifacts get removed afterwards or are clearly marked as disposable.

When I see that a throwaway file was created anyway, I delete it and mention in the next prompt that we focus on the main project files. Over time the repository stays cleaner, and the risk is smaller that somebody later takes experimental code for production code.

6. Clear prompts and iterations

How you talk to the AI matters a lot. Vague requests give vague results. I try to be specific about the task, the constraints and what I expect. If the first answer is not close to what I had in mind, I treat it as a draft and refine the request.

Often it works better to split a complex task in stages. First ask for an outline or a high level plan, then for the implementation of just one part, and only later for refactoring and tests. Pretty much how you would work with a junior developer: first agree on the approach, then go into details.

Over time you get a feeling which phrases and patterns give the most reliable output. And prompting feels less like "talking to a black box" and more like giving structured instructions to a teammate who is very fast but sometimes careless.

A shared instructions file

To make this more consistent, I started to add a small instructions file for Claude to every repository, for example .github/instructions.md, which describes how I want the assistant to behave in this project.

Usually it contains the principles above: focus on boilerplate and standard patterns, keep files small and simple, write and run tests, document the code, don't create unnecessary files etc. Then I adjust the details depending on language, framework or domain.

With the rules written down, the AI has a stable reference point, and it also reminds me how I want to use it. What started as ad-hoc tricks in one project becomes something I can reuse in many.

Example:

- Focus on implementing well-known patterns and boilerplate. Avoid tackling very niche or complex domain logic without
  explicit guidance.
- Whenever you generate code for a feature, also write corresponding unit tests and execute them to verify the code
  works as intended.
- Keep each file short (around 300 lines max) and avoid repetition. If a solution starts getting too long or complex,
  refactor and simplify it.
- Do a few passes of simplification of any final code you produce. Aim for clarity and conciseness while not
  compromising on the requested functionality.
- Write clear comments and documentation for any code you produce. This helps clarify the code's purpose for both humans
  and future AI prompts.
- Do not create additional files or artifacts unless explicitly asked. Avoid littering the project with extra scripts,
  notebooks, or READMEs that were not requested.

For new projects I also add:

- Do not make the code backwards-compatible. Make sure the rest of the code knows the interface of the new code, but do
  not worry about support of deprecated features.
- Do not worry about support of different major versions of dependencies. Use the latest stable versions.

Happy coding!